Skip to main content

CEL reference overview

Common Expression Language (CEL) is a fast, safe expression language used throughout Agentgateway to evaluate user-defined expressions against live request data. CEL expressions are evaluated at request time against a rich context of variables describing the request, response, authentication state, and more. CEL is not as general-purpose as Lua or WASM, but it is significantly faster and sufficient for the majority of gateway policy use cases.

Where CEL is used

Agentgateway uses CEL in several places across the request processing pipeline:
  • Authorization rules — define which requests are allowed or denied
  • Rate limiting conditions — select the attribute to rate limit on (for example, per user or per API key)
  • Logs and traces — define which request attributes to include as structured fields
  • Header and body transformations — compute new header or body values
  • MCP authorization — control which MCP tools, prompts, and resources a caller can access

Expression syntax

CEL expressions are single-line expressions that evaluate to a value. They support:
SyntaxDescriptionExample
Field accessDot notationrequest.method
Map lookupBracket notationrequest.headers["x-api-key"]
Comparison==, !=, <, <=, >, >=response.code >= 500
Logical&&, ||, !jwt.role == "admin" && request.method == "GET"
Membershipinmcp.tool.name in ["read_file", "list_files"]
String methodsBuilt-in string functionsrequest.path.startsWith("/api")
Ternarycondition ? a : bhas(jwt.sub) ? jwt.sub : "anonymous"
Field existencehas()has(jwt.sub)

Available context objects

Agentgateway exposes the following top-level objects to CEL expressions. Not all objects are available in all contexts — for example, response is not available during a request-phase transformation, and mcp is only present for MCP requests.
ObjectDescription
requestAttributes of the incoming HTTP request (method, path, headers, body, timing)
responseAttributes of the HTTP response (status code, headers, body)
sourceAttributes of the downstream connection (IP, port, mTLS identity)
envSelected Kubernetes environment attributes (pod name, namespace, gateway)
jwtClaims from a verified JWT token (present only when JWT auth is enabled)
apiKeyClaims from a verified API key (present only when API key auth is enabled)
basicAuthBasic authentication credentials (present only when basic auth is enabled)
mcpMCP-specific context: the tool, prompt, or resource being accessed
llmLLM-specific context: model, token counts, prompt, completion, parameters
llmRequestRaw LLM request before processing (available only during LLM policy evaluation)
backendInformation about the selected backend (name, type, protocol)
extauthzDynamic metadata from external authorization filters
extprocDynamic metadata from external processing filters
metadataValues set by transformation metadata expressions
Agentgateway uses static analysis at configuration load time to determine which context fields your expressions reference. Fields that are not referenced are not collected, so you only pay for what you use. This is especially important for request.body and response.body, which require buffering.

Practical examples

request.method == "GET"

Custom CEL functions

Agentgateway extends CEL with custom functions beyond the standard library.
FunctionDescriptionExample
jsonParse a string or bytes as JSONjson(request.body).some_field
toJsonConvert a CEL value to a JSON stringtoJson({"hello": "world"})
base64.encodeEncode a string to base64base64.encode("hello")
base64.decodeDecode a base64 string to bytesstring(base64.decode("aGVsbG8K"))
FunctionDescriptionExample
unvalidatedJwtPayloadParse a JWT payload without verifying the signatureunvalidatedJwtPayload(request.headers.authorization.split(" ")[1]).sub
FunctionDescriptionExample
withBind an expression result to a variable (CEL has no native bindings)json(request.body).with(b, b.field_a + b.field_b)
variablesExpose all context variables as a single valuevariables
defaultReturn a fallback if the expression fails to resolvedefault(request.headers["missing-header"], "fallback")
coalesceReturn the first non-null, non-error expressioncoalesce(request.headers["x-id"], json(request.body).id, "fallback")
failUnconditionally fail an expressionfail
FunctionDescriptionExample
mapValuesApply a function to all values in a map
filterKeysReturn a new map keeping only keys matching a predicate{"a":1,"b":2}.filterKeys(k, k == "a")
mergeJoin two maps (right-hand values win on key conflict){"a":2,"k":"v"}.merge({"a":3})
flattenFlatten a list or struct into many fields (logging/tracing only)flatten(request.headers)
flattenRecursiveLike flatten but flattens multiple levels (logging/tracing only)
FunctionDescriptionExample
regexReplaceReplace substrings matching a regular expression"/id/1234/data".regexReplace("/id/[0-9]*/", "/id/{id}/")
randomGenerate a random float from 0.0 to 1.0random() < 0.1
uuidGenerate a random UUIDv4uuid()
All standard CEL functions are available, including collections (contains, size, has, map, filter, all, exists), type conversion (string, bytes, double, int, uint), strings (startsWith, endsWith, matches, trim, replace, split, substring), time functions (duration, timestamp, getFullYear, getMonth), and IP/CIDR helpers (isIP, ip, cidr).

Header views

The request.headers and response.headers objects expose chainable methods for common header access patterns:
MethodDescriptionExample
Direct accessReturns a string for single values, list for multiplerequest.headers["content-type"]
.redacted()Replace sensitive values with "<redacted>"request.headers.redacted().authorization
.join()Join all entries for a header with ,request.headers.join()["x-forwarded-for"]
.raw()Return raw entries as a listrequest.headers.raw()["set-cookie"]
.split()Split entries on , and return as a listrequest.headers.split()["accept"]
.cookie(name)Parse the Cookie header and return a named cookie valuerequest.headers.cookie("session")

Query string access

request.pathAndQuery and request.uri expose query-aware methods:
MethodDescriptionExample
.query(name)Return all values for a query parameter as a listrequest.pathAndQuery.query("foo") == ["bar"]
.addQuery(name, value)Return a new string with the parameter appendedrequest.pathAndQuery.addQuery("foo", "qux")
.setQuery(name, value)Return a new string with the parameter replacedrequest.uri.setQuery("foo", "qux")

Reference pages

Request context

Full reference for request, response, source, env, jwt, apiKey, basicAuth, backend, and metadata objects.

MCP context

Full reference for the mcp object: tools, prompts, and resources.

LLM context

Full reference for the llm object: model, token counts, prompt, completion, and parameters.