What is CEL?
CEL is a fast, safe expression language designed for evaluating user-defined conditions at runtime. Unlike Lua or WASM, CEL is sandboxed and cannot perform I/O or side effects — this makes it predictable, safe to use in a high-performance proxy, and straightforward to reason about. A simple MCP authorization expression:Where CEL is used
| Use case | Example |
|---|---|
| Authorization policies | jwt.sub == "alice" && mcp.tool.name != "delete" |
| Log and trace field extraction | request.headers["user-agent"] |
| HTTP header and body transformations | "Bearer " + jwt.sub |
| Rate limit selectors | source.address |
| Tracing sampling | 0.1 (10% random sampling) |
How expressions are evaluated
Expressions are compiled at configuration load time (not per request). During compilation, Agentgateway extracts which context variables the expression references. At request time, only the referenced data is collected — you only pay for what you use.request.body— causes the body to be buffered in memory (expensive)request.headers— header map allocation (moderate cost)llm.prompt/llm.completion— large string copies for LLM traffic
Variable extraction uses static analysis. It handles
request.body correctly, but not dynamic access patterns like request["body"]. Stick to dot notation for reliable optimization.Context reference
The following variables are available in CEL expressions. Availability depends on where in the pipeline the expression runs — for example,response is not available in request-phase transformations.
request — incoming HTTP request
request — incoming HTTP request
The
Examples:
request object contains attributes about the incoming HTTP request.| Field | Type | Description |
|---|---|---|
request.method | string | HTTP method, e.g. GET |
request.uri | string | Complete URI, e.g. http://example.com/path |
request.host | string | Hostname, e.g. example.com |
request.scheme | string | Scheme, e.g. https |
request.path | string | Path component, e.g. /path |
request.pathAndQuery | string | Path and query, e.g. /path?foo=bar |
request.version | string | HTTP version, e.g. HTTP/1.1 |
request.headers | map | Request headers (access by name) |
request.body | string | Request body (buffers entire body) |
request.startTime | timestamp | Time the request started |
request.endTime | timestamp | Time the request completed |
response — HTTP response
response — HTTP response
The
Examples:
response object is available in response-phase expressions (e.g., response transformations, access logs).| Field | Type | Description |
|---|---|---|
response.code | int | HTTP status code |
response.headers | map | Response headers |
response.body | string | Response body (buffers entire body) |
jwt — JWT token claims
jwt — JWT token claims
The
Examples:
jwt object contains claims from a verified JWT token. It is only present when the JWT authentication policy is enabled and a valid token is provided.| Field | Type | Description |
|---|---|---|
jwt.sub | string | Subject claim |
jwt.iss | string | Issuer claim |
jwt.aud | list | Audience claim |
jwt.<claim> | any | Any custom claim from the token |
jwt is only available after the JWT policy has verified the token. If authentication fails, the request is rejected before authorization expressions run.mcp — MCP request context
mcp — MCP request context
The
Examples:
mcp object contains attributes about an MCP request. It is available when the route handles MCP traffic.| Field | Type | Description |
|---|---|---|
mcp.tool.name | string | Name of the MCP tool being called |
mcp.tool.target | string | Target server for the tool call |
mcp.resource.name | string | Name of the MCP resource being accessed |
mcp.resource.target | string | Target server for the resource |
mcp.prompt.name | string | Name of the MCP prompt being requested |
mcp.prompt.target | string | Target server for the prompt |
llm — LLM request and response
llm — LLM request and response
The
Examples:
llm object contains attributes about an LLM request or response. It is only present when using an ai backend.| Field | Type | Description |
|---|---|---|
llm.streaming | bool | Whether the response is streamed |
llm.requestModel | string | Model requested by the client |
llm.responseModel | string | Model that served the response |
llm.provider | string | LLM provider name |
llm.inputTokens | int | Input/prompt token count |
llm.outputTokens | int | Output/completion token count |
llm.totalTokens | int | Total token count |
llm.cachedInputTokens | int | Tokens read from cache (savings) |
llm.reasoningTokens | int | Reasoning tokens in output |
llm.prompt | list | Prompt messages (has performance impact) |
llm.completion | string | Completion text (has performance impact) |
llm.params.temperature | float | Temperature parameter |
llm.params.max_tokens | int | Max tokens parameter |
source — connection source
source — connection source
The
Examples:
source object contains attributes about the downstream connection.| Field | Type | Description |
|---|---|---|
source.address | string | IP address of the downstream connection |
source.port | int | Port of the downstream connection |
source.identity | object | SPIFFE identity (if mTLS is enabled) |
source.identity.trustDomain | string | SPIFFE trust domain |
source.identity.namespace | string | Kubernetes namespace |
source.identity.serviceAccount | string | Kubernetes service account |
source.subjectAltNames | list | SANs from the downstream certificate |
source.issuer | string | Issuer from the downstream certificate |
source.subject | string | Subject from the downstream certificate |
backend — upstream backend info
backend — upstream backend info
The
Examples:
backend object contains information about the backend selected for the request.| Field | Type | Description |
|---|---|---|
backend.name | string | Backend name, e.g. my-service |
backend.type | string | Backend type: ai, mcp, static, dynamic, service |
backend.protocol | string | Backend protocol: http, tcp, a2a, mcp, llm |
apiKey and basicAuth — API key and basic auth
apiKey and basicAuth — API key and basic auth
These objects are present when the corresponding authentication policy is enabled and credentials have been verified.
Examples:
| Field | Type | Description |
|---|---|---|
apiKey.key | string | The verified API key value |
basicAuth.username | string | The verified username |
env — environment variables
env — environment variables
The
Examples:
env object exposes a curated subset of well-known environment attributes. It does not expose raw process environment variables.| Field | Type | Description |
|---|---|---|
env.podName | string | Kubernetes pod name |
env.namespace | string | Kubernetes namespace |
env.gateway | string | Gateway name (Kubernetes) |
Authorization policy examples
CEL expressions are most commonly used in authorization (authz) policies. Here are practical examples:
Authorization guide
Complete guide to setting up CEL-based authorization policies
MCP proxy guide
Proxy MCP servers with tool-level access control