Coco

Quick start

Pick the road that matches where your agent lives. Both end with the gate stopping something and a receipt you can read.

Quick start

Two roads, and the only question is where your agent runs.

npxSDK
Your agent runs inClaude CodeAnywhere else
Also coversRuntimes with their own hooks, Cursor among themLangChain, the OpenAI Agents SDK, CrewAI, workflow platforms
You installA PreToolUse hookOne file in your harness
Time to a first verdictOne command and a restartOne call and a gate URL
Network on the decision pathNoneThe round trip to the gate
Who operates the gateYouCoco, or you

Both end the same way. The gate stops a call that should not have run, and writes a row naming the contract that stopped it.

The gate does not know which runtime called it. It reads one proposed action and answers, which is why the same core serves an editor's hook and a platform's harness. A runtime with its own hooks, Cursor among them, runs the same gate as its hook, and a framework like LangChain or the OpenAI Agents SDK takes the SDK road with one call where its tools execute. Claude Code is the example on every page, because it is where most agents run.

The npx road

Your agent runs in a runtime with hooks. The gate installs as one, nothing about your agent changes, and the walkthrough shows Claude Code.

npx @trustcoco/guardrails claude-code

Restart Claude Code and it is on, in observe mode, stopping nothing. Node 18 to install, python3 to run, standard library only. Everything stays on your machine, and there is no account, no service to reach and no network call on the decision path.

Full walkthrough.

The SDK road

Your agent runs on a platform, in a container, in a workflow builder, or anywhere without a terminal. The gate runs as a service and your harness asks it one question before each action.

from coco_gate import CocoGate

gate = CocoGate(GATE_URL, api_key=key, session_id=run_id)

verdict = gate.check("payment.send", {"amount": 25000, "payee": payee})
if not verdict.allowed:
    refuse(verdict.reason)

The client is one file with no dependency beyond the language itself. Coco can run the gate for you, or you can run the container.

Full walkthrough.

Running both

A team can take both roads. The developer machines take the hook, the production agents take the SDK, and both write receipts in the same shape under the same contracts.

That works because there is one gate. serve.py runs gate/coco_gate.py as a subprocess with the payload on stdin, exactly as the hook does, so the decision path has one implementation and an auditor has one story to follow.

What ships turned on, either way

Four contracts, deliberately quiet. Ordinary work runs untouched.

ContractFires whenAnswer
baseline.credential_accessThe call touches a credential fileESCALATE to read, BLOCK to write
baseline.destructive_commandThe command destroys with no safe readingBLOCK
session.blast_radiusThis session has written more files than your ceilingESCALATE
session.credential_then_egressData leaves after this session read a secretBLOCK

The last one is the one worth understanding. Reading .env is fine and fetching a URL is fine, and doing the second after the first is exfiltration. A check that looks at one call at a time allows both, and the gate keeps session state so it sees the pair.

Two further sets exist as worked examples, one for a KYC case folder and one for agent-initiated payments. Both stay off until a mandate names them, and neither ships in the npm package because neither can fire for a coding agent. They live in the repository.

Next

On this page