Skip to main content
Wardin’s enforcement point normally sits on model calls: a request is authenticated, policy-checked, metered, and signed into the receipt chain before it reaches a provider. Agentic governance extends that same lifecycle to agent tool calls — so when an agent asks to invoke a tool (file a PR, hit a database, send a message), the governance decision on that action gets the same tamper-evident, audit-grade record as a token spend.
Two ways to govern a tool call ship today. The decision endpoint (/mcp/tool-call) returns an allow/deny verdict for a {server, tool} without forwarding — for an agent runner that enforces the decision itself. The live proxy (/mcp/servers/<name>) sits in the path: point an MCP client at it and Wardin governs the tools/call, forwards it to your configured upstream MCP server, records the real upstream outcome, and relays the response. Both write the same signed receipt. Scope is gateway-routed tool calls to remote HTTP MCP servers — see Honest scope.

The three pieces

1. Agent identity registry

An agent is a durable, named actor bound to one virtual key (a key can front many agents — e.g. a CI key running pr-bot and deploy-bot). Register agents in Console → MCP / Agents. Identity is deliberately not taken from an agent runner’s ephemeral per-spawn headers — it comes from the registry, bound to the authenticating key, so “which agent, on whose behalf” is answerable from the signed record and cannot be forged by presenting another key’s agent id. A tool call presents its agent via the X-Wardin-Agent-Id header. The gateway accepts it only if it resolves to a registered agent bound to the same key the request authenticated with; a cross-key or cross-tenant agent id is rejected with a 403 and recorded as an AGENT_IDENTITY: FAIL check in the chain.

2. Tool allowlist policy

tool_allowlist is a policy type — which tools an agent may invoke. Patterns are globs, authored in Console → Policies:
Like model_allowlist, the gateway fail-opens on an empty list (so an empty allowlist is blocked at save time). An off-list tool is denied with a structured 403 and a signed TOOL_ALLOWLIST: FAIL check.

3. Enforcement mode

Governance follows an observe → enforce ramp, set per tenant in Console → Organization → Agentic Governance:
Mode/mcp/* endpointsTool callsAgent identity
off (default)disabled — returns 404
permissiveliveallowed, metered, signed; only an explicit tool_allowlist deniesa presented agent id must resolve, but is optional (falls back to the key)
enforcedlivemust pass a covering tool_allowlist (fail-closed)a registered X-Wardin-Agent-Id is required
Mode changes are picked up by the gateway on its refresh cycle — no redeploy.

The governance endpoint

Point a tool call at the gateway’s /mcp/tool-call endpoint with your virtual key and (optionally) an agent id:
An allowed call returns 200 {"decision":"allow", ...}; a denied call returns a structured 403 (TOOL_NOT_ALLOWED, AGENT_REQUIRED, or AGENT_INVALID). Either way a signed receipt is written.

The live proxy

The decision endpoint tells you whether a tool call is allowed; the live proxy actually runs it. Connect an upstream MCP server in Console → MCP / Agents (name, URL, credential), then point any MCP client at https://gw.wardin.ai/mcp/servers/<name> with your virtual key. See the connect-an-MCP-server guide for a full walkthrough. For each request the proxy:
  1. Authenticates the virtual key and checks the tenant’s enforcement mode (off404).
  2. Resolves the upstream server by <name> from your connected servers.
  3. Governs a tools/call with the same enforcement as the decision endpoint (agent identity → tool allowlist). Other JSON-RPC methods — initialize, tools/list, notifications — are forwarded transparently so the MCP handshake works; only a tool invocation is governed.
  4. Forwards an allowed call to the upstream with the stored credential, captures the real upstream outcome as a signed UPSTREAM: PASS/FAIL check, and relays the response. A denied call never reaches the upstream — it returns a JSON-RPC error and a FAIL receipt.
Because the proxy speaks JSON-RPC, a denial is delivered as a JSON-RPC error (the MCP-native shape) rather than an HTTP 403, so the agent’s client parses it as the call’s outcome. Each governed tool call is bucketed into the caller’s session (idle-timeout, or an explicit X-Wardin-Session-Id), so the signed record answers which agent → which tools within one task. Console → MCP / Agents shows a per-server LAST CALL badge — the most recent forwarded outcome, so a failing upstream is visible without leaving the product.

Signed tool-call receipts

Every governed tool call — allowed, tool-denied, or identity-denied — is chained into the same per-tenant receipt chain as model calls, so an auditor verifies one continuous, tamper-evident chain of model and agent activity. Tool receipts reuse the canonical receipt fields (provider = the MCP server, model = the tool name, tokens/cost = 0) and carry the enforcement decision as signed AGENT_IDENTITY / TOOL_ALLOWLIST checks — plus, for a forwarded proxy call, the UPSTREAM outcome. The kind marker (distinguishing tool_call from model_call receipts for querying) and the session_id linking a call to its task are both unsigned side channels — they don’t change the signed content, so the offline verifier needs no special handling.

Honest scope

Agentic governance covers gateway-routed tool calls only — tools an agent invokes outside the gateway are not seen. The mappings and controls here are runtime records, not a certification. The live proxy forwards to remote HTTP MCP servers (a hosted gateway can’t sit in a local stdio pipe). Upstream credentials are encrypted at rest. Today it handles the request/response tool-call shape; it does not yet consume server-initiated SSE streams, and tools/list is forwarded whole rather than filtered to the allowlist (so an agent may see a tool it cannot invoke — the invocation is still blocked). Session→tools lineage is recorded; wiring a tool’s outcome into quality scoring is the remaining roadmap item.