People, contacts & companies
Halyard distinguishes two kinds of people. A User is an authenticated member of your organization — sacred, identity-bearing, the people who sign in and whose work is attributed. A Contact is everyone else — external people you talk about, work with, or capture knowledge about. The split matters because internal identity carries permissions and attribution, while external people are just records in the graph. But both end up as canonical person records you can search and link.
User vs Contact
Section titled “User vs Contact”| User | Contact | |
|---|---|---|
| Who | Internal org member | External person |
| Authenticates? | Yes — signs in, has an accessRole | No |
| Can be an expert? | Yes — routing target | No |
| Represented in the graph as | A paired CONTACT knowledge entry | A CONTACT knowledge entry |
The User is the authenticated account. The CONTACT entry is its representation in the knowledge graph. They are not the same object — one is identity, the other is memory.
Every person is a CONTACT entry
Section titled “Every person is a CONTACT entry”The canonical person record in the knowledge graph is a CONTACT knowledge entry — one of the six entry types. Every internal user has a paired CONTACT entry as their record, and every external person you capture is also a CONTACT entry. This means people are first-class in the graph: a contact can carry relations, be referenced by other entries, and be linked to a company, exactly like any other knowledge.
Because the canonical record is a single entry type, “who is this person?” is a knowledge question with one shape — whether the person is on the team or not.
Companies and the WORKS_AT relation
Section titled “Companies and the WORKS_AT relation”Companies follow the same pattern. A company is a COMPANY knowledge entry, and a person is linked to it through the WORKS_AT relation:
CONTACT (person) --WORKS_AT--> COMPANY (org)This is structure emerging from links rather than a separate table or a foreign key (principle P4). To know where someone works, you follow the WORKS_AT relation out from their contact entry with explore_knowledge.
The tools
Section titled “The tools”| Tool | Use |
|---|---|
search_people(query, limit?) | Find a person by name or fuzzy match |
find_person_by_email(email) | Look up a contact by exact email |
upsert_person(email, displayName?, …) | Create or update a contact (email is the key) |
upsert_company(name, domain?, …) | Create or update a company record |
upsert_person keys on email — call it again with the same email to update rather than duplicate. upsert_company keys on name. Both are idempotent by design, so an agent can record a person or company it encounters mid-work without first checking whether it already exists.
In practice
Section titled “In practice”- Capture what you learn — recording people and companies as you encounter them.
- Knowledge entries & the graph —
CONTACT/COMPANYentry types and theWORKS_ATrelation. - Experts & routing — how internal users become routing targets.
- Tool reference —
search_people,upsert_person,find_person_by_email,upsert_companysignatures.