Skip to content

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.

PolicyAvailable variables
Transformationsource, request, jwt, extauthz
Remote Rate Limitsource, request, jwt
HTTP Authorizationsource, request, jwt
External Authorizationsource, request, jwt
MCP Authorizationsource, request, jwt, mcp
Loggingsource, request, jwt, mcp, extauthz, response, llm
Tracingsource, request, jwt, mcp, extauthz, response, llm
Metricssource, request, jwt, mcp, extauthz, response, llm

Functions

The following functions can be used in all policy types.

FunctionPurpose
jsonParse a string or bytes as JSON. Example: json(request.body).some_field.
toJsonConvert a CEL value into a JSON string. Example: toJson({"hello": "world"}).
unvalidatedJwtPayloadParse 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
withCEL does not allow variable bindings. with allows doing this. Example: json(request.body).with(b, b.field_a + b.field_b)
variablesvariables 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.
mapValuesmapValues applies a function to all values in a map. map in CEL only applies to map keys.
filterKeysReturns 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_")).
mergemerge joins two maps. Example: {"a":2,"k":"v"}.merge({"a":3}) results in {"a":3,"k":"v"}.
flattenUsable 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.
flattenRecursiveUsable only for logging and tracing. Like flatten but recursively flattens multiple levels.
base64.encodeEncodes a string to a base64 string. Example: base64.encode("hello").
base64.decodeDecodes 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.encodeComputes the SHA-1 digest of a string or bytes value and returns the lowercase hex string. Example: sha1.encode("hello").
sha256.encodeComputes the SHA-256 digest of a string or bytes value and returns the lowercase hex string. Example: sha256.encode("hello").
md5.encodeComputes the MD5 digest of a string or bytes value and returns the lowercase hex string. Example: md5.encode("hello").
randomGenerates a number float from 0.0-1.0
defaultResolves to a default value if the expression cannot be resolved. For example default(request.headers["missing-header"], "fallback")
coalesceEvaluates 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")
regexReplaceReplace the string matching the regular expression. Example: "/id/1234/data".regexReplace("/id/[0-9]*/", "/id/{id}/") would result in the string /id/{id}/data.
failUnconditionally fail an expression.
uuidRandomly 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().
Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.