Coco

Questions

The questions people actually ask, answered short enough to send and specific enough to survive a follow-up.

Questions

Answers short enough to send. Each one holds up if the person asking follows up, which is the only test that matters.

Anything Coco has not built yet is marked. Anything measured names the command that reproduces it.

Should we take npx or the SDK

Whichever matches where the agent runs. npx if the runtime has hooks, Claude Code and Cursor among them, the SDK otherwise, and both if you have both.

npx is a hook on the machine, so nothing leaves it, there is no service to keep running and there is no network call on the decision path. Its weakness is that anyone who can edit their own settings file can remove the hook, which is why a fleet deployment uses managed settings.

The SDK is one call in your harness against a gate that runs as a service. It covers every runtime that is not Claude Code, and it costs you a network hop and an availability dependency. With enforcement on, an unreachable gate stops your agents, because an unanswered check is not an allow.

Both run the same gate file against the same contracts and write the same receipt shape, so the choice is about deployment rather than about what gets enforced. Architecture has the comparison in full.

How is it actually enforced

At the execution layer, not the prompt layer.

Inside Claude Code, Coco installs a PreToolUse hook. The hook is a process that runs before any tool call executes, on every tool call. It receives the tool name and its arguments, evaluates them against a contract and the session's own history, and answers allow, deny or ask. A deny stops the call.

In any other runtime the same gate runs as a service and the harness calls it at the seam that executes tool calls.

The model is not consulted and cannot participate. The check runs outside the agent, after the model has finished deciding what it wants to do and before anything happens.

Nothing here depends on a system prompt, a project instruction file or a rule written in markdown the model reads. Those shape what an agent tries. They do not decide what runs.

That distinction is the whole product. An instruction is a request the model can reason its way past when the context gets long or the case looks unusual. A hook is a return code.

Is the policy a markdown file the model reads

No. The model never sees it.

Contracts are YAML compiled to JSON at install. The gate reads them, and the agent has no access to them and is not told what they say.

Rules take comparisons, boolean operators and arithmetic. No function calls, no arbitrary code. That limit is deliberate, because a rule an auditor cannot read is a rule nobody can defend in an audit.

A compliance officer can read a contract and say whether it matches the policy. That is the test the format was designed against.

One clarification, because a later page mentions a model. A model can help draft a contract from your policy documents, once, at authoring time, and a person approves what it wrote. At runtime no model is anywhere near the decision, and the agent being governed never sees the contract either way.

id: kyc.step0_before_risk
applies_when: '"02_Risk_Assessment" in tool.path'
constraints:
  - id: five_independent_searches
    rule: case.step0_screenshots_count >= 5
    on_fail: BLOCK
    reason: >
      Step 0 requires five independent searches and fewer have been
      evidenced in the case folder

Can auto mode bypass it

No, and this was tested rather than assumed. A permission mode changes when the runtime prompts the operator, and the hook runs before that prompt.

The full result table and the probe that reproduces it are in Can the agent get past it. It is worth checking yourself, because the opposite is widely repeated.

So what does get past it

Four things, and Coco says them first. Editing the settings file that registers the hook. A session on a machine where Coco is not installed. What a permitted call does once it is running. And a contract that is wrong.

The full threat model is in What it does not stop.

Is it an MCP server sitting between the agent and its tools

No, and the difference matters.

An MCP gateway sees MCP traffic. It cannot see a shell command, a file write or a subagent being spawned, because none of those goes through MCP.

Coco sits at the tool-call boundary, so it sees every tool the agent has, MCP tools included. An MCP call arrives at the same gate as Bash and is evaluated by the same contract.

For MCP specifically the interception is client-side. The call is stopped before it leaves the runtime. Coco does not today reject anything at the MCP server, and describing it as server-side enforcement would be wrong.

A gateway in front of an MCP server is a reasonable second layer and it is a different control. It protects the server from every client. Coco governs one agent across all of its tools.

Why not ship it as an MCP server or a tool the agent calls

Because a tool is a call the agent chooses to make and can decline to make. The verdict would also land in the model's context, which is the one place a verdict can be argued with.

The check has to sit outside the agent, so the client goes in the harness, at the seam that executes tool calls, where code and not judgement decides whether the call runs.

Allowlist or blocklist

