> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/agentgateway/agentgateway/llms.txt
> Use this file to discover all available pages before exploring further.

# Request context

> CEL reference for request, response, source, env, jwt, apiKey, basicAuth, backend, and metadata context objects.

# Request context

This page documents the CEL context objects available for HTTP request and response processing in Agentgateway. These objects are available across authorization rules, transformations, logging, and tracing expressions.

## `request`

The `request` object contains attributes about the incoming HTTP request.

<ParamField path="request.method" type="string">
  The HTTP method of the request.

  ```cel theme={null}
  request.method == "GET"
  request.method in ["POST", "PUT", "PATCH"]
  ```
</ParamField>

<ParamField path="request.uri" type="string">
  The complete URI of the request, including scheme, host, path, and query string. Supports `.query()`, `.addQuery()`, and `.setQuery()` methods.

  ```cel theme={null}
  request.uri == "http://example.com/api/users"
  request.uri.query("page") == ["2"]
  request.uri.setQuery("version", "2")
  ```
</ParamField>

<ParamField path="request.host" type="string">
  The hostname of the request.

  ```cel theme={null}
  request.host == "api.example.com"
  ```
</ParamField>

<ParamField path="request.scheme" type="string">
  The scheme of the request (`http` or `https`).

  ```cel theme={null}
  request.scheme == "https"
  ```
</ParamField>

<ParamField path="request.path" type="string">
  The path component of the request URI, without query string.

  ```cel theme={null}
  request.path == "/api/v1/users"
  request.path.startsWith("/admin")
  ```
</ParamField>

<ParamField path="request.pathAndQuery" type="string">
  The path and query string of the request URI. Supports `.query()`, `.addQuery()`, and `.setQuery()` methods.

  ```cel theme={null}
  request.pathAndQuery == "/api/users?page=2"
  request.pathAndQuery.query("filter") == ["active"]
  ```
</ParamField>

<ParamField path="request.version" type="string">
  The HTTP version of the request.

  ```cel theme={null}
  request.version == "HTTP/1.1"
  request.version == "HTTP/2.0"
  ```
</ParamField>

<ParamField path="request.headers" type="object">
  The headers of the request. Returns a string for single-value headers and a list for multi-value headers. Supports `.redacted()`, `.join()`, `.raw()`, `.split()`, and `.cookie(name)` methods.

  ```cel theme={null}
  request.headers["content-type"] == "application/json"
  request.headers["x-api-key"]
  request.headers.cookie("session")
  request.headers.join()["x-forwarded-for"]
  ```
</ParamField>

<ParamField path="request.body" type="string">
  The body of the request as a string.

  <Warning>
    Accessing `request.body` causes the body to be buffered in memory. Only reference this field when necessary, as it has performance implications for large payloads.
  </Warning>

  ```cel theme={null}
  json(request.body).user_id == "abc123"
  json(request.body).action in ["read", "list"]
  ```
</ParamField>

<ParamField path="request.startTime" type="string">
  The timestamp when the request started, as an RFC3339 string. Use `timestamp()` to parse for time arithmetic.

  ```cel theme={null}
  timestamp(request.startTime).getHours() >= 9
  ```
</ParamField>

<ParamField path="request.endTime" type="string">
  The timestamp when the request completed. Only available after the response has been received.

  ```cel theme={null}
  timestamp(request.endTime).getHours() < 17
  ```
</ParamField>

***

## `response`

The `response` object contains attributes about the HTTP response. It is only available in response-phase expressions (for example, logging and response transformations) — not during request-phase authorization.

<ParamField path="response.code" type="integer">
  The HTTP status code of the response.

  ```cel theme={null}
  response.code == 200
  response.code >= 400
  response.code >= 500
  ```
</ParamField>

<ParamField path="response.headers" type="object">
  The headers of the response. Supports the same chainable methods as `request.headers`.

  ```cel theme={null}
  response.headers["content-type"] == "application/json"
  response.headers.redacted()["set-cookie"]
  ```
</ParamField>

<ParamField path="response.body" type="string">
  The body of the response as a string.

  <Warning>
    Accessing `response.body` causes the body to be buffered in memory. Only reference this field when necessary, as it has performance implications for large responses.
  </Warning>

  ```cel theme={null}
  json(response.body).error == "unauthorized"
  ```
</ParamField>

***

## `source`

The `source` object contains attributes about the downstream connection — the client that sent the request.

<ParamField path="source.address" type="string">
  The IP address of the downstream connection.

  ```cel theme={null}
  source.address == "192.168.1.10"
  cidr("10.0.0.0/8").containsIP(source.address)
  !cidr("192.168.0.0/16").containsIP(source.address)
  ```
</ParamField>

<ParamField path="source.port" type="integer">
  The port of the downstream connection.

  ```cel theme={null}
  source.port == 8080
  ```
</ParamField>

