Exposing agents through A2A protocol
Every AI agent created with kagent implements the A2A protocol and can be invoked by an A2A client.
Let's look at how this works in kagent!
Create an AI agent that supports A2A
We'll create a simple agent (k8s-a2a-agent
) that can retrieve resources from a Kubernetes cluster. Note the definition of the agent follows the Agent CRD with the a2aConfig
section added that describes the skills the agent can perform. You can follow the quick start to install kagent and then apply the following definition to your cluster:
apiVersion: kagent.dev/v1alpha1kind: Agentmetadata:name: k8s-a2a-agentnamespace: kagentspec:description: An example A2A agent that knows how to use Kubernetes tools.modelConfig: openai-model-configsystemMessage: |-You are an expert Kubernetes agent that uses tools to help users.tools:- builtin:name: kagent.tools.k8s.GetResourcestype: Builtina2aConfig:skills:- id: get-resources-skillname: Get Resourcesdescription: Get resources in the Kubernetes clusterinputModes:- textoutputModes:- textexamples:- "Get all resources in the Kubernetes cluster"- "Get the pods in the default namespace"- "Get the services in the istio-system namespace"- "Get the deployments in the istio-system namespace"- "Get the jobs in the istio-system namespace"- "Get the cronjobs in the istio-system namespace"- "Get the statefulsets in the istio-system namespace"
Testing the A2A endpoint
The A2A endpoint is exposed on the port 8083
of the kagent service. So let's do a port-forward to make the endpoint accessible:
kubectl port-forward svc/kagent 8083:8083 -n kagent
Note that you could also expose the A2A endpoint publicly by using a gateway.
To test that the agent is available and has an agent card, we can send a request to the .well-known/agent.json
endpoint. Note the API endpoint follows the pattern /api/a2a/{namespace}/{agent-name}/.well-known/agent.json
.
Let's send a request to the endpoint:
curl localhost:8083/api/a2a/kagent/k8s-a2a-agent/.well-known/agent.json
The output will be a JSON object that describes the agent as per the A2A protocol.
{"name": "k8s-a2a-agent","description": "An example A2A agent that knows how to use Kubernetes tools.","url": "http://127.0.0.1:8083/api/a2a/kagent/k8s-a2a-agent","version": "1","capabilities": {"streaming": false,"pushNotifications": false,"stateTransitionHistory": false},"defaultInputModes": ["text"],"defaultOutputModes": ["text"],"skills": [{"id": "get-resources-skill","name": "Get Resources","description": "Get resources in the Kubernetes cluster","examples": ["Get all resources in the Kubernetes cluster","Get the pods in the default namespace","Get the services in the istio-system namespace","Get the deployments in the istio-system namespace","Get the jobs in the istio-system namespace","Get the cronjobs in the istio-system namespace","Get the statefulsets in the istio-system namespace"],"inputModes": ["text"],"outputModes": ["text"]}]}
Use the A2A host CLI to invoke the agent
We'll use the A2A host CLI to call the agent. This CLI part of the A2A repository. Start by cloning the repository:
git clone https://github.com/google/A2A.git
Then from the A2A/samples/python/hosts/cli
directory, run the CLI and point it to the kagent endpoint:
cd A2A/samples/python/hosts/cliuv run . --agent http://127.0.0.1:8083/api/a2a/kagent/k8s-a2a-agent
The CLI will connect to the kagent, display the agent card and prompt you for input:
======= Agent Card ========{"name":"my-a2a-agent","description":"An example A2A agent that knows how to use Kubernetes tools.","url":"http://127.0.0.1:8083/api/a2a/kagent/my-a2a-agent","version":"1","capabilities":{"streaming":false,"pushNotifications":false,"stateTransitionHistory":false},"defaultInputModes":["text"],"defaultOutputModes":["text"],"skills":[{"id":"kagent-k8s-agent","name":"Get Resources","description":"Get resources in the Kubernetes cluster","examples":["Get all resources in the Kubernetes cluster","Get the pods in the default namespace","Get the services in the istio-system namespace","Get the deployments in the istio-system namespace","Get the jobs in the istio-system namespace","Get the cronjobs in the istio-system namespace","Get the statefulsets in the istio-system namespace"],"inputModes":["text"],"outputModes":["text"]}]}========= starting a new task ========What do you want to send to the agent? (:q or quit to exit):
Let's send the task "Get the pods in the kagent namespace" to the agent. You'll be also prompted to optionally attach a file to the request, but just hit enter to skip this step. The request will be sent to the agent and the response will be displayed in the CLI. Her'es the formated version of the response:
{"jsonrpc": "2.0","id": "0df6761ed3394b43a2dee2bd6572bc94","result": {"id": "89bae00376e44ed094a2174e163da9f6","sessionId": "d966626d06ab42b19bd3999e65333311","status": {"state": "completed","message": {"role": "agent","parts": [{"type": "text","text": "Processed result: There is one pod running in the \"kagent\" namespace:\n\n- Pod Name: kagent-748fb675c6-9ddsz\n- Status: Running\n- Ready Containers: 3 out of 3\n- Restarts: 0\n- Age: 31 minutes\n- Pod IP: 10.244.0.11\n- Node: kagent-control-plane\n\nLet me know if you need more details or want to perform any actions on this pod."}]},"timestamp": "2025-05-06T22:27:31+00:00"},"artifacts": [{"name": "Task Result","description": "The result of the task processing","parts": [{"type": "text","text": "There is one pod running in the \"kagent\" namespace:\n\n- Pod Name: kagent-748fb675c6-9ddsz\n- Status: Running\n- Ready Containers: 3 out of 3\n- Restarts: 0\n- Age: 31 minutes\n- Pod IP: 10.244.0.11\n- Node: kagent-control-plane\n\nLet me know if you need more details or want to perform any actions on this pod."}],"index": 0,"lastChunk": true}]}}
The result
section contains the result of the task and the artifacts
section contains the output of the task and it shows the pods running inside the kagent namespace.
The agent has processed the request and returned the result.