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 folderCan 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.
| Road | Failure | What happens |
|---|---|---|
| npx hook | The check errors | BLOCK. 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 hook | The check hangs past 30 seconds | Claude 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 client | The gate is unreachable, times out, or refuses the key | BLOCK, from the client itself. fail_open reverses it, and it exists for the observe phase only |
| Hosted or self-hosted gate | The check errors or hangs inside the service | BLOCK, 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.
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
- Can the agent get past it. What was tested, and what happened.
- What it costs. Measured, with the command that reproduces it.
- How it compares. Against permission rules, gateways and prompts.