Skip to content

The verdict API, govern without a gateway

Sometimes you don’t want a proxy in front of your agent, you just want to ask policy a question and act on the answer yourself. That’s the verdict API: one call, one decision, TapPass never touches your traffic.

This is the opposite deployment shape from TapPass as the gateway. Here TapPass is a policy oracle beside your app, not in the hot path.

POST /v1/govern takes the action you’re about to perform and returns a decision:

Terminal window
curl -X POST https://tappass.example.com/v1/govern \
-H "Authorization: Bearer tp_dev_..." \
-H "Content-Type: application/json" \
-d '{
"type": "TOOL_CALL",
"agent_id": "support-agent",
"session_id": "ses_abc123",
"payload": {"tool": "send_email", "args": {"to": "user@acme.com"}}
}'
{
"outcome": "allow",
"reason": "",
"behavior_id": "beh_…",
"pipeline_id": "run_…",
"decided_at": "2026-07-21T09:14:03Z",
"mandate": "<signed-mandate-jwt>"
}

outcome is one of:

Outcome What you do
allow Perform the action. The mandate is a short-lived signed token naming exactly what was authorized.
block Don’t perform it, reason and details say why (the same evidence an auditor sees).
needs_approval A human must approve. Resubmit the identical call once the approval is granted.

You call this before the action. If it’s allow, you execute the tool / write / LLM call in your own code. TapPass recorded the decision either way.

The type names what the agent is about to do. It’s not just tool calls, the verdict API governs the full range of agent behaviors:

type The action
LLM_CALL / EMBEDDING_CALL A model or embedding request
TOOL_CALL / TOOL_LIST / TOOL_RESULT Invoking a tool, discovering tools, or handing a tool result back
SYSTEM_OF_RECORD_WRITE A write to a system of record (CRM, ledger, ticketing…)
STATE_TRANSITION A change in your workflow’s state
PROMPT_SUBMIT A user/agent prompt entering the loop
CREDENTIAL_ACCESS / CODE_EXEC / SKILL_LOAD Reading a secret, executing code, loading a skill

The payload carries the specifics for that type (e.g. tool + args, or model + messages). See behaviors for each shape.

A decision isn’t only yes/no. An allow can arrive with obligations, things you must apply before proceeding, like redacting a detected secret or routing to a different model. When TapPass can apply the change itself it returns a modified_payload; otherwise the obligations list tells you what to do. Honour them, then act. See verdicts & obligations.

Decision-only means TapPass didn’t see the result, so close the loop by reporting it. POST /v1/govern/execution (correlated by pipeline_id) records what happened, output, latency, tokens, cost, so the audit trail and trust score stay complete. When a call comes back needs_approval, an operator grants it via POST /v1/govern/approve (or the dashboard), and you resubmit the identical call.

You rarely hand-write the curl. The Python SDK wraps /v1/govern around any framework’s tools or plain callables:

import tappass
from tappass import GovernanceBlocked, ApprovalPending
tools = tappass.govern(
[send_email],
url="https://tappass.example.com",
api_key="tp_dev_...",
agent_id="support-agent",
mode="enforce", # POST a TOOL_CALL to /v1/govern before running
)
try:
tools[0](to="cfo@acme.com", subject="Q4", body="…")
except GovernanceBlocked as e:
print(f"Blocked by policy: {e.reason}") # tool never executed
except ApprovalPending as e:
print(f"Suspended pending approval: {e.request_id}")

govern() works with CrewAI, LangChain, LlamaIndex, Pydantic AI, and plain functions, see governance from code. In mode="enforce" an unreachable server fails closed by default; nothing runs unless policy said allow.

Because it’s a single JSON call, /v1/govern drops into any pre-execution hook. The Claude Code integration is exactly this: every PreToolUse becomes a TOOL_CALL behavior posted to /v1/govern, and a block refuses the tool, no gateway involved.

  • Zero blast radius. TapPass being slow or down never stalls your traffic, you decide the fail-open/fail-closed policy in your own code.
  • Governs non-LLM actions. Database writes, state transitions, tool calls, anything you can describe as a behavior, not just model calls.
  • Cryptographic proof. An allow mints a mandate your executor can verify offline against the published JWKS.

When you’d rather not touch every call site, and want provider key handling, streaming, and audit for free, put TapPass in the path as the gateway instead.