Contacts
A contact is one person the business deals with: a client, a lead, a supplier. All the owner’s agents share one list, so a contact Client desk adds is there for Bookkeeper too.
A contact holds:
- Fields: name, emails, phone, job title, labels, and named
fieldssuch asbirthday. - Context: what everyone should know before writing to them, such as “Prefers a call to email; signs off quotes herself.” Set it with
contextand say why. - Open items: who owes the next move.
you(the business owes them),them(they owe the business), or afollow_upat a time, which wakes the agent that set it. - Log: dated notes and every change, newest first. Changes to a contact show on its log, not on Home.
- Companies and projects: where they work, with a role, and the projects they’re part of. Companies have their own page.
Before you write to someone, find their address and read their Context.
How to use it
Section titled “How to use it”What find_tools sends with these tools, word for word:
The people the business deals with, shared by all the owner’s agents. Add and update the ones your work touches on your own judgement: no yes is needed, and every change can be undone. Use add_many for several at once; to fill Contacts from mail, search mail the owner sent (dir sent, bulk false): its counts.people says who they write to most; read their latest messages for names, roles and phones, then save them. Read someone’s Context with find before you write to them. The businesses they work at are in companies.
| Tool | What it does | Owner’s yes |
|---|---|---|
| contacts.list | Compact contacts; company is a name or id | No |
| contacts.find | The contact with that address, their Context, company Context and open items, or null | No |
| contacts.read | Fields, Context, open items, newest 20 log entries, companies and projects | No |
| contacts.timeline | Live mail threads and meetings this agent may read | No |
| contacts.create | Add a contact | No |
| contacts.add_many | Add up to 200 people at once; company is a name (the workspace’s own, made if new). Addresses already on a contact are reported, not added twice | No |
| contacts.update | Change fields and labels | Checked |
| contacts.context | Set Context and record why it changed; can be undone | Checked |
| contacts.note | Add a dated note | No |
| contacts.follow_up | Add a follow-up for this agent; at is an ISO date and time | No |
| contacts.link_project | Link a contact to a project | No |
contacts.list · Compact contacts; company is a name or id.
Owner’s yes: No. Nothing of the owner’s changes.
| Input | Type | Required | Limits |
|---|---|---|---|
label |
text | no | 1–40 characters |
company |
text | no | 1–200 characters |
query |
text | no | up to 200 characters |
open |
one of you, them, follow_up |
no | |
quietDays |
whole number | no | 0 or more |
offset |
whole number | no | 0 or more |
Returns:
{ items: { id: string; name: string; company: string | null; labels: string[]; last: ContactLast; open: { id: string; kind: "you" | "them" | "follow_up"; text: string; at: string; thread?: string; link?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; } | null; }[]; nextOffset: number | null; total: number;}contacts.find · The contact with that address, their Context, company Context and open items, or null.
Owner’s yes: No. Nothing of the owner’s changes.
| Input | Type | Required | Limits |
|---|---|---|---|
email |
text | yes |
Returns:
{ companies: { context: string | null; id: string; name: string; ticker: string | null; handle: string; role?: string | null; since?: string | null; ended?: string | null; labels?: string[]; }[]; id: string; organizationId: string; name: string; emails: string[]; phone: string | null; jobTitle: string | null; labels: string[]; context: string | null; open: { id: string; kind: "you" | "them" | "follow_up"; text: string; at: string; thread?: string; link?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; }[]; last: ContactLast; fields: ContactFreeFields; status: "active" | "suggested" | "ignored"; projects: ProjectRef[]; createdAt: string; updatedAt: string;} | nullcontacts.read · Fields, Context, open items, newest 20 log entries, companies and projects.
Owner’s yes: No. Nothing of the owner’s changes.
| Input | Type | Required | Limits |
|---|---|---|---|
contactId |
id | yes |
Returns:
{ log: { id: string; at: string; by: { kind: "agent" | "user" | "system"; id: string; }; kind: "removed" | "note" | "ask" | "context" | "labels" | "created" | "sent" | "drafted" | "triage" | "looked" | "merged" | "restored"; text?: string; before?: string | string[] | null; after?: string | string[] | null; why?: string; subject?: string; to?: string[]; thread?: string; link?: string; hold?: number; sentAt?: string; approval?: { kind: "rule" | "allowed" | "waiting" | "yes" | "undone" | "declined"; at?: string; rule?: string; }; }[]; id: string; organizationId: string; name: string; emails: string[]; phone: string | null; jobTitle: string | null; labels: string[]; context: string | null; open: { id: string; kind: "you" | "them" | "follow_up"; text: string; at: string; thread?: string; link?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; }[]; last: ContactLast; fields: ContactFreeFields; status: "active" | "suggested" | "ignored"; companies: CompanyRef[]; projects: ProjectRef[]; createdAt: string; updatedAt: string;}timeline
Section titled “timeline”contacts.timeline · Live mail threads and meetings this agent may read.
Owner’s yes: No. Nothing of the owner’s changes.
| Input | Type | Required | Limits |
|---|---|---|---|
contactId |
id | yes | |
limit |
whole number | no | 1–100, default 20 |
Returns:
{ items: ContactTimelineItem[]; failures: Failure[];}create
Section titled “create”contacts.create · Add a contact.
Owner’s yes: No. It makes something new.
Your work: listed on Home.
| Input | Type | Required | Limits |
|---|---|---|---|
name |
text | yes | 1–200 characters |
emails |
list of text | no | each up to 254 characters |
phone |
text or null | no | up to 80 characters |
jobTitle |
text or null | no | up to 200 characters |
labels |
list of text | no | each 1–40 characters |
companyIds |
list of id | no | |
fields |
named values of anything | no | default {} |
Returns:
ContactRecord | { id: unknown; message: string;}add_many
Section titled “add_many”contacts.add_many · Add up to 200 people at once; company is a name (the workspace’s own, made if new). Addresses already on a contact are reported, not added twice.
Owner’s yes: No. It makes something new.
Your work: listed on Home.
| Input | Type | Required | Limits |
|---|---|---|---|
people |
list of named values of anything | yes | 1–200 items |
Returns:
{ added: { id: string; name: string; }[]; existing: { id: string; name: string; email: string; }[]; invalid: { row: number; name: string | null; error: string; }[];}update
Section titled “update”contacts.update · Change fields and labels.
Owner’s yes: Checked. It changes what’s there.
Your work: not listed on Home; the change shows on the record itself.
| Input | Type | Required | Limits |
|---|---|---|---|
contactId |
id | yes | |
name |
text | no | 1–200 characters |
emails |
list of text | no | each up to 254 characters |
phone |
text or null | no | up to 80 characters |
jobTitle |
text or null | no | up to 200 characters |
labels |
list of text | no | each 1–40 characters |
fields |
named values of anything | no |
Returns:
{ id: string; organizationId: string; name: string; emails: string[]; phone: string | null; jobTitle: string | null; labels: string[]; context: string | null; open: { id: string; kind: "you" | "them" | "follow_up"; text: string; at: string; thread?: string; link?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; }[]; last: ContactLast; fields: ContactFreeFields; status: "active" | "suggested" | "ignored"; companies: CompanyRef[]; projects: ProjectRef[]; createdAt: string; updatedAt: string;}context
Section titled “context”contacts.context · Set Context and record why it changed; can be undone.
Owner’s yes: Checked. It changes what’s there.
Your work: listed on Home, with Undo.
| Input | Type | Required | Limits |
|---|---|---|---|
contactId |
id | yes | |
text |
text | yes | up to 1,500 characters |
why |
text | yes | 1–2,000 characters |
Returns:
{ contact: ContactRecord; entryId: string;}contacts.note · Add a dated note.
Owner’s yes: No. It makes something new.
Your work: not listed on Home; the change shows on the record itself.
| Input | Type | Required | Limits |
|---|---|---|---|
contactId |
id | yes | |
text |
text | yes | 1–2,000 characters |
Returns:
{ id: string; at: string; by: { kind: "agent" | "user" | "system"; id: string; }; kind: "removed" | "note" | "ask" | "context" | "labels" | "created" | "sent" | "drafted" | "triage" | "looked" | "merged" | "restored"; text?: string; before?: string | string[] | null; after?: string | string[] | null; why?: string; subject?: string; to?: string[]; thread?: string; link?: string; hold?: number; sentAt?: string; approval?: { kind: "rule" | "allowed" | "waiting" | "yes" | "undone" | "declined"; at?: string; rule?: string; };}follow_up
Section titled “follow_up”contacts.follow_up · Add a follow-up for this agent; at is an ISO date and time.
Owner’s yes: No. It makes something new.
Your work: not listed on Home; the change shows on the record itself.
| Input | Type | Required | Limits |
|---|---|---|---|
contactId |
id | yes | |
text |
text | yes | 1–2,000 characters |
at |
date and time (ISO 8601) | yes |
Returns:
{ id: string; organizationId: string; name: string; emails: string[]; phone: string | null; jobTitle: string | null; labels: string[]; context: string | null; open: { id: string; kind: "you" | "them" | "follow_up"; text: string; at: string; thread?: string; link?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; }[]; last: ContactLast; fields: ContactFreeFields; status: "active" | "suggested" | "ignored"; companies: CompanyRef[]; projects: ProjectRef[]; createdAt: string; updatedAt: string;}link_project
Section titled “link_project”contacts.link_project · Link a contact to a project.
Owner’s yes: No. It makes something new.
Your work: not listed on Home; the change shows on the record itself.
| Input | Type | Required | Limits |
|---|---|---|---|
contactId |
id | yes | |
projectId |
id | yes |
Returns:
{ projectId: string; contactId: string;}Named types in the results above.
type ContactLast = { first?: string; at?: string; channel?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; members?: Record<string, string>; agents?: Record<string, string>;}
type ContactFreeFields = Record<string, unknown> & { ask?: boolean; source?: string; addedBy?: { kind: "agent" | "user" | "system"; id: string; }; notDuplicate?: string[];}
type ProjectRef = { id: string; name: string;}
type CompanyRef = { id: string; name: string; ticker: string | null; handle: string; role?: string | null; since?: string | null; ended?: string | null; labels?: string[];}
type ContactTimelineItem = { kind: "mail" | "meeting"; id: string; title: string; at: string; direction?: "out" | "in"; from?: string; snippet?: string; url?: string; attendees?: string[];}
type Failure = { source: string; kind: "not_connected" | "reauth" | "forbidden" | "not_found" | "rate_limited" | "unavailable" | "too_large" | "unsupported" | "bad_input" | "vendor" | "changed" | "unknown_outcome"; message: string; integration: string; connection: string;}
type ContactRecord = { id: string; organizationId: string; name: string; emails: string[]; phone: string | null; jobTitle: string | null; labels: string[]; context: string | null; open: { id: string; kind: "you" | "them" | "follow_up"; text: string; at: string; thread?: string; link?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; }[]; last: { first?: string; at?: string; channel?: string; by?: { kind: "agent" | "user" | "system"; id: string; }; members?: Record<string, string>; agents?: Record<string, string>; }; fields: Record<string, unknown> & { ask?: boolean; source?: string; addedBy?: { kind: "agent" | "user" | "system"; id: string; }; notDuplicate?: string[]; }; status: "active" | "suggested" | "ignored"; companies: CompanyRef[]; projects: ProjectRef[]; createdAt: string; updatedAt: string;}