Coco

The mandate

What the agent is for, the ceilings it works inside, which contract sets load, and where the gate looks to find out how far the work has got.

The mandate

A mandate is not an identity document. It does not say who the agent is, it says what the organisation has allowed it to do. The contracts carry the rules and the mandate carries the things those rules compare against.

id: coco.developer
description: >
  A coding agent working in Claude Code on one machine. Ordinary work runs
  untouched, a credential read asks first, a destructive command stops, and a
  session that has read a secret cannot then send data off the machine.

status: active
unknown_tool: BLOCK
escalate_fallback: deny

limits:
  max_files_written: 40

packs:
  - baseline
  - session

The kill switch

Set status to anything other than active and every call stops, before a single contract is loaded. Revocation is one field, and it is checked first for exactly that reason.

Who can pull it is whoever can write the mandate file, so on a fleet the mandate belongs with the managed configuration rather than in a developer's home directory, and in a container it is baked into the image, so pulling it there is a redeploy or a mode change.

unknown_tool

What happens to a tool the gate does not recognise. BLOCK is the honest default, because an action nobody wrote a contract for has not been authorised, and it means a new tool arriving in a runtime release is denied until someone decides about it.

Setting it to ALLOW is a real choice with a real cost, and the receipt records which way it went.

escalate_fallback

What happens to an ESCALATE that cannot reach a person, because the session is running in a permission mode that never prompts. deny is the only answer that keeps an escalation meaningful, and the receipt says what actually happened rather than recording an escalation nobody could have answered.

limits

Ceilings the contracts compare against. Every field here is readable as mandate.<name>.

limits:
  max_files_written: 40

Set these from your own history rather than from the file that shipped. Start high, read coco report, bring them down. A ceiling copied out of an example is a ceiling nobody will defend when it blocks something.

packs

Which contract sets load, by directory name.

A set can sit in ~/.coco/packs/ unenforced until the mandate names it, which is the mechanism for staging a set you are not ready to run.

The npx install seeds baseline and session and names both. The KYC and payments sets are in the repository rather than the npm package, because neither has the state it reads on a developer's machine, and adding a set is copying its directory in and naming it here.

Pointing the gate at your workflow

case_state is what makes a verdict depend on where the work has got to.

case_state:
  root: KYC_Cases
  depth: 3
  markers:
    step0_report: "00_Step0_Verification/Step0_Report.*"
    step0_screenshots: "00_Step0_Verification/Screenshots/*.png"
    screening_sanctions: "01_Screening/Sanctions_*.pdf"

root is where cases live, absolute or relative to the working directory. depth is how many folders below that identify one case, so a case at KYC_Cases/2026/03_March/Smith_Jane_20260312 is depth 3. Every marker is a glob, and its existence becomes a boolean a contract can read, with a count and a size beside it.

The gate resolves the case from the path the call is writing to, so a write into one customer's folder is judged against that customer's evidence and nobody else's.

Every marker is a file whose existence is the fact, which means a compliance officer can point at the folder and see why the gate decided as it did.

Get this right and the rules stop being about tool names and start being about the work. Get it wrong and case.present is false, which is why contracts that read case state should check case.present in a pre-condition first.

More than one mandate

One mandate governs one deployment. A coding agent on a machine and a payments agent on a platform have different ceilings, different state and different contracts, so they get different mandates.

The three examples in the repository are worth reading side by side. packs/mandate.default.yaml governs a coding agent and reads nothing but the session, and it is the one the installer seeds. packs/mandate.kyc.yaml adds case_state and points at a case folder. packs/mandate.x402.yaml sets payment ceilings and expects a ledger snapshot from the platform.

A receipt names the mandate it was decided under, so an auditor can tie a decision back to the contract that governed it. Change a limit as a new version rather than editing in place.

On this page