Agent-to-Agent (A2A) Protocol is an open standard from the Linux Foundation that enables agent-to-agent communication and collaboration. The protocol standardizes how agents discover capabilities, delegate tasks, and exchange information.
You can create a workflow that connects to remote A2A agents and provides a function interface for interacting with their capabilities.
This guide covers how to use NeMo Agent Toolkit as an A2A client. For information on publishing workflows as A2A servers, refer to A2A Server.
:::important Per-User A2A Clients
A2A clients are per-user function groups, which means:
- Each user gets their own isolated A2A client instance with separate connections, authentication, and session state
- Workflows using A2A clients must be registered as per-user using
@register_per_user_functionor use one of the builtin per-user workflows (such asper_user_react_agent) - Shared workflows (such as
react_agent) cannot use A2A client function groups directly
For multi-user deployments, this provides automatic isolation between users. See Writing Per-User Functions for details on creating per-user workflows. :::
A2A client functionality requires the nvidia-nat-a2a package. Install it with:
uv pip install "nvidia-nat[a2a]":::{note} Authentication: For connecting to OAuth2-protected A2A agents, see A2A Authentication. :::
NeMo Agent Toolkit enables workflows to interact with remote A2A agents through function groups.
function_groups:
currency_agent:
_type: a2a_client
url: http://localhost:11000
task_timeout: 60
workflow:
_type: per_user_react_agent # Per-user workflow required for A2A clients
tool_names:
- currency_agent
llm_name: nim_llmThe a2a_client function group connects to a remote A2A agent, discovers its skills through the Agent Card, and provides a function interface for invoking those skills.
Note: Since A2A clients are per-user, the workflow must also be per-user. The example above uses per_user_react_agent, which is the per-user version of the builtin ReAct agent. See the examples section for complete implementations.
The a2a_client function group supports the following configuration options:
| Parameter | Type | Description | Default |
|---|---|---|---|
url |
string | A2A agent URL | Required |
agent_card_path |
string | Path to agent card endpoint | /.well-known/agent-card.json |
task_timeout |
int | Task timeout in seconds | 300 |
include_skills_in_description |
boolean | Embed discovered skills in function description | true |
auth_provider |
string | Reference to authentication provider | None |
Note: You can get the complete list of configuration options and their schemas by running:
nat info components -t function_group -q a2a_clientYou can connect to multiple A2A agents in the same per-user workflow:
function_groups:
calculator_agent:
_type: a2a_client
url: http://localhost:10000
currency_agent:
_type: a2a_client
url: http://localhost:11000
workflow:
_type: per_user_react_agent # Per-user workflow required for A2A clients
tool_names:
- calculator_agent
- currency_agentNote: All A2A clients in a workflow will be per-user, providing isolated connections for each user.
The A2A client provides three levels of API access, allowing you to choose the right abstraction level for your use case.
flowchart TB
subgraph "Remote A2A Agent"
AC[Agent Card<br/>Skills & Metadata]
end
AC -->|discovers| FG[Function Group<br/>agent_name]
subgraph "Three-Level API"
L1["Level 1: High-Level<br/>agent_name.call(query)<br/>Natural language interface"]
L2["Level 2: Helpers<br/>agent_name.get_skills(), agent_name.get_info(), agent_name.get_task()<br/>Task management utilities"]
L3["Level 3: Low-Level<br/>agent_name.send_message(), agent_name.send_message_streaming()<br/>Raw A2A Protocol access"]
end
FG --> L1
FG --> L2
FG --> L3
style L1 fill:#e1f5e1,color:#000
style L2 fill:#e1e5f5,color:#000
style L3 fill:#f5e1e1,color:#000
Function: agent_name.call(query: str) -> str
The high-level API provides a natural language interface optimized for LLM-based agents. This is the recommended approach for most use cases.
When to use:
- Standard LLM-based agents (most common)
- Simple task delegation
- Agent-as-a-tool pattern
Features:
- Accepts natural language queries
- Skills automatically embedded in function description
- Agent handles skill selection and execution
- Returns string response
Example:
workflow:
_type: react_agent
tool_names:
- currency_agent # Uses high-level .call() functionThe LLM will see a function like:
currency_agent(query: str) -> str
Description: Currency conversion agent with the following skills:
- convert_currency: Convert between currencies
- get_exchange_rate: Get current exchange rates
Functions:
agent_name.get_skills()- List available skillsagent_name.get_info()- Get agent metadataagent_name.get_task(task_id)- Get task statusagent_name.cancel_task(task_id)- Cancel a running task
When to use:
- Task management and monitoring
- Metadata queries
- Building custom orchestration logic
Example:
# Get available skills
skills = await agent.get_skills()
# Get agent information
info = await agent.get_info()Functions:
agent_name.send_message(query, task_id, context_id)- Send message and get eventsagent_name.send_message_streaming(query, task_id, context_id)- Stream events
When to use:
- Custom agents needing full protocol control
- Advanced task management
- Direct access to A2A events
Example:
# Direct protocol access
events = await agent.send_message(
query="Convert 100 USD to EUR",
task_id=None,
context_id=None
)The A2A client discovers agent capabilities through the Agent Card and creates a function interface for interacting with them. The following diagram shows the complete discovery and mapping process:
flowchart TB
subgraph A2A["A2A Agent Card Discovery"]
AC[AgentCard<br/>name: Dice Agent<br/>url: http://localhost:9999<br/>version: 1.0.0<br/>description: Roll dice and get random numbers]
S1[Skill: roll_dice<br/>description: Roll N-sided dice<br/>examples: Roll 2d6, Roll 1d20]
S2[Skill: random_number<br/>description: Generate random numbers<br/>examples: Random between 1-100]
AC --> S1
AC --> S2
end
AC ==>|discovers & maps to| FG[Function Group<br/>dice_agent]
subgraph "Three-Level API"
L1["Level 1: High-Level<br/>dice_agent.call(query)<br/>Natural language interface<br/>Skills optionally embedded in description"]
L2["Level 2: Helpers<br/>dice_agent.get_skills(), dice_agent.get_info()<br/>dice_agent.get_task(), dice_agent.cancel_task()<br/>Task management utilities"]
L3["Level 3: Low-Level<br/>dice_agent.send_message(), dice_agent.send_message_streaming()<br/>Raw A2A Protocol access with task and context IDs"]
end
FG --> L1
FG --> L2
FG --> L3
S1 -.->|embedded in description| L1
S2 -.->|embedded in description| L1
style L1 fill:#e1f5e1,color:#000
style L2 fill:#e1e5f5,color:#000
style L3 fill:#f5e1e1,color:#000
Discovery Process:
- Client fetches Agent Card from
{url}/.well-known/agent-card.json - Parses agent metadata (name, version, description)
- Extracts skills with their descriptions and examples
- Maps skills to a function group with three API levels
- Optionally embeds skill details in high-level function description
The A2A client uses the transport protocol specified in the agent's Agent Card. The A2A Python SDK automatically selects the appropriate transport based on the agent's capabilities. Default transport is JSON-RPC over HTTP.
Coming Soon:
- Explicit transport configuration options
- Support for additional transport protocols (gRPC, HTTP/REST)
The A2A client automatically enables streaming support when connecting to agents. Streaming is handled at the protocol level through the low-level send_message_streaming() function, which yields events as they arrive from the remote agent.
For most use cases, the high-level call() function is sufficient. Use send_message_streaming() only when you need direct access to streaming events.
The following examples demonstrate A2A client usage:
- Math Assistant A2A Example - A2A communication with hybrid tool composition. Refer to
examples/A2A/math_assistant_a2a/README.md. - Currency Agent A2A Example - Connecting to external third-party A2A services. See
examples/A2A/currency_agent_a2a/README.md.
The A2A client includes CLI utilities for testing and debugging.
Quick reference:
# Discover an A2A agent
nat a2a client discover --url http://localhost:10000
# call the agent
nat a2a client call --url http://localhost:10000 --message "Your query here"The discover command connects to an A2A agent and displays its Agent Card, which contains information about capabilities, skills, and configuration.
Basic usage:
nat a2a client discover --url $A2A_SERVER_URLCall an A2A agent with a message and get a response. This is useful for quick testing and one-off queries.
Usage:
nat a2a client call --url $A2A_SERVER_URL --message "What is 2 + 2?"Output example:
Query: What is 2 + 2?
The sum of 2 and 2 is 4.
(0.85s)
Agent Not Reachable:
# Verify agent is running and accessible
curl http://localhost:10000/.well-known/agent-card.json | jqTimeouts:
- Increase
task_timeoutin configuration - Check network latency to remote agent
The A2A client is built on the official A2A Python SDK to ensure protocol compliance. For detailed protocol specifications, refer to the A2A Protocol Documentation.
- A2A Server Guide - Publishing workflows as A2A agents
- Function Groups - Understanding function groups
