A condition expression is a string assigned to the condition field of an AI Policy.
The language is CEL, with the same fields and operators as Kong Gateway plugin conditions, except for the differences listed in Differences from Kong Gateway plugin conditions.
AI Gateway validates the expression when you save the AI Policy.
A predicate is the basic unit of an expression and compares a field against a value:
|
Object
|
Description
|
Example
|
|
Field
|
A value extracted from the incoming request or the AI Gateway context.
An absent field may return null or cause a runtime error depending on the field type. See Null handling.
|
http.method
|
|
Value
|
The value the field is compared against. Can be a constant (string, int, bool, null) or another field.
The value can appear on either side of the predicate.
|
"GET"
|
|
Operator
|
Defines the comparison to perform between the field and the value.
|
==
|
|
Predicate
|
Compares a field against a value using the given operator. Returns true if the comparison passes, false if it doesn’t.
|
http.method == "GET"
|
|
Operator
|
Description
|
Example
|
&&
|
Logical AND. True if both sides are true.
|
http.method == "POST" && http.headers.x_tier == "premium"
|
||
|
Logical OR. True if either side is true.
|
http.method == "GET" || http.method == "POST"
|
!
|
Logical NOT. Inverts the result.
|
!(http.method == "DELETE")
|
()
|
Parentheses. Control evaluation order.
|
(http.method == "GET" || http.method == "POST") && http.headers.x_tier == "premium"
|
AI Policy conditions support HTTP request fields and context fields.
For fields that you shouldn’t use in AI Policy conditions, see Fields to avoid.
These fields reflect the state of the incoming HTTP request at the time the expression is evaluated.
Higher-priority AI Policies can modify these values before AI Gateway evaluates the expression.
|
Field
|
Type
|
Description
|
Example
|
http.method
|
string
|
The HTTP method of the incoming request, for example "GET" or "POST".
|
http.method == "POST"
|
http.host
|
string
|
The Host header of the incoming request.
|
http.host == "internal.example.com"
|
http.path
|
string
|
The normalized request path, without query parameters.
|
http.path.startsWith("/api/v2")
|
http.path_segments
|
list<string>
|
The path split on /, with empty segments excluded.
For example, /a/b/c yields ["a", "b", "c"].
Test membership with in. Indexing, such as http.path_segments[0], isn’t supported.
|
"admin" in http.path_segments
|
http.headers.<header_name>
|
string
|
The value of the specified request header.
Header names are always normalized to lowercase with underscores, so X-My-Header becomes http.headers.x_my_header.
Returns the first value if the header has multiple values.
Returns null if the header is absent.
|
http.headers.x_tier == "premium"
|
http.queries.<param_name>
|
string
|
The value of the specified query parameter.
Returns the first value if the parameter appears multiple times.
Returns null if the parameter is absent.
|
http.queries.plan == "pro"
|
http.headers_list.<header_name>
|
list<string>
|
All values of the specified request header as a list. Returns null if the header is absent.
|
http.headers_list.x_roles != null && "editor" in http.headers_list.x_roles
|
http.queries_list.<param_name>
|
list<string>
|
All values of the specified query parameter as a list. Returns null if the parameter is absent.
|
http.queries_list.tag != null && "featured" in http.queries_list.tag
|
net.protocol
|
string
|
The protocol of the request, for example "http" or "https".
|
net.protocol == "https"
|
net.tls.sni
|
string
|
The server name from the TLS ClientHello packet. Returns null for non-TLS connections.
|
net.tls.sni == "api.example.com"
|
net.src.ip
|
string
|
The IP address of the client.
|
net.src.ip == "10.0.0.1"
|
net.src.port
|
int
|
The port the client used to connect.
|
net.src.port > 1024
|
net.dst.ip
|
string
|
The listening IP address where the data plane accepted the connection.
|
net.dst.ip == "192.168.1.1"
|
net.dst.port
|
int
|
The listening port where the data plane accepted the connection.
|
net.dst.port == 443
|
The following fields describe the AI Gateway context.
|
Field
|
Behavior for an AI Policy
|
consumer.id, consumer.username, consumer.custom_id, consumer.tags
|
Return null when the request isn’t authenticated.
For an authenticated AI Consumer, consumer.id is the AI Consumer’s ID, consumer.username is its name, and consumer.custom_id is its custom ID.
consumer.tags contains the AI Consumer’s labels as key:value strings, and is null when the AI Consumer has no labels.
|
consumer_group.names, consumer_group.ids
|
Return null when the request isn’t authenticated.
For an authenticated AI Consumer that belongs to AI Consumer Groups, return the names and IDs of those groups.
|
principal.id, principal.metadata
|
When the request is authenticated through an AI Auth Strategy with Kong Identity Principal mapping (config.principals), principal.id is the Principal’s ID and principal.metadata is its metadata map.
In all other cases, both fields are null.
|
kong.ctx.shared
|
Always a map. Accessing a missing key causes a runtime error.
Check for the key with has() first. See Null handling.
|
The consumer.*, consumer_group.*, and principal.* fields are populated only after an authentication step has identified the caller.
Don’t use route.*, service.*, or plugins.* fields in AI Policy conditions.
AI Gateway generates a Route, a Service, and plugins from your AI entities and AI Policies.
These fields describe the generated resources.
Their names and IDs differ from your AI entity names and aren’t part of the AI Gateway interface.
The plugins.<name>.is_matched, plugins.<name>.priority, and plugins.<name>.access_has_executed fields describe Kong Gateway plugins.
How null values behave depends on the field type.
The following fields return null when a value isn’t set:
http.headers.*
http.queries.*
http.headers_list.*
http.queries_list.*
net.tls.sni
consumer.*, consumer_group.*, principal.*
Compare these fields directly with null:
consumer.id != null
http.headers.x_tier != null && http.headers.x_tier.startsWith("prem")
A comparison such as http.headers.x_tier == "premium" evaluates to false, not an error, when the header is absent.
The kong.ctx.shared and principal.metadata fields are maps whose inner keys aren’t pre-populated.
Accessing a missing key in these maps causes a runtime error.
Before you access a key, use has() to check that it exists:
has(kong.ctx.shared.my_flag) && kong.ctx.shared.my_flag == "enabled"
AI Gateway doesn’t support default() in AI Policy conditions. The default() function that Kong Gateway plugin conditions use to catch runtime errors is rejected when you save the AI Policy. Use has() instead.
|
Operator or function
|
Description
|
&&, ||, !
|
Logical AND, OR, NOT.
|
()
|
Group expressions to control evaluation order.
|
==, !=, <, <=, >, >=
|
Standard value comparison.
|
+
|
String concatenation.
|
in
|
Tests whether a value is a member of a list.
|
contains()
|
Returns true if the string contains the given substring.
|
startsWith()
|
Returns true if the string starts with the given prefix.
|
endsWith()
|
Returns true if the string ends with the given suffix.
|
matches()
|
Tests the string against a regular expression.
|
has()
|
Returns true if the key exists in the map. Required before you access inner keys of kong.ctx.shared or principal.metadata.
|
cond ? a : b
|
Conditional expression.
|
Regular expression matches succeed if they match a substring of the argument.
Use explicit anchors (^ and $) to force full-string matching.
For example, http.path.matches("^/api/v[0-9]+$") matches /api/v1 but not /other/api/v1.
|
Type
|
Description
|
Example literal
|
bool
|
Boolean value.
|
true, false
|
int
|
64-bit signed integer.
|
42, -1
|
string
|
UTF-8 string.
|
"hello"
|
list<string>
|
Ordered list of string values.
|
["foo", "bar"]
|
map<string, _type>
|
Map with string keys and values of any type. Used for kong.ctx.shared and principal.metadata.
|
See the kong.ctx.shared field.
|
null
|
Null value, returned when an optional field has no value.
|
null
|