---
title: "Governing AI agents at the gateway with Cerbos and agentgateway"
description: "How to govern AI agents at the gateway with agentgateway and Cerbos. This covers the three authorization questions on every agent hop, which model an identity can call, which MCP servers and tools it can open, and what a tool call is actually asking for, all from one policy bundle over Envoy ext_authz."
author: "Alex Olivier"
date: "2026-06-10T18:05:24.670Z"
canonical: "https://www.cerbos.dev/blog/governing-ai-agents-at-the-gateway-with-cerbos-and-agentgateway"
image: "https://stylish-appliance-1c1cc1c30d.media.strapiapp.com/Governing_AI_agents_at_the_gateway_with_Cerbos_and_agentgateway_c451b0a637.png"
tags: ["engineering","guide","documentation"]
source: "https://www.cerbos.dev/blog/governing-ai-agents-at-the-gateway-with-cerbos-and-agentgateway"
---

# Governing AI agents at the gateway with Cerbos and agentgateway

[Watch on YouTube](https://www.youtube.com/watch?v=dFmGp7remuo)

Most teams rolling out AI agents end up in the same place. An employee kicks off an agent to handle a task, or an event like an inbound support ticket spins one up autonomously, and that agent needs to reach a model and a handful of tools to get its job done. The agent connects to an LLM. It discovers MCP servers for the CRM, the ticketing system, payments, payroll. And the moment it has those connections, you have a problem that the agent runtime was never built to answer. Which model is this agent allowed to call. Which MCP servers can it even open. And when it produces a tool call, are the arguments inside the policy you would have enforced if a human had asked.

[agentgateway](https://agentgateway.dev) closes the network side of that gap. It is a CNCF data plane that sits in front of agents and becomes the single front door for everything they reach, routing model traffic to the right provider and proxying every MCP server behind one address. What it does not decide on its own is who is allowed to do what. That is the authorization question, and it belongs in a policy engine, the same one your platform already uses for the rest of the stack.

Cerbos Synapse plugs into agentgateway as the authorization guardrail. agentgateway calls Synapse on every model request and every [MCP](https://www.cerbos.dev/features-benefits-and-use-cases/dynamic-authorization-for-MCP-servers) tool call over standard Envoy ext\_authz, Synapse asks Cerbos, and the decision comes back before the upstream is ever touched. No custom plugin to write, no SDK to keep in step with gateway releases. The gateway routes. The decisions move to where access decisions already live.

## Three questions on every agent hop

Authorization for an agent at the gateway is not one decision. It is three, and they fire at different points as the agent works.

Which model can this identity call. A basic triage classification does not need a frontier model, and a junior support tier does not need the same model menu as a lead. agentgateway already knows which providers are wired up. The policy decides who gets which one. In the demo the LLM route carries a `completion` action and the resource id is the model name the agent asked for, so the [resource policy](https://docs.cerbos.dev/cerbos/latest/policies/resource_policies.html) is a plain allow-list. Tiered support agents can reach `gpt-4o` and `gpt-4o-mini`, while the autonomous triage role is pinned to the cheaper `gpt-4o-mini` and nothing else. Everything not named is default-deny, so a request for a model the caller has no business using is refused before any token is spent upstream.

Which MCP servers and tools the agent can see. Before an agent can call a tool it has to open the MCP server and list what is there. agentgateway proxies each server on its own route, and every route is guarded. In the demo the autonomous triage agent opens tickets and CRM cleanly, but its attempt to even initialize the payments and payroll servers is denied at the gateway, so those tool catalogues never reach it. Payroll is the sharp edge of this. It is wired up exactly like every other server, but its policy only allows a `payroll-admin` role, so the MCP `initialize` call denies for everyone else before a single tool name is exposed. The model never gets the chance to choose a tool it should not have, because it never learns the tool exists.

What the tool call is actually asking for. This is the decision a gateway cannot make on its own, and it is the one that matters most for agents. When the model produces a refund call, agentgateway forwards the request body to Synapse, so the policy reads the structured arguments directly and joins them with the calling identity. A refund against a ticket the agent's task is not bound to is one rule. A refund above the caller's tier cap is another. Both live in the policy, not in gateway config, so changing them is a policy change rather than a redeploy of the data plane.

## How the integration is shaped

agentgateway is a good fit for this pattern because the extension point is already a standard. Every route in the gateway config carries an `extAuthz` policy that points at Synapse over gRPC, with `failureMode: deny` so a gateway that cannot reach the policy engine fails closed rather than open. The model route and each MCP route carry the same block. There is no adapter binary and no agentgateway-specific authorization primitive in the path, which is the whole point. Because ext\_authz is an Envoy standard, the same Cerbos policies and the same Synapse mapper run unchanged behind Envoy, Istio, or any other gateway that speaks it. Swapping the gateway is a routing-config change, not a rewrite of your access rules.

The credential that the gateway hands to the policy is a per-resource token. The agent runs inside a sandbox with outbound access blocked, so agentgateway is its only way out, and at boot it exchanges for one runtime token per server it is allowed to reach, each scoped to exactly that resource. A token captured from the payments wire is useless at the LLM route or at CRM. The identity inside that token is whatever your environment attests. It can be the user the agent is acting on behalf of, or for a truly autonomous agent it can be a workload identity, a [SPIFFE](https://www.cerbos.dev/blog/spiffe-identity-parsing-cerbos-pdp)\-attested non-human principal that the agent earned at startup rather than a human it is impersonating. Either way it rides through to Cerbos on every call, and the decision comes back in milliseconds.

One more property falls out of the ordering. agentgateway applies the upstream provider key after ext\_authz, so a Cerbos deny stops the request before the model or the MCP server is ever contacted. The denied model call costs nothing. The denied refund never reaches payments. The guardrail is in front of the spend, not behind it.

## What a rule looks like

A Cerbos rule reads like the access control it actually is. Here is the pair that governs the refund tool, the join between identity and tool arguments that the demo turns on.

```
# Tiered support agents may issue refunds...
- name: allow-listed-actions
  actions: [tools/call/refund_issue]
  effect: EFFECT_ALLOW
  roles: [tier-1-support, tier-2-lead]

# ...but a tier-1 agent cannot go over their cap.
- name: tier-1-refund-cap
  actions: [tools/call/refund_issue]
  effect: EFFECT_DENY
  roles: [tier-1-support]
  condition:
    match:
      expr: R.attr.arguments.amount_cents > 5000
  output:
    when:
      ruleActivated: |-
        {
          "decision": "deny",
          "reason": "tier-1-support refund cap exceeded",
          "remediation": { "type": "step_up", "approvers_role": "tier-2-lead" }
        }
```

`R.attr.arguments` are the arguments the model produced for the tool call, forwarded by the gateway. `P` is the calling identity from the token. A separate `cross-ticket-guard` rule denies when `R.attr.arguments.ticket_id` does not match the ticket the agent's task is bound to, so an agent can only act on the case it was spun up for. The cap rule does something a proxy-native check cannot. It returns structured context with the denial, and that context flows back to the agent. In the demo the refund handler asks for $9,000, the cap rule fires, and the agent reads the reason and updates the ticket to tell the customer it needs to escalate rather than silently failing. The denial is not just a wall, it is a signal the agent can act on.

## Why this matters for AI-agent governance

| Area | Details |
| :---- | :---- |
| Per-model access at the gateway | Different roles and autonomous agents get different model tiers without touching agent code. A triage agent is pinned to a cheap model, and a request for anything off its allow-list denies before any spend reaches the provider. |
| Per-server and per-tool control before tools reach the model | An agent only opens the MCP servers its identity allows. Servers it should not touch, like payments and payroll for an autonomous triage agent, deny at MCP `initialize`, so their tool catalogues never enter the model's context. |
| Argument-aware ABAC | The gateway forwards the request body, so the policy reads the real tool arguments and joins them with the caller. A refund is allowed only on the agent's bound ticket and only within the caller's cap. Denials carry structured reasons the agent can read and act on. |
| One PDP for the whole stack | Model access, MCP access, and your application's own authorization run on the same engine and the same policy language, with one [audit trail](https://www.cerbos.dev/features-benefits-and-use-cases/audit-logs) across every plane. |
| Standard extension point | agentgateway calls Cerbos over Envoy ext\_authz with no adapter. The same policies port to any ext\_authz-capable gateway, so the data plane stays swappable. |

## The kill switch and the audit trail

The reason a gateway is the right place for all of this is that it is also the right place for the things you reach for when an agent goes wrong. Because every model call and every tool call passes one decision point, you get a single record of what every agent tried and what was allowed, enriched with which agent, which harness version, which model, and which case it was bound to. [Cerbos Hub](https://hub.cerbos.cloud) is the control plane for that, both the place the policies are versioned and the unified log of every decision across the LLM and MCP planes.

It is also the kill switch. An agent's authority is scoped to a task, and that task is separately revocable. Pull it and the agent's next call denies, no matter how far into its run it is, because the gateway checks on every hop rather than once at the start. There is no standing access to claw back and no agent process to chase down. The authority simply stops being granted.

## The broader pattern

agentgateway is one shape of this. The pattern applies to anything sitting on the request path between an agent and the surfaces it reaches. A gateway that speaks ext\_authz calls Cerbos with no adapter at all. A proxy with hookable middleware, like LiteLLM, calls it from a guardrail instead. The data layer that enriches the principal is shared. The policy language is the same. The audit trail lives in one place.

If your agents reach OpenAI and Anthropic through one gateway and also proxy a catalogue of MCP servers for your tools, you do not want two policy stores, two audit pipelines, and two sets of role definitions, one for the model plane and one for the tools. You want one place where access policy is written down, tested, and enforced, and you want it to plug into the agent sandboxes, gateways, and MCP servers you already run rather than asking you to rebuild any of them. That is what Cerbos does for [agentic systems](https://www.cerbos.dev/features-benefits-and-use-cases/ai-security) end to end.

## Get a walkthrough on your stack

The fastest way to see whether this fits your setup is to walk through it with the Cerbos team. We can show how the ext\_authz route plugs into agentgateway, what the policy bundle looks like for your agent roles and workload identities, and how the decision trail flows back into the system you already use for compliance. Most calls take thirty minutes and end with you knowing what the integration would cost in time and what it would change in your identity model.

[**Try Cerbos**](https://hub.cerbos.cloud) to author and ship a policy bundle for your agents, or [**book a call**](https://www.cerbos.dev/workshop) to talk through your gateway architecture with the team.

**Go deeper:**

- [Zero Trust for AI: Securing MCP servers](https://www.cerbos.dev/ebooks-webinars) (eBook) for a playbook on locking down AI tool access across your stack  
- [Fine-grained authorization for non-human identities](https://www.cerbos.dev/ebooks-webinars) (Webinar) for a walkthrough of the policy patterns behind agent permissions  
- [MCP authorization](https://www.cerbos.dev/blog/mcp-authorization) for the deeper guide to securing the AI tool perimeter

## FAQ

### How do you govern what an AI agent is allowed to do at the gateway?

You govern an AI agent at the gateway by putting one authorization decision in front of every model request and every tool call. agentgateway becomes the single front door for everything the agent reaches, and it calls Cerbos over the Envoy ext\_authz protocol before any upstream is touched. The agent runtime was never built to decide which model it can call or which MCP servers it can open, so those decisions move to the policy engine your platform already uses for the rest of the stack.

### What are the three authorization questions for an AI agent?

The three authorization questions for an AI agent fire at different points as it works. First, which model this identity can call, enforced as a default-deny allow-list so a request for an off-list model is refused before any token is spent. Second, which MCP servers and tools the agent can even open, so a server it should not touch denies at MCP initialize and its tool catalogue never reaches the model. Third, what the tool call is actually asking for, where the policy reads the structured arguments and joins them with the calling identity.

### What is argument-aware authorization for AI agents?

Argument-aware authorization reads the real arguments the model produced for a tool call and makes the decision on what the agent is actually trying to do. When the model produces a refund call, the gateway forwards the request body to Cerbos, so a rule can deny a refund against a ticket the agent's task is not bound to, or a refund above the caller's tier cap. This is the join a proxy-native check cannot make, because identity comes from the token and arguments come from the request body, and the two only meet inside the policy. This is [ABAC](https://www.cerbos.dev/features-benefits-and-use-cases/abac) applied to agent behavior.

### How does Cerbos integrate with agentgateway without a custom adapter?

Cerbos integrates with agentgateway over the standard Envoy ext\_authz protocol, so there is no adapter binary and no gateway-specific authorization primitive in the path. Every route in the gateway config carries an extAuthz policy pointing at Cerbos Synapse over gRPC, with failure mode set to deny so a gateway that cannot reach the policy engine fails closed. Because ext\_authz is an Envoy standard, the same policies run unchanged behind Envoy, Istio, or any other gateway that speaks it, so swapping the gateway is a routing-config change rather than a rewrite of your access rules.

### How does identity work for autonomous AI agents?

Identity for an autonomous AI agent rides through to Cerbos on every call inside a per-resource token. The agent runs in a sandbox with outbound access blocked, so the gateway is its only way out, and at boot it exchanges for one runtime token per server it is allowed to reach, each scoped to exactly that resource. The identity inside that token can be the human the agent is acting on behalf of, or for a truly autonomous agent a SPIFFE-attested workload identity, a non-human principal the agent earned at startup rather than a human it impersonates.

### Can one policy engine cover model access, MCP access, and application authorization?

One Cerbos engine can cover model access, MCP access, and your application's own authorization on the same policy language with a single audit trail across every plane. That matters because if your agents reach OpenAI and Anthropic through one gateway and proxy a catalogue of MCP servers, you do not want two policy stores and two sets of role definitions. Cerbos Hub versions the policies and holds the unified log of every decision, which also gives you a task-scoped kill switch, since the gateway checks on every hop you can revoke an agent's authority mid-run and its next call denies.
