Upstream Authentication
Each registered A2A agent carries the credential AISIX uses to authenticate to that upstream agent. AISIX holds this credential on the gateway side and presents it when it forwards a call upstream. The caller API key an A2A client sends to AISIX authenticates the caller to AISIX — it is never forwarded to, or exposed to, the upstream agent's caller.
Set the credential with the auth_type field (and its companion fields) when you register or update an agent. AISIX applies the same credential to both operations it performs against the upstream: fetching the agent card and forwarding JSON-RPC calls.
auth_type | Upstream credential | How AISIX presents it |
|---|---|---|
none | None | No credential is sent. |
bearer | secret (a bearer token) | Authorization: Bearer <secret> |
api_key | secret (an API key) | x-api-key: <secret> |
oauth2 | client_id + token_url + secret | Accepted on the resource but not yet served — see below. |
The secret holds the plaintext credential AISIX must present upstream. It is used only gateway-side and is never sent to the calling client. To rotate a credential, update the resource with a new secret.
No Authentication
Use none when the upstream agent does not require a credential (for example, an agent reachable only on a trusted internal network).
curl -sS -X POST "http://127.0.0.1:3001/admin/v1/a2a_agents" \
-H "Authorization: Bearer ${AISIX_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"display_name": "invoice-processor",
"url": "https://agents.internal/invoice",
"protocol_version": "0.3",
"auth_type": "none"
}'
auth_type defaults to none, so you can also omit it. Leave secret, client_id, token_url, and scopes unset for a none agent.
Bearer Token
Use bearer when the upstream agent expects a static token in the Authorization header. Put the token in secret.
curl -sS -X POST "http://127.0.0.1:3001/admin/v1/a2a_agents" \
-H "Authorization: Bearer ${AISIX_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"display_name": "research-assistant",
"url": "https://agents.example.com/a2a",
"protocol_version": "0.3",
"auth_type": "bearer",
"secret": "YOUR_UPSTREAM_TOKEN"
}'
AISIX sends Authorization: Bearer YOUR_UPSTREAM_TOKEN on every request to this upstream. secret is required and must be non-empty.
API Key
Use api_key when the upstream agent expects a key in the x-api-key header. Put the key in secret.
curl -sS -X POST "http://127.0.0.1:3001/admin/v1/a2a_agents" \
-H "Authorization: Bearer ${AISIX_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"display_name": "translator",
"url": "https://agents.example.com/translate",
"protocol_version": "0.3",
"auth_type": "api_key",
"secret": "YOUR_UPSTREAM_API_KEY"
}'
AISIX sends x-api-key: YOUR_UPSTREAM_API_KEY on every request to this upstream. secret is required and must be non-empty.
OAuth 2.0 Client Credentials (Not Yet Available)
The oauth2 auth type is accepted on the agent resource for forward compatibility, but the data-plane runtime does not yet mint the token. You can create an oauth2 agent — supplying client_id, token_url, and the OAuth client secret in secret — but a call to it returns HTTP 501, and its agent card is not served.
# Accepted at write time, but calls to this agent return 501 until the
# runtime implements the OAuth 2.0 client credentials grant.
curl -sS -X POST "http://127.0.0.1:3001/admin/v1/a2a_agents" \
-H "Authorization: Bearer ${AISIX_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"display_name": "orders",
"url": "https://agents.example.com/orders",
"auth_type": "oauth2",
"client_id": "aisix-gateway",
"token_url": "https://auth.example.com/oauth/token",
"secret": "YOUR_OAUTH_CLIENT_SECRET",
"scopes": ["a2a.invoke"]
}'
Until the runtime supports it, use bearer or api_key for authenticated agents.