Guides · 4 min read
Set up a CRM in Known
Set up a CRM your team and agents keep together: contacts and organizations once, interactions, and a pipeline, with the rules that keep records clean.
This guide sets up a CRM your team and your agents keep together: people and organizations once, the meetings and messages with them, and where each relationship stands. It's the model we use for Known's own fundraise and partnerships.
You need a Known organization and the known CLI, or an agent connected to Known. The examples use the organization acme.
The model
| Table | One record is | Key |
|---|---|---|
people:contacts |
A person: who they are and how to reach them | jo-park |
people:organizations |
A company, fund or firm | northwind |
sales:interactions |
One event: a call, a meeting, a message | jo-park:2026-10-14:call:1 |
sales:pipeline |
Where one relationship stands now, and the next step | jo-park |
Two wikis, on purpose. people is the one directory the whole company shares; every other wiki links to it. sales holds what your sales team does with those people. A hiring or a fundraising wiki would link to the same contacts.
1. Create the directory
known acme wiki create people --description "Everyone we know: who they are and how to reach them. One record each; other wikis link here."
known acme wiki write people:contacts --title "Contacts" --text "One record per person."
known acme wiki write people:organizations --title "Organizations" --text "One record per company."
Then a schema for each. The contact schema, as contacts.json:
{
"key": "id",
"schema": {
"type": "object",
"required": ["id", "name"],
"properties": {
"id": { "type": "string", "description": "Name in lowercase with hyphens, e.g. jo-park." },
"name": { "type": "string", "description": "Full name, spelled the way the person spells it." },
"current_role": { "type": ["string", "null"], "description": "Title and organization. null if unknown." },
"email": { "type": ["string", "null"] },
"linkedin": { "type": ["string", "null"] },
"organizations": { "type": "array", "items": { "type": "string", "pattern": "^\\[\\[organizations/[^\\]|]+\\]\\]$" }, "description": "Links to their organizations. Each lists this contact back." },
"content": { "type": ["string", "null"], "description": "A few plain sentences: who they are and how we know them." }
},
"additionalProperties": false
}
}
known acme wiki meta people:contacts --file contacts.json
Organizations follow the same pattern, with name, website, type and a contacts list of links back.
2. Create the sales tables
An interaction is one event. Its schema, as interactions.json:
{
"key": "id",
"schema": {
"type": "object",
"required": ["id", "people", "type", "summary"],
"properties": {
"id": { "type": "string", "description": "<main-contact>:<YYYY-MM-DD>:<type>:<n>." },
"people": { "type": "array", "minItems": 1, "items": { "type": "string", "pattern": "^\\[\\[people:contacts/[^\\]|]+\\]\\]$" }, "description": "Everyone confirmed who took part, main contact first." },
"organizations": { "type": "array", "items": { "type": "string", "pattern": "^\\[\\[people:organizations/[^\\]|]+\\]\\]$" } },
"occurred_at": { "type": ["string", "null"], "description": "Date of the event. null if unknown; never guessed." },
"type": { "enum": ["call", "meeting", "message", "introduction", "other"] },
"summary": { "type": "string", "description": "What was said or agreed, and the next step. No facts about the person." },
"content": { "type": ["string", "null"], "description": "Notes, or the message quoted word for word." }
},
"additionalProperties": false
}
}
The pipeline table holds person (a link), stage, last_touch, next_action and next_action_due.
3. Write the rules on the pages
Agents read a table's page before writing to it. These rules, on the right pages, prevent most bad records:
- Search before you create. Look for the person by name, other spellings and email. Update the record that exists.
- Facts about a person go on their contact. Role, email, LinkedIn and background never go on an interaction.
- One event is one interaction. A LinkedIn profile or a directory entry is not an interaction.
- Only confirmed people go in
people. If you're not sure who attended, name them incontentand leave them out of the links. - Unknown is
null. Don't guess a date, a role or a company. - After an interaction, update the pipeline:
last_touch,stage,next_action.
4. Use it
From a chat with your agent:
"I had coffee with Jo Park from Northwind today. They're moving their support team to agents next quarter and want a demo in two weeks."
The agent finds Jo's contact, writes one interaction linked to Jo and Northwind, sets the pipeline's next action to the demo, and adds a due date. If Jo has no contact yet, it creates one first.
To see where things stand, open sales:pipeline in your browser: a table you can sort and filter. To see everything about Jo, open her contact: its backlinks list every interaction and pipeline record that links to her.
What Known doesn't do
Known doesn't sync your email or calendar, record calls, or enrich contacts from outside data. Interactions come from people and agents writing them, which is also why they say what was decided, not just that an email was sent. If you need inbox sync and sequences, a dedicated CRM does those; see Known vs HubSpot and Known vs Attio.