Skip to content

TapPass as the gateway (and LiteLLM, two ways)

The verdict API keeps TapPass beside your app. This is the other shape: put TapPass in the request path as a governed gateway. Your agent’s calls flow through it, get governed and audited, and TapPass talks to the provider on your behalf — your agent never holds a provider key.

The gateway speaks OpenAI and Anthropic wire formats. Point any existing client at /v1 and change nothing else:

Terminal window
export OPENAI_BASE_URL=https://tappass.example.com/v1
export OPENAI_API_KEY=tp_dev_...

Every call is now governed. The gateway always returns HTTP 200 — a policy block comes back as an assistant message with tappass.blocked: true, so your agent reads the verdict instead of crashing on it. Under the hood the gateway reaches 100+ providers (OpenAI, Anthropic, Gemini, Bedrock, Azure, Mistral, and self-hosted), selected by the model string. See LLM providers for the full matrix.

Point your existing client at /v1 and keep using the endpoints you already call:

Endpoint For
POST /v1/chat/completions OpenAI-style chat
POST /v1/messages Anthropic Messages
POST /v1/embeddings OpenAI-style embeddings
GET /v1/models The models available to your org
  • Streaming works as usual — set "stream": true and read the SSE stream in your provider’s native format. Tool calls and parallel_tool_calls pass through.
  • Provider selection is driven entirely by the model string (gpt-4o, claude-…, gemini-…, or an explicit provider/model). Provider keys are your own, resolved per-org from the vault — a missing key fails closed.
  • Correlation headers you may set: X-Session-Id to group calls into a session, and Idempotency-Key for safe retries. Your org and agent are taken from the tp_ key, not from headers.

If you also want TapPass to execute governed tools (not just model calls), the gateway exposes POST /v1/tools/execute (TapPass runs the tool) and POST /v1/tools/govern (TapPass decides, you run it) — see the HTTP API.

Already running LiteLLM? Two ways to connect it

Section titled “Already running LiteLLM? Two ways to connect it”

Many teams already run a LiteLLM proxy. TapPass composes with it from either direction.

Option A — your LiteLLM behind TapPass (pass-through)

Section titled “Option A — your LiteLLM behind TapPass (pass-through)”

Treat your LiteLLM proxy as one more upstream. TapPass governs the call first, then forwards it to LiteLLM, which fans out to whichever provider it’s configured for. Register the proxy as a self-hosted model:

Terminal window
tappass model register \
--name team-litellm \
--base-url http://litellm.internal:4000/v1 \
--served-model-name gpt-4o \
--location EU --tier frontier \
--auth-token $LITELLM_MASTER_KEY
  • --base-url — your LiteLLM proxy’s OpenAI-compatible endpoint.
  • --served-model-name — the model name LiteLLM serves for this route.
  • --locationEU | US | China (data-residency tag).
  • --tierlocal | regional | frontier.

Then govern calls to it by name — {"model": "team-litellm"} — and TapPass governs, forwards to LiteLLM, and audits the result. Test connectivity with tappass model test <model_id>.

For an OpenAI-compatible endpoint you’d rather key per-org from the vault, TapPass also has a built-in custom provider: store the endpoint’s api_base + key (dashboard → Settings → LLM providers), then call custom/<model> and TapPass routes it as openai/<model>. It’s BYOK-only — a missing key or base fails closed, never a silent fallback.

Option B — TapPass verdict inside LiteLLM (guardrail hook)

Section titled “Option B — TapPass verdict inside LiteLLM (guardrail hook)”

If you want LiteLLM to stay your gateway and just add TapPass’s decision, use LiteLLM’s custom-guardrail hook to call the verdict API on every request. The guardrail POSTs the pending call to POST /v1/govern and refuses it when the outcome is block:

# litellm config.yaml (customer-side) — a pre-call guardrail
guardrails:
- guardrail_name: tappass
litellm_params:
guardrail: custom_guardrail.TapPassGuardrail # your class
mode: pre_call
# custom_guardrail.py — the TapPass side is one call to /v1/govern
import httpx
from litellm.integrations.custom_guardrail import CustomGuardrail
class TapPassGuardrail(CustomGuardrail):
async def async_pre_call_hook(self, user_api_key_dict, cache, data, call_type):
r = httpx.post(
"https://tappass.example.com/v1/govern",
headers={"Authorization": "Bearer tp_dev_..."},
json={"type": "LLM_CALL", "agent_id": "support-agent",
"payload": {"model": data["model"], "messages": data["messages"]}},
)
if r.json()["outcome"] == "block":
raise ValueError("blocked by TapPass policy")
return data
You want… Use
Zero code change, provider keys and audit handled for you Gateway (base_url swap)
Keep your LiteLLM routing, add governance in front of it Option A — LiteLLM behind TapPass
Keep LiteLLM as the gateway, bolt on the TapPass decision Option B — verdict via LiteLLM guardrail
No proxy in the path at all The verdict API directly