<ParamField path="source.identity" type="object">
  The [Istio SPIFFE](https://istio.io/latest/docs/concepts/security/#istio-identity) identity of the downstream connection. Only present when mTLS is enabled and the downstream presents a valid certificate.

  <Expandable title="identity fields">
    <ParamField path="source.identity.trustDomain" type="string">
      The trust domain of the SPIFFE identity. For example, `cluster.local`.

      ```cel theme={null}
      source.identity.trustDomain == "cluster.local"
      ```
    </ParamField>

    <ParamField path="source.identity.namespace" type="string">
      The Kubernetes namespace from the SPIFFE identity.

      ```cel theme={null}
      source.identity.namespace == "production"
      ```
    </ParamField>

    <ParamField path="source.identity.serviceAccount" type="string">
      The Kubernetes service account from the SPIFFE identity.

      ```cel theme={null}
      source.identity.serviceAccount == "my-agent"
      ```
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="source.subjectAltNames" type="string[]">
  The Subject Alternative Names from the downstream client certificate, if available.

  ```cel theme={null}
  "spiffe://cluster.local/ns/default/sa/my-agent" in source.subjectAltNames
  ```
</ParamField>

<ParamField path="source.issuer" type="string">
  The issuer from the downstream client certificate, if available.

  ```cel theme={null}
  source.issuer == "O=My CA,CN=Root CA"
  ```
</ParamField>

<ParamField path="source.subject" type="string">
  The subject from the downstream client certificate, if available.

  ```cel theme={null}
  source.subject.contains("O=My Org")
  ```
</ParamField>

<ParamField path="source.subjectCn" type="string">
  The Common Name (CN) from the subject of the downstream client certificate, if available.

  ```cel theme={null}
  source.subjectCn == "my-service.example.com"
  ```
</ParamField>

***

## `env`

The `env` object exposes a curated subset of Kubernetes environment attributes. It does not expose raw environment variables.

<ParamField path="env.podName" type="string">
  The name of the pod, when running on Kubernetes.

  ```cel theme={null}
  env.podName
  ```
</ParamField>

<ParamField path="env.namespace" type="string">
  The Kubernetes namespace of the pod.

  ```cel theme={null}
  env.namespace == "production"
  ```
</ParamField>

<ParamField path="env.gateway" type="string">
  The name of the Gateway resource the proxy is running as, when running on Kubernetes.

  ```cel theme={null}
  env.gateway == "main-gateway"
  ```
</ParamField>

***

## `jwt`

The `jwt` object contains the claims from a verified JWT token. All standard and custom claims from the token payload are accessible as fields.

<Note>
  `jwt` is only available when the JWT authentication policy is enabled for the route. The token is verified against the configured issuer and JWKS before the claims are made available.
</Note>

```cel theme={null}
# Standard claims
jwt.sub == "user-123"
jwt.iss == "https://auth.example.com"

# Custom claims
jwt.role == "admin"
jwt.org_id == "acme"

# Nested custom claims
jwt.nested.key == "value"

# Combine with other context
jwt.sub == "test-user" && mcp.tool.name == "add"
```

***

## `apiKey`

The `apiKey` object contains information about a verified API key. Only present when the API key authentication policy is enabled.

<ParamField path="apiKey.key" type="string">
  The verified API key value.

  ```cel theme={null}
  apiKey.key == "my-secret-key"
  ```
</ParamField>

***

## `basicAuth`

The `basicAuth` object contains credentials from a verified HTTP Basic authentication header. Only present when the basic authentication policy is enabled.

<ParamField path="basicAuth.username" type="string">
  The username from the Basic authentication credentials.

  ```cel theme={null}
  basicAuth.username == "alice"
  basicAuth.username in ["alice", "bob"]
  ```
</ParamField>

***

## `backend`

The `backend` object contains information about the backend selected to handle the request.

<ParamField path="backend.name" type="string">
  The name of the backend being used.

  ```cel theme={null}
  backend.name == "my-mcp-server"
  backend.name == "service/production/api:8080"
  ```
</ParamField>

<ParamField path="backend.type" type="string">
  The type of the backend. One of: `ai`, `mcp`, `static`, `dynamic`, `service`, `unknown`.

  ```cel theme={null}
  backend.type == "ai"
  backend.type == "mcp"
  backend.type in ["ai", "mcp"]
  ```
</ParamField>

<ParamField path="backend.protocol" type="string">
  The protocol of the backend. One of: `http`, `tcp`, `a2a`, `mcp`, `llm`.

  ```cel theme={null}
  backend.protocol == "mcp"
  backend.protocol == "llm"
  ```
</ParamField>

***

## `extauthz`, `extproc`, and `metadata`

<ParamField path="extauthz" type="object">
  Dynamic metadata set by external authorization (`ext_authz`) filters. Fields depend on what the external authorization service returns.

  ```cel theme={null}
  extauthz.user_id == "alice"
  ```
</ParamField>

<ParamField path="extproc" type="object">
  Dynamic metadata set by external processing (`ext_proc`) filters. Fields depend on what the external processor returns.

  ```cel theme={null}
  extproc.decision == "allow"
  ```
</ParamField>

<ParamField path="metadata" type="object">
  Values set by transformation metadata expressions in the Agentgateway configuration. Use this to pass computed values between transformation stages.

  ```cel theme={null}
  metadata.computed_user_id
  ```
</ParamField>

***

## Practical examples

<AccordionGroup>
  <Accordion title="Authorization: restrict by IP and JWT role">
    ```cel theme={null}
    cidr("10.0.0.0/8").containsIP(source.address) && jwt.role == "internal"
    ```
  </Accordion>

  <Accordion title="Logging: capture user identity">
    ```cel theme={null}
    # In a logging policy, define named fields:
    # user_id: 'jwt.sub'
    # user_agent: 'request.headers["user-agent"]'
    # path: 'request.path'
    # status: 'response.code'
    ```
  </Accordion>

  <Accordion title="Transformation: rewrite a header using a JWT claim">
    ```cel theme={null}
    # Set the x-user-id header from the JWT subject
    jwt.sub
    ```
  </Accordion>

  <Accordion title="Tracing: sample only slow or error responses">
    ```cel theme={null}
    response.code >= 500 || random() < 0.05
    ```
  </Accordion>

  <Accordion title="Parse a JSON body field">
    ```cel theme={null}
    json(request.body).action == "delete"
    json(request.body).with(b, b.user + "-" + b.tenant)
    ```
  </Accordion>

  <Accordion title="Check a cookie value">
    ```cel theme={null}
    request.headers.cookie("session") == "my-session-token"
    ```
  </Accordion>
</AccordionGroup>
