Architecture
The life of a policy
One policy from its manifest in chock-catalog, through chock compile and an install, to a tool call, its verdict and the decision log.
A policy is written once, compiled into the files each hook point runs, and installed per agent. After that, every tool call the agent makes runs through the hook, gets a verdict, and leaves one line in a local log.
Diagram
- Generated file
- Engine code
- The agent's client
- Local log
Select a box to read its card below.
Select a box to read its card here.
Components
Policy manifest Generated file
A policy is a folder under chock-catalog's base/. Its manifest.yaml names the policy, its enforcement and its hook: a declarative gate, or a guard script in implementations/. This one declares a content gate on commit and on tool use.
Source: chock-catalog/base/block-invisible-unicode/manifest.yaml @ 3e9d2d3e04cf
chock compileEngine codeReads a policy folder and runs one emitter per hook point: the ambient rule, agent hooks, git hook, CI step, Claude managed settings and the MCP gateway. The output lands in .chock/compiled/<policy>/.
Source: chock/src/chock/compile/compiler.py @ 39df00bbf764
gate.json Generated file
The manifest's hook.gate, resolved into one gate.json per hook point: before a tool runs, at the turn's end, in the git hook and in CI.
Source: chock/src/chock/gate/build.py @ 39df00bbf764
Guard script Generated file
A policy's own program, for a check a pattern cannot express. The hook hands it the shell command (--guard) and reads its verdict. The cited one is block-destructive-commands.
Source: chock-catalog/base/block-destructive-commands/implementations/block-destructive-commands.py @ 3e9d2d3e04cf
Ambient rule Generated file
Text the agent reads, as an AGENTS.md block. It blocks nothing on its own. The gate and the guard do.
Source: chock/src/chock/compile/emitters/ambient.py @ 39df00bbf764
Install per agent Engine code
The chock sync command writes each agent's hook file in that agent's own format, and its runtime into .chock/bin/. The chock install command builds the same for one agent as a plugin (ask the user before running either). Each hook command names the gate.json or guard it runs.
Source: chock/src/chock/hooks/in_agent_install.py @ 39df00bbf764
A tool call The agent's client
The agent's client runs the hook before the tool runs and passes the call on stdin. Agentseam's dispatcher reads it, and that agent's adapter turns the payload into one Event.
Source: agentseam/src/agentseam/dispatch.py @ dd4f0a485a36
Verdict Engine code
Evaluates the compiled gate, caps the verdict by the rollout level in force, and concludes with an exit code: block, ask, warn or allow.
Source: chock/src/chock/gate/runner/verdict.py @ 39df00bbf764
Back to the client The agent's client
The adapter speaks the Decision in the client's own dialect, and the client refuses or runs the tool. What a hook can do in each agent, and what happens when it cannot run, is agentseam's data, not ours.
Agentseam's tier table at the release the engine pins, by fail mode:
- No adapted pre-tool hook (10): Aider (none), Amp (unadapted), GitHub Copilot (Agent Plugins 1.0 marketplace bundle) (unadapted), DeepSeek Harness (dsh) (unadapted), Kilo Code (unadapted), Kiro (unadapted), OpenCode (unadapted), Replit Agent (unadapted), Roo Code (unadapted), Zed (none)
- If the hook fails, the action goes through (14): Antigravity (block+rewrite), Claude Code (block+rewrite), Cline (block), OpenAI Codex CLI (block+rewrite), Devin (block+rewrite), Factory Droid (block), Gemini CLI (block+rewrite), Grok CLI (block), Junie CLI (block+rewrite), Kimi Code CLI (block), OpenHands (block), Tabnine CLI (block+rewrite), GitHub Copilot (VS Code agent mode / CLI) (block+rewrite), Windsurf (Cascade) (block)
- What a failed hook does can be configured (3): Cursor (block+rewrite), goose (block), Mistral Vibe (block+rewrite)
Source: agentseam/src/agentseam/contract.py @ dd4f0a485a36
Decision log Local log
One line per hook call, in a local file. With repo hooks it is
<repo>/.chock/log/gate-events.jsonl. With the plugin it is~/.chock/log/<agent>/events.jsonl. Writing it never changes the decision, and the hook sends nothing over the network.Source: chock/src/chock/gate/decision_log.py @ 39df00bbf764
Connections
- Policy manifest →
chock compile: Read chock compile→ gate.json:hook.gatechock compile→ Ambient rule:ambient- Policy manifest → Guard script:
implementations/ - gate.json → Install per agent:
--gate - Guard script → Install per agent:
--guard - Install per agent → A tool call: Hook registered
- A tool call → Verdict: Event
- Verdict → Decision log: One line
- Verdict → Back to the client: Decision
Main path
The flow this diagram is about, in order:
- Policy manifest
chock compile- gate.json
- Install per agent
- A tool call
- Verdict
- Decision log
Pinned sources
Every box cites a file at these commits. CI fails the build if a cited path is missing at its commit.
- chock @ 39df00bbf764
- agentseam @ dd4f0a485a36
- chock-catalog @ 3e9d2d3e04cf
Built from engine 5a4b6287a46e and catalog 1e60d211c1bb.