Variables and functions
How CEL variables are populated per policy phase, and where to find the full context reference and function list.
When using CEL expressions, a variety of variables and functions are made available.
Variables
Variables are only available when they exist in the current context. Previously in version 0.11 or earlier, variables like jwt were always present but could be null. Now, to check if a JWT claim exists, use the expression has(jwt.sub). This expression returns false if there is no JWT, rather than always returning true.
Additionally, fields are populated only if they are referenced in a CEL expression. This way, agentgateway avoids expensive buffering of request bodies if no CEL expression depends on the body.
Each policy execution consistently gets the current view of the request and response. For example, during logging, any manipulations from earlier policies (such as transformations or external processing) are observable in the CEL context.
For the full list of fields available on each top-level object (request, response, jwt, mcp, llm, source, extauthz), see the CEL Expression Context reference, which is generated from the agentgateway schema.
Variables by policy type
Depending on the policy, different fields are accessible based on when in the request processing they are applied.
| Policy | Available variables |
|---|---|
| Transformation | source, request, jwt, extauthz |
| Remote Rate Limit | source, request, jwt |
| HTTP Authorization | source, request, jwt |
| External Authorization | source, request, jwt |
| MCP Authorization | source, request, jwt, mcp |
| Logging | source, request, jwt, mcp, extauthz, response, llm |
| Tracing | source, request, jwt, mcp, extauthz, response, llm |
| Metrics | source, request, jwt, mcp, extauthz, response, llm |
Functions
The following functions can be used in all policy types.
| Function | Purpose |
|---|---|
json | Parse a string or bytes as JSON. Example: json(request.body).some_field. |
toJson | Convert a CEL value into a JSON string. Example: toJson({"hello": "world"}). |
unvalidatedJwtPayload | Parse the payload section of a JWT without verifying the signature. This splits the token, base64url-decodes the middle segment, and parses it as JSON. Example: unvalidatedJwtPayload(request.headers.authorization.split(" ")[1]).sub |
with | CEL does not allow variable bindings. with allows doing this. Example: json(request.body).with(b, b.field_a + b.field_b) |
variables | variables exposes all of the variables available as a value. CEL otherwise does not allow accessing all variables without knowing them ahead of time. Warning: this automatically enables all fields to be captured. |
mapValues | mapValues applies a function to all values in a map. map in CEL only applies to map keys. |
filterKeys | Returns a new map keeping only entries where the key matches the predicate (must evaluate to bool). Example: {"a":1,"b":2}.filterKeys(k, k == "a") results in {"a":1}. To remove keys, invert the predicate: m.filterKeys(k, !k.startsWith("x_")). |
merge | merge joins two maps. Example: {"a":2,"k":"v"}.merge({"a":3}) results in {"a":3,"k":"v"}. |
flatten | Usable only for logging and tracing. flatten will flatten a list or struct into many fields. For example, defining headers: 'flatten(request.headers)' would log many keys like headers.user-agent: "curl", etc. |
flattenRecursive | Usable only for logging and tracing. Like flatten but recursively flattens multiple levels. |
base64.encode | Encodes a string to a base64 string. Example: base64.encode("hello"). |
base64.decode | Decodes a string in base64 format. Example: string(base64.decode("aGVsbG8K")). Warning: this returns bytes, not a String. Various parts of agentgateway will display bytes in base64 format, which may appear like the function does nothing if not converted to a string. |
sha1.encode | Computes the SHA-1 digest of a string or bytes value and returns the lowercase hex string. Example: sha1.encode("hello"). |
sha256.encode | Computes the SHA-256 digest of a string or bytes value and returns the lowercase hex string. Example: sha256.encode("hello"). |
md5.encode | Computes the MD5 digest of a string or bytes value and returns the lowercase hex string. Example: md5.encode("hello"). |
random | Generates a number float from 0.0-1.0 |
default | Resolves to a default value if the expression cannot be resolved. For example default(request.headers["missing-header"], "fallback") |
coalesce | Evaluates expressions from left to right and returns the first one that resolves successfully to a non-null value. null values are skipped while searching, but if every expression is either null or an error and at least one expression resolved to null, the result is null. Unlike default, it swallows any error from earlier expressions, not just missing keys or undeclared references. Example: coalesce(request.headers["x-id"], json(request.body).id, "fallback") |
regexReplace | Replace the string matching the regular expression. Example: "/id/1234/data".regexReplace("/id/[0-9]*/", "/id/{id}/") would result in the string /id/{id}/data. |
fail | Unconditionally fail an expression. |
uuid | Randomly generate a UUIDv4 |
The following standard functions are available:
contains,size,has,map,filter,all,max,startsWith,endsWith,string,bytes,double,exists,exists_one,int,uint,matches.- Duration/time functions:
duration,timestamp,getFullYear,getMonth,getDayOfYear,getDayOfMonth,getDate,getDayOfWeek,getHours,getMinutes,getSeconds,getMilliseconds. - From the strings extension:
charAt,indexOf,join,lastIndexOf,lowerAscii,upperAscii,trim,replace,split,substring,stripPrefix,stripSuffix. - From the Kubernetes IP extension:
isIP("..."),ip("..."),ip("...").family(),ip("...").isUnspecified(),ip("...").isLoopback(),ip("...").isLinkLocalMulticast(),ip("...").isLinkLocalUnicast(),ip("...").isGlobalUnicast(). - From the Kubernetes CIDR extension:
cidr("...").containsIP("..."),cidr("...").containsIP(ip("...")),cidr("...").containsCIDR(cidr("...")),cidr("...").ip(),cidr("...").masked(),cidr("...").prefixLength().