It retried, and you still have one company
A create with a stable idempotency key returns the original result, marked as a replay. Reusing that key for materially different input is refused rather than silently applied.
For agents
An agent operating a CRM fails differently than a person does. It times out and tries again. It runs beside itself. It reads a record, thinks, and writes back against state that moved underneath it. A CRM built for someone typing turns all three into duplicates and lost edits.
Safe by default
A create with a stable idempotency key returns the original result, marked as a replay. Reusing that key for materially different input is refused rather than silently applied.
Supply the version you read and a conflicting write is refused with the current version, so the agent re-reads and reapplies instead of burying a human correction.
Every operation that writes a CRM record takes a dry-run flag and returns the diff it would make without committing, on the API and the tools alike. Control-plane calls that create a workspace, mint a credential, or open billing do not: there is no diff to show for an act whose whole effect is outside the workspace.
A fixed set of error codes, each carrying a recovery hint written for an agent rather than a log reader, plus the structured detail that makes the recovery possible: the candidates, the current version, the valid stages.
One call to learn everything
Every workspace starts with the same model: companies, contacts, opportunities, interactions, tasks, and pipelines, with the same field meanings everywhere.
An agent calls get_crm_schema once and knows the objects,
the pipelines, the custom fields, its own permissions, the workspace
timezone and default currency, what each object type can be filtered
and sorted on, and every stated limit. There is nothing to probe for
and nothing to special-case, so one integration works against every
workspace rather than every workspace needing its own.
The canonical types cannot be redefined, so an agent that has operated one Indraft workspace can operate yours without being taught what a company is. A workspace can define object types of its own beside them, and the schema says which is which, so the agent reads one call and knows both.
Identity
A zero-maintenance CRM fails in exactly two ways: the agent creates duplicates, or it merges the wrong two people. Fuzzy matching trades the first for the second, and the second is worse because it is silent.
Indraft matches on real identity evidence only, a normalized domain or email. Name similarity matches nothing. An uncertain upsert returns the candidates and writes nothing at all.
Next
Connect over MCP or call the REST API from your own service. Both reach the same objects through the same rules.
Every error code, limit, and matching rule is published and generated from the running API, so an agent looks up what it is allowed to do instead of discovering it by failing.