Connect a generic A2A agent¶
For a team with an agent that speaks A2A but does not run on kagent: at the end, Agent Kourier sends a Binding's turns
to that agent through the generic a2a dialect.
Before you start¶
The agent must:
- serve an A2A 1.0 or 0.3 agent card whose capabilities advertise streaming. Agent Kourier rejects an agent whose card does not;
- offer a JSON-RPC interface. A card that lists only gRPC or REST is refused;
- serve its card at the endpoint URL plus
/.well-known/agent-card.json, with a trailing slash on the URL trimmed; - answer with task events and put its answer in artifact text parts, or answer a new turn with one agent message that names no task. A message is the whole answer, and with no task there is nothing to follow after a dropped stream or to look up after a restart. An answer to a question must continue its task with task events.
The agent contract lists the rest: the methods it must serve, what each message carries, and how replies, task states and errors are read.
Declare the backend¶
config:
agentBackends:
my-agent:
spec:
dialect: a2a
url: https://my-agent.example.internal/a2a/ # (1)!
headers: # (2)!
- name: X-Tenant
value: payments
allowedNamespaces: [payments]
- The exact JSON-RPC endpoint, used as written. Keep a trailing slash if the agent's route has one: Agent Kourier follows no redirects, because a redirect could carry the Binding's token to another host.
- Optional static headers, sent on every request. A value can come from a Secret with
valueSecretRef. Headers that carry or select identity are refused:Authorization,Proxy-Authorization,Cookie,X-User-Id,X-Agent-Name,X-Share-TokenandX-Kagent-Insecure-Runtime-Identity.
Choose how the Binding identifies itself¶
See Create the Binding identity for choosing the account or name and obtaining a token.
In the Binding's identity:
tokenSecretRefsends the Secret's value asAuthorization: Bearer. Something must verify it: the agent itself, or a proxy in front of it. If the Secret cannot be read, the turn is retried and then fails after 15 minutes; it never falls back touserId.userIdalone is sent asX-User-Id, for an agent that trusts its network.
What works on this dialect¶
- Chat and alert investigations, with streamed answers.
- An agent's question, when it pauses with
input-requiredand text, if the Binding setsinteractions.askUser: true. A single question with no choices also takes a typed reply in the thread. - A
Working…card (a line, in an alert thread) while the agent is silent for 3 seconds, with the defaultchat.progress. - Tool calls as step cards, when the agent marks its tool parts as Google ADK or kagent does (
adk_type,kagent_typeorkagent.dev/a2a/part-type, set tofunction_callorfunction_response): see Tool calls and results. Without that marker the calls are not shown. - Structured questions (with choices, several at once, or from a sub-agent) and tool approvals, when the agent card
lists kagent's human-in-the-loop extension,
https://kagent.dev/extensions/hitl/v1, undercapabilities.extensions. Agent Kourier then asks for the extension, and reads and answers a pause that names it as thekagent-v1dialect does; the agent contract has what is sent and read.interactions.askUser,toolApprovalsandapproverGroupsapply as described in Agent questions. A structured question takes its answer from the prompt's controls only, never from a typed reply. kagent 1.0.0-alpha5's agent card lists the extension; 0.9.x has not been checked. - Not: structured pauses from an agent without that extension. Agent Kourier does not read a framework's own approval
format (see Why approvals use one extension). Any other
pause must be text alone; a pause with any part that is not text cannot be used, so the task is cancelled. A payload that the status message does not name in its
extensionsis not read, and the pause is handled as text. - A kagent agent paused for a tool approval without the extension (its card does not list it, or a request did not ask
for it) sends text alone, asking for a
FunctionResponse(recorded with kagent 1.0.0-alpha5). Agent Kourier handles that pause as a question. On a Binding withinteractions.askUser: falseit cancels the task and tells the thread the agent asked a question. WithaskUser: trueit posts kagent's text, and the reply goes to kagent as plain text, never as an approval; what kagent does with plain text has not been tested. - An A2A 0.3 agent has no task list, so after a restart a turn may be sent, and run, twice.
Check it¶
Mention the bot in a bound channel and watch the pod log for session turn started and session turn ended. A card
problem shows in session turn failed; see Troubleshoot an install.