CEL expressions
Agentgateway uses the CEL expression language throughout the project to enable flexibility. CEL allows writing simple expressions based on the request context that evaluate to some result.
Example expressions
Review the following examples of expressions for different uses cases.
Default function
You can use the default
function to provide a fallback value if the expression cannot be resolved.
Request header fallback with example of an anonymous user:
default(request.headers["x-user-id"], "anonymous")
Nested object fallback with example of light theme:
default(json(request.body).user.preferences.theme, "light")
JWT claim fallback with example of default “user” role:
default(jwt.role, "user")
Logs, traces, and observability
# Include logs where there was no response or there was an error
filter: |
!has(response) || response.code > 299
fields:
add:
user.agent: 'request.headers["user-agent"]'
# A static string. Note the expression is a string, and it returns a string, hence the double quotes.
span.name: '"openai.chat"'
gen_ai.usage.prompt_tokens: 'llm.input_tokens'
# Parse the JSON request body, and conditionally log...
# * If `type` is sum, val1+val2
# * Else, val3
# Example JSON request: `{"type":"sum","val1":2,"val2":3,"val4":"hello"}`
json.field: |
json(request.body).with(b,
b.type == "sum" ?
b.val1 + b.val2 :
b.val3
)
Authorization
mcpAuthorization:
rules:
# Allow anyone to call 'echo'
- 'mcp.tool.name == "echo"'
# Only the test-user can call 'add'
- 'jwt.sub == "test-user" && mcp.tool.name == "add"'
# Any authenticated user with the claim `nested.key == value` can access 'printEnv'
- 'mcp.tool.name == "printEnv" && jwt.nested.key == "value"'
Rate limiting
remoteRateLimit:
descriptors:
# Rate limit requests based on a header, whether the user is authenticated, and a static value (used to match a specific rate limit rule on the rate limit server)
- entries:
- key: some-static-value
value: '"something"'
- key: organization
value: 'request.headers["x-organization"]'
- key: authenticated
value: 'has(jwt.sub)'
Context reference
As you write expressions, keep the following context in mind.
Functions and variables
When using CEL in agentgateway, you can use the following variables and functions.
Field | Description |
---|---|
request |
request contains attributes about the incoming HTTP request |
request.method |
The HTTP method of the request. For example, GET |
request.uri |
The complete URI of the request. For example, http://example.com/path . |
request.host |
|
request.scheme |
|
request.path |
The path of the request URI. For example, /path . |
request.headers |
The headers of the request. |
request.body |
The body of the request. Warning: accessing the body will cause the body to be buffered. |
request.startTime |
The (pre-rendered) time the request started |
request.endTime |
The (pre-rendered) time the request completed |
response |
response contains attributes about the HTTP response |
response.code |
The HTTP status code of the response. |
response.body |
The body of the response. Warning: accessing the body will cause the body to be buffered. |
jwt |
jwt contains the claims from a verified JWT token. This is only present if the JWT policy is enabled. |
llm |
llm contains attributes about an LLM request or response. This is only present when using an ai backend. |
llm.streaming |
Whether the LLM response is streamed. |
llm.requestModel |
The model requested for the LLM request. This may differ from the actual model used. |
llm.responseModel |
The model that actually served the LLM response. |
llm.provider |
The provider of the LLM. |
llm.inputTokens |
The number of tokens in the input/prompt. |
llm.outputTokens |
The number of tokens in the output/completion. |
llm.totalTokens |
The total number of tokens for the request. |
llm.prompt |
The prompt sent to the LLM. Warning: accessing this has some performance impacts for large prompts. |
llm.prompt[].role |
|
llm.prompt[].content |
|
llm.completion |
The completion from the LLM. Warning: accessing this has some performance impacts for large responses. |
llm.params |
The parameters for the LLM request. |
llm.params.temperature |
|
llm.params.top_p |
|
llm.params.frequency_penalty |
|
llm.params.presence_penalty |
|
llm.params.seed |
|
llm.params.max_tokens |
|
source |
source contains attributes about the source of the request. |
source.address |
The IP address of the downstream connection. |
source.port |
The port of the downstream connection. |
source.identity |
The (Istio SPIFFE) identity of the downstream connection, if available. |
source.identity.trustDomain |
The trust domain of the identity. |
source.identity.namespace |
The namespace of the identity. |
source.identity.serviceAccount |
The service account of the identity. |
mcp |
mcp contains attributes about the MCP request. |
mcp.(any)(1)tool |
|
mcp.(any)(1)tool.target |
The target of the resource |
mcp.(any)(1)tool.name |
The name of the resource |
mcp.(any)(1)prompt |
|
mcp.(any)(1)prompt.target |
The target of the resource |
mcp.(any)(1)prompt.name |
The name of the resource |
mcp.(any)(1)resource |
|
mcp.(any)(1)resource.target |
The target of the resource |
mcp.(any)(1)resource.name |
The name of the resource |
backend |
backend contains information about the backend being used. |
backend.name |
The name of the backend being used. For example, my-service or service/my-namespace/my-service:8080 . |
backend.type |
The type of backend. For example, ai , mcp , static , dynamic , or service . |
backend.protocol |
The protocol of backend. For example, http , tcp , a2a , mcp , or llm . |
extauthz |
extauthz contains dynamic metadata from ext_authz filters |
Functions by policy type
Certain 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
.
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 |
Remote Rate Limit | source , request , jwt |
HTTP Authorization | source , request , jwt |
MCP Authorization | source , request , jwt , mcp |
Logging | source , request , jwt , mcp , response , llm |
Tracing | source , request , jwt , mcp , response , llm |
Metrics | source , request , jwt , mcp , response , llm |
Functions for all policy types
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 . |
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. |
map_values |
map_values applies a function to all values in a map. map in CEL only applies to map keys. |
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. |
flatten_recursive |
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. |
random |
Generates a number float from 0.0-1.0 |
Standard functions
Additionally, the following standard functions are available for all policy types, too.
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
.