YOUR ONTOLOGY.
VERSIONED LIKE CODE.
CMP42 ships with sensible defaults for the CRM primitives — contact, company, deal, task, activity. Then you extend: in TypeScript-shaped YAML, in git, migrated with a single command, validated at write-time. Your ontology is a first-class product artefact, not a hidden Salesforce setting.
THE SCHEMA IS THE PRODUCT.
In most CRMs the data model lives behind three tabs in an admin settings screen, owned by an ops team you never see. Fields accumulate over years. Nobody remembers which ones are still filled in, which pipeline stage replaced which, or why there are four “industry” fields on a company.
Humans cope with that — they skip what they do not understand. Agents do not. To an agent, every declared field is a claim that the field means something, and every empty one is an invitation to guess. A schema nobody owns is a schema an agent will hallucinate into.
CMP42 treats the model as code. It lives in files, in git, next to everything else your team reviews. Changes are diffs. Migrations are one command. And the agents in production are never surprised by a schema that changed underneath them.
LEAN DEFAULTS.
EXPLICIT EXTENSION.
Defaults are lean. Extension is explicit. If a field is not on your ontology, it is not on your contact. Silence is a feature.
That is not minimalism for its own sake. For an agent, a field that does not exist is an honest answer; a field that exists but is empty looks like missing data it should fill in. Every field you add should be one you are prepared to define, keep populated and let an agent write to.
So CMP42 starts with the five primitives every CRM needs and nothing else. Anything specific to your business — an engagement, a retainer, a playbook, a renewal date — you declare yourself, where your team can see it.
| Default primitive | What it stands for |
|---|---|
contact | A person you work with. Knows a company, owns a deal, authored a doc. |
company | An organisation you work with or sell to. |
deal | An opportunity moving through the stages you declare. |
task | Something a human or an agent has to do. |
activity | Something that happened — a call, a meeting, a note. |
The exact default fields per primitive are finalised during the Alpha, together with the Design Partners.
FOUR PROPERTIES OF A MODEL.
Declarative model files
Models are declared in TypeScript-shaped YAML and versioned in git. Review an ontology change like a pull request, see who changed what and when, roll back like any other commit.
Validated at write-time
Every write is checked against the model before it lands in the graph. Errors are clear and specific, so an agent that sends the wrong value learns what is allowed and corrects itself instead of inventing a workaround.
Backwards-compatible migrations
A single command migrates your models. Migrations are backwards-compatible, so the agents and integrations already running in production do not meet a schema surprise.
MCP tools per model
Every model type automatically becomes a set of MCP tools — get_contact, list_deals_at_stage, write_note_on_company — that any MCP-compliant client can consume.
A FILE, NOT A SETTINGS PAGE.
The example below illustrates the idea for a boutique consultancy that tracks client engagements. It declares one new model with typed fields and named edges into the default primitives, and adds one optional field to the default deal.
One command applies the change and regenerates the tools agents see. If an agent later writes a value the model does not allow, it gets an error it can act on.
The syntax shown is illustrative. The concrete model format ships with the Alpha and is shaped together with the Design Partners.
# A custom model, declared next to your code
model: Engagement
fields:
title: string # required
stage: "scoping" | "active" | "closed"
started_on: date? # optional
budget_eur: number?
edges:
client: -> Company # engagement is for a company
lead: -> Contact # who runs it
playbook: -> Doc? # the framework it follows
# Extend a default primitive — explicitly
extend: Deal
fields:
renewal_date: date?$ cmp42 migrate
+ model Engagement new
+ field Deal.renewal_date optional · backwards-compatible
✓ tools get_engagement, list_engagements_at_stage,
write_note_on_engagement
✓ migration applied✕ Engagement.stage
got: "in progress"
expected: "scoping" | "active" | "closed"
→ retry with stage: "active" ✓ written · v2NO SCHEMA SURPRISE IN PRODUCTION.
An agent in production has learned the shape of your data: which tools exist, which fields they take, which values are valid. Change that shape carelessly and the agent does not throw an error you can see — it quietly starts doing the wrong thing.
That is why CMP42 migrations are backwards-compatible. Adding a model, an optional field or a new edge extends what agents can do without breaking what they already do. Identities are content-addressable and stay stable across schema evolution, so references held by an agent or an integration survive a migration.
Because models live in git, the history of your ontology is the history of your repository: every change reviewed, attributable and reversible.
EVERY MODEL BECOMES TOOLS.
You never hand-write an MCP server for your CRM. When a model is migrated, CMP42 generates the matching tools — for the defaults and for everything you declare yourself. Add Engagement and your agent can ask for engagements, filter them by stage and write notes on them, with inputs typed by the model you wrote.
The same operations are available through REST and GraphQL for clients that do not speak MCP, with the same auth and the same audit trail. See the MCP tool surface →