Govern via hooks
A hook is the lightest way to connect: at a point where your runtime is about to do something — run a tool, submit a prompt, make a model call — you call TapPass, get a decision, and act on it. TapPass never sits in your request path; you keep executing in your own code.
This is the same verdict API decision, invoked from a hook your framework already gives you. If you don’t have a natural hook point, use the gateway instead.
The pattern
Section titled “The pattern”Every hook does the same three things:
- Describe the pending action as a behavior (a tool call, an LLM call, a record write…).
POST /v1/governand read theoutcome.allow→ proceed ·block→ refuse and surface the reason ·needs_approval→ pause until a human approves.
import httpx
def before_tool(name, args): d = httpx.post( "https://tappass.example.com/v1/govern", headers={"Authorization": "Bearer tp_dev_..."}, json={"type": "TOOL_CALL", "payload": {"tool": name, "args": args}}, ).json() if d["outcome"] == "block": raise PermissionError(d["reason"]) # tool never runs return d # allow — carries a mandate you can verify downstreamBecause it’s one JSON call, this drops into anything with a pre-execution seam.
Where hooks plug in
Section titled “Where hooks plug in”| Surface | Hook point | Guide |
|---|---|---|
| Claude Code / Cursor | Native PreToolUse hook via the SDK’s tappass-claude-code-hook command |
Claude Code |
| LiteLLM | A custom pre-call guardrail that calls /v1/govern |
Gateway & LiteLLM → Option B |
| Your own agent / framework | Wrap each tool with the SDK’s govern(), or call /v1/govern directly in a pre-tool hook |
Governance from code |
| MCP clients | Point the client at the governed MCP endpoint — every tools/call is governed for you |
MCP |
Fail-open or fail-closed — your call
Section titled “Fail-open or fail-closed — your call”Because the decision lives in your process, you choose what happens when TapPass is unreachable. The SDK and the Claude Code forwarder fail closed by default (nothing runs without an allow); set the relevant fail-open switch if availability matters more than enforcement for a given surface.
Why choose hooks
Section titled “Why choose hooks”- No proxy, no blast radius. TapPass being slow or down never stalls your traffic — you decide the failure policy.
- Governs non-LLM actions. Tool calls, database writes, state transitions — anything you can describe as a behavior.
- Ambient in the tools you already use. Claude Code, Cursor, and MCP clients get governed with zero changes to your agent code.
Next steps
Section titled “Next steps”- The verdict API — the decision every hook asks for
- Claude Code — the ready-made coding-agent hook
- Governance from code —
govern()and enforce-mode exceptions