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.