The ack-agent-gateway extension lets you expose AI agent services to external traffic using the Agent2Agent (A2A) protocol. Built on the Gateway API standard, it gives you precise control over how A2A protocol traffic is routed to your agent backends.
This tutorial walks you through the complete setup:
-
Install ack-agent-gateway — deploy the gateway component to your cluster
-
Deploy a sample A2A service — run a backend agent to test routing against
-
Create a gateway and routing rule — configure external traffic entry and route it to the agent
-
Test service connectivity — verify end-to-end routing through the gateway
-
Add API key authentication (Optional) — secure the service without modifying application code
Prerequisites
Before you begin, ensure that you have:
-
An ACK managed cluster running Kubernetes 1.32 or later
-
Gateway API version 1.3.0 or later installed in your cluster
Install ack-agent-gateway
ack-agent-gateway implements the Gateway API standard to configure and manage traffic for AI agent scenarios. Install it using Helm from the ACK console.
-
On the ACK Clusters page, click the name of your cluster. In the left navigation pane, choose Applications > Helm.ACK Clusters
-
Click Create. In the Chart section, search for and select
ack-agent-gateway. Keep the default settings and click Next.The component is installed in the
ack-agent-gatewaynamespace by default, and the application is published using the component name. -
On the Parameters page, select the latest chart version and click OK.
-
After installation, verify the component appears on the Helm page with a status of Deployed.
Step 1: Deploy a sample A2A service
Deploy a sample agent service that implements the A2A protocol. This service acts as the backend for testing gateway routing in later steps.
-
Create a file named
a2a-server.yamlwith the following content. The file defines a Deployment and a Service that exposes it within the cluster.apiVersion: apps/v1 kind: Deployment metadata: name: demo-a2a spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: demo-a2a template: metadata: labels: app.kubernetes.io/name: demo-a2a spec: containers: - image: registry-cn-hangzhou.ack.aliyuncs.com/dev/sample-a2a-agent-helloworld:v0.2.0 imagePullPolicy: IfNotPresent name: agent ports: - containerPort: 9999 name: server protocol: TCP --- apiVersion: v1 kind: Service metadata: name: demo-a2a-agent-server spec: ports: - name: server port: 9999 protocol: TCP targetPort: 9999 selector: app.kubernetes.io/name: demo-a2a sessionAffinity: None type: ClusterIP -
Apply the manifest.
kubectl apply -f a2a-server.yaml -
Verify the Pod is running.
kubectl get pod -l app.kubernetes.io/name=demo-a2aExpected output:
NAME READY STATUS RESTARTS AGE demo-a2a-77dd75ddcf-qn9jx 1/1 Running 0 13s
Step 2: Create a gateway and a routing rule
Create a Gateway instance and an HTTPRoute that directs external traffic to the A2A service deployed in the previous step.
All three resources in a2a-gateway.yaml work together: the Backend resource points to your A2A service, the Gateway resource opens an HTTP listener on port 80, and the HTTPRoute resource ties the two together.
-
Create a file named
a2a-gateway.yamlwith the following content.--- # Custom Backend resource that defines the backend A2A service apiVersion: agentgateway.alibabacloud.com/v1alpha1 kind: Backend metadata: name: test-a2a spec: type: A2A a2a: targets: - name: a2a-target static: # Points to the Service created in Step 1 host: demo-a2a-agent-server port: 9999 --- # Gateway resource that defines the traffic entrypoint apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: test-a2a-gateway spec: # Specifies ack-agent-gateway as the implementer of this Gateway gatewayClassName: ack-agent-gateway listeners: - name: http # The port exposed by the gateway port: 80 protocol: HTTP allowedRoutes: namespaces: # Allows only HTTPRoutes in the same namespace to attach to this listener from: Same --- # HTTPRoute resource that defines the routing rule apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: route-for-a2a-backend spec: parentRefs: # Attaches this HTTPRoute to the Gateway named test-a2a-gateway - name: test-a2a-gateway rules: - backendRefs: # References the custom Backend resource as the backend - group: agentgateway.alibabacloud.com kind: Backend name: test-a2a -
Apply the manifest.
kubectl apply -f a2a-gateway.yaml -
Get the public IP address of the gateway.
kubectl get gateway test-a2a-gatewayThe
ADDRESSfield shows the IP address of the Server Load Balancer (SLB) instance associated with the gateway. Record this address — you need it in the next step.NAME CLASS ADDRESS PROGRAMMED AGE test-a2a-gateway ack-agent-gateway 8.136.xx.xx True 4m36s
Step 3: Test service connectivity
Use an A2A client to send requests through the gateway and confirm end-to-end routing is working.
-
Install Git and clone the official A2A sample repository. Check out a specific commit to match the versions used in this tutorial.
This tutorial pins to commit
d4fa006438e52to ensure compatibility. In production, check out a stable release tag instead.git clone https://github.com/a2aproject/a2a-samples.git && \ cd a2a-samples && git checkout d4fa006438e52 && \ cd samples/python/hosts/cli -
Install Python if it isn't already available. Then use uv to install the client dependencies.
uv sync -
Connect to the A2A service through the gateway. Replace
<GATEWAY_IP>with the address you obtained in Step 2.uv run . --agent http://<GATEWAY_IP>Expected output: The gateway forwards the request to the backend, which responds with its Agent Card. The client then waits for input.
Will use headers: {} ======= Agent Card ======== {"capabilities":{"streaming":true},"defaultInputModes":["text"],"defaultOutputModes":["text"],"description":"Just a hello world agent","name":"Hello World Agent",...} ========= starting a new task ======== What do you want to send to the agent? (:q or quit to exit): -
At the prompt, enter
helloand press Enter. The agent replies withHello World.What do you want to send to the agent? (:q or quit to exit): hello Select a file path to attach? (press enter to skip): stream event => {"kind":"message","messageId":"...","parts":[{"kind":"text","text":"Hello World"}],"role":"agent"} {"kind":"message","messageId":"...","parts":[{"kind":"text","text":"Hello World"}],"role":"agent"} -
Enter
quitto exit the client.
Step 4: Add API key authentication to the service (Optional)
Protect the agent service with API key authentication using a TrafficPolicy resource — no changes to your application code are required.
How it works: TrafficPolicy is a Custom Resource Definition (CRD) provided by ack-agent-gateway that implements the Gateway API Policy Attachment pattern. It attaches policies such as authentication and rate limiting directly to an HTTPRoute, keeping policy configuration decoupled from application logic.
API key authentication is a simple credential-based method. If a key is leaked, it can be misused immediately. Store and rotate keys carefully.
Verify baseline connectivity before adding authentication
Before applying the authentication policy, confirm that the gateway routes traffic correctly without any credentials. This lets you isolate routing issues from authentication issues if something goes wrong later.
Run the connectivity test from Step 3:
uv run . --agent http://<GATEWAY_IP>
If the Agent Card appears and the client starts, routing is working correctly. Proceed to apply authentication.
Apply API key authentication
-
Create a file named
a2a-api-key.yamlwith the following content. TheSecretstores the API keys, and theTrafficPolicyattaches the authentication policy to the HTTPRoute.ImportantStore only the raw credential value in the Secret — do not include the
Bearerprefix. When a client sendsAuthorization: Bearer key-value-foo, the gateway strips theBearerprefix before comparing the value against the Secret.Configuration Secret value Client sends Correct key-value-fooAuthorization: Bearer key-value-fooIncorrect Bearer key-value-fooAuthentication fails — double Bearerprefix--- apiVersion: v1 kind: Secret metadata: name: a2a-api-key stringData: # The key name (such as key1) is only an identifier. # The value (such as key-value-foo) is the actual credential the client must provide. key1: 'key-value-foo' key2: 'key-value-bar' --- apiVersion: agentgateway.alibabacloud.com/v1alpha1 kind: TrafficPolicy metadata: name: test-a2a-apikey-auth spec: targetRefs: # The target for policy attachment - group: gateway.networking.k8s.io kind: HTTPRoute name: route-for-a2a-backend # Attaches to the previously created HTTPRoute traffic: authentication: apiKeyAuth: secretRef: name: a2a-api-key # References the Secret that stores the credentials -
Apply the authentication policy.
kubectl apply -f a2a-api-key.yaml
Test authentication
-
Verify that requests without credentials are rejected. Replace
<GATEWAY_IP>with your gateway address.uv run . --agent http://<GATEWAY_IP>Expected output: The gateway returns
401 Unauthorizedbefore the client can fetch the Agent Card.a2a.client.errors.A2AClientHTTPError: HTTP Error 401: Failed to fetch agent card from http://8.136.xx.xx/.well-known/agent-card.json: Client error '401 Unauthorized' ... -
Access the service again with a valid API key.
uv run . --bearer-token 'key-value-foo' --agent http://<GATEWAY_IP>Expected output: The request header includes
Authorization: Bearer key-value-foo. The gateway authenticates the credentials, forwards the request, and the client starts successfully.Will use headers: {'Authorization': 'Bearer key-value-foo'} ======= Agent Card ======== {"capabilities":{"streaming":true},"defaultInputModes":["text"],"defaultOutputModes":["text"],"description":"Just a hello world agent","name":"Hello World Agent",...} ========= starting a new task ======== What do you want to send to the agent? (:q or quit to exit):
Clean up resources
Delete all resources created in this tutorial to avoid incurring unnecessary charges.
-
Delete the Kubernetes resources in the following order.
# If you completed the optional Step 4, delete the authentication resources first kubectl delete -f a2a-api-key.yaml # Delete the gateway and routing rule kubectl delete -f a2a-gateway.yaml # Delete the backend sample service kubectl delete -f a2a-server.yaml -
Confirm the SLB instance is released. Deleting the
Gatewayresource automatically triggers deletion of the associated SLB instance. Log on to the Server Load Balancer console to confirm the instance no longer appears.