Both, in different places, and the split is deliberate.

Tool routing is fail-closed. A tool no contract covers is denied, so a new tool arriving in a runtime release is denied until someone decides about it. That is an allowlist and it is the default.

Contracts themselves express whichever shape the policy has. A path restriction is an allowlist. "No egress after reading a credential" is a condition on a sequence and it is neither.

A missing configuration, an unreadable contract, a rule that will not evaluate and a gate that throws all produce a block rather than a pass. There is a setting to change that and the default is the one a bank should want.

What happens when the gate breaks

The answer depends on which road you are on, so here is the whole matrix.

RoadFailureWhat happens
npx hookThe check errorsBLOCK. The receipt says the gate failed rather than pretending a rule fired. on_error can make it ask or allow, and the choice is recorded
npx hookThe check hangs past 30 secondsClaude Code stops waiting and runs the call as though no gate were installed. This is the one fail-open in the product, and it is Claude Code's timeout, not a Coco setting
SDK clientThe gate is unreachable, times out, or refuses the keyBLOCK, from the client itself. fail_open reverses it, and it exists for the observe phase only
Hosted or self-hosted gateThe check errors or hangs inside the serviceBLOCK, with a reason saying the gate did not answer

So the npx hook is fail-closed on error and fail-open on a hang, and everything on the SDK road is fail-closed throughout.

The receipt is written by the check itself, so a hook that timed out leaves no row at all, and a client verdict marked unreached never reached the gate. The ledger has a hole rather than a wrong answer, in observe mode as much as in enforce, and reading the ledger says how to find those holes.

The gate itself makes no network call and no model call while deciding, which is what keeps a hang unlikely rather than impossible.

What if Coco is unreachable on the SDK road

With enforcement on and the client at its default, your agents stop until the gate answers, because a check nobody answered is not an allow. That is the honest cost of a hosted checker, and you choose it rather than discover it.

In observe mode, fail open and nothing interrupts you while Coco is only watching.

What does the auditor actually get

One row per decision, allows included, holding the verdict, the contract and the specific check that produced it, the reason in a sentence, the tool, the permission mode the session was running in, and a summary of what was attempted.

Rows are hash-chained, and coco verify names the first row that does not verify.

Receipts are not cryptographically signed today. They are tamper-evident on one machine and they would not survive an operator with write access and patience. Signing and an external anchor are the next step, and calling the current state signed would be dishonest.

The ledger has the detail.

What if the rule is wrong and the agent is right

The verdict is recorded either way, so a wrong block is visible rather than silent. That is the point of the receipt naming its rule.

ESCALATE exists for the cases nobody wants decided automatically. A human answers and the answer is written next to the receipt.

Observe mode is how a team finds the wrong rules before the rules cost anyone anything. Install, work normally for a week, then read coco report. A rule firing constantly on ordinary work is a drafting problem, and a team that cannot produce that report should not be enforcing yet.

Who writes the contract

Your team owns it. Coco can draft it from your documents, with every check citing the policy sentence it came from, and your reviewer approves what it wrote. Changing a rule is a new version, reviewed the same way.

See Drafting from a policy.

Does a model decide anything at runtime

No. A model drafts the contract once, a person approves it, and the runtime check is plain rule evaluation. Same call, same state, same answer, every time.

What does it cost per call

About 30 milliseconds, everything included, and most of that is the interpreter starting rather than the rules. A tool call itself takes hundreds of milliseconds to several seconds, so the check is a small fraction of the action it governs. What it costs breaks it down and names the command that measures it on your own machine.

What does our agent vendor have to change

Nothing structural. The check is one call at the point where tools execute, and platforms without code can gate a workflow step with a single web request.

What if our data cannot leave our infrastructure

The same gate ships as a container image for exactly that case. See Self-hosted. The hosted service is the faster road and most teams start there.

Where it does not go yet

  • Receipts are unsigned, as above.
  • Cross-session and cross-agent state is not implemented. Two agents co-ordinating across separate sessions are outside what the gate sees.
  • The npx install needs a runtime that exposes hooks. Any other runtime takes the SDK road.
  • The npm package carries the baseline and session contracts. The KYC and payments sets are in the repository, because neither has the state it reads on a developer's machine.

In this section

On this page