All Products
Search
Document Center

Container Service for Kubernetes:Use ack-agent-gateway to implement Agent2Agent (A2A) traffic governance and authentication

Last Updated:Mar 26, 2026

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:

  1. Install ack-agent-gateway — deploy the gateway component to your cluster

  2. Deploy a sample A2A service — run a backend agent to test routing against

  3. Create a gateway and routing rule — configure external traffic entry and route it to the agent

  4. Test service connectivity — verify end-to-end routing through the gateway

  5. 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.

  1. On the ACK Clusters page, click the name of your cluster. In the left navigation pane, choose Applications > Helm.ACK Clusters

  2. 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-gateway namespace by default, and the application is published using the component name.
  3. On the Parameters page, select the latest chart version and click OK.

  4. 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.

  1. Create a file named a2a-server.yaml with 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
  2. Apply the manifest.

    kubectl apply -f a2a-server.yaml
  3. Verify the Pod is running.

    kubectl get pod -l app.kubernetes.io/name=demo-a2a

    Expected 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.

  1. Create a file named a2a-gateway.yaml with 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
  2. Apply the manifest.

    kubectl apply -f a2a-gateway.yaml
  3. Get the public IP address of the gateway.

    kubectl get gateway test-a2a-gateway

    The ADDRESS field 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.

  1. 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 d4fa006438e52 to 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
  2. Install Python if it isn't already available. Then use uv to install the client dependencies.

    uv sync
  3. 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):
  4. At the prompt, enter hello and press Enter. The agent replies with Hello 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"}
  5. Enter quit to 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.

Important

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

  1. Create a file named a2a-api-key.yaml with the following content. The Secret stores the API keys, and the TrafficPolicy attaches the authentication policy to the HTTPRoute.

    Important

    Store only the raw credential value in the Secret — do not include the Bearer prefix. When a client sends Authorization: Bearer key-value-foo, the gateway strips the Bearer prefix before comparing the value against the Secret.

    Configuration Secret value Client sends
    Correct key-value-foo Authorization: Bearer key-value-foo
    Incorrect Bearer key-value-foo Authentication fails — double Bearer prefix
    ---
    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
  2. Apply the authentication policy.

    kubectl apply -f a2a-api-key.yaml

Test authentication

  1. 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 Unauthorized before 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' ...
  2. 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.

  1. 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
  2. Confirm the SLB instance is released. Deleting the Gateway resource automatically triggers deletion of the associated SLB instance. Log on to the Server Load Balancer console to confirm the instance no longer appears.