a2a 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.agent-docs/ROADMAP.md +423 -0
- data/.agent-docs/index.md +124 -0
- data/.agent-docs/llms.txt +318 -0
- data/.agent-docs/specification/json.json +2575 -0
- data/.agent-docs/specification.md +1924 -0
- data/.agent-docs/topics/a2a-and-mcp.md +132 -0
- data/.agent-docs/topics/agent-discovery.md +96 -0
- data/.agent-docs/topics/enterprise-ready.md +139 -0
- data/.agent-docs/topics/extensions.md +260 -0
- data/.agent-docs/topics/key-concepts.md +99 -0
- data/.agent-docs/topics/life-of-a-task.md +255 -0
- data/.agent-docs/topics/streaming-and-async.md +111 -0
- data/.agent-docs/topics/what-is-a2a.md +218 -0
- data/.agent-docs/tutorials/index.md +31 -0
- data/.agent-docs/tutorials/python/1-introduction.md +32 -0
- data/.agent-docs/tutorials/python/2-setup.md +55 -0
- data/.agent-docs/tutorials/python/3-agent-skills-and-card.md +48 -0
- data/.agent-docs/tutorials/python/4-agent-executor.md +57 -0
- data/.agent-docs/tutorials/python/5-start-server.md +55 -0
- data/.agent-docs/tutorials/python/6-interact-with-server.md +95 -0
- data/.agent-docs/tutorials/python/7-streaming-and-multiturn.md +97 -0
- data/.agent-docs/tutorials/python/8-next-steps.md +40 -0
- data/.agent-docs/types.ts +1544 -0
- data/.agent-docs/types_mapping.md +196 -0
- data/.claude/commands/gemfile/update.md +52 -0
- data/.claude/settings.local.json +23 -0
- data/.tool-versions +1 -1
- data/CHANGELOG.md +68 -1
- data/CLAUDE.md +98 -0
- data/README.md +20 -14
- data/Rakefile +1 -3
- data/WARP.md +115 -0
- data/lib/a2a/extensions/json_deserialization.rb +1 -3
- data/lib/a2a/types/agent_capabilities.rb +3 -0
- data/lib/a2a/types/agent_card.rb +49 -17
- data/lib/a2a/types/agent_card_signature.rb +17 -0
- data/lib/a2a/types/agent_extension.rb +19 -0
- data/lib/a2a/types/agent_interface.rb +13 -0
- data/lib/a2a/types/agent_provider.rb +2 -2
- data/lib/a2a/types/agent_skill.rb +11 -4
- data/lib/a2a/types/api_key_security_scheme.rb +15 -0
- data/lib/a2a/types/artifact.rb +10 -15
- data/lib/a2a/types/authenticated_extended_card_not_configured_error.rb +43 -0
- data/lib/a2a/types/authorization_code_oauth_flow.rb +22 -0
- data/lib/a2a/types/cancel_task_request.rb +5 -2
- data/lib/a2a/types/cancel_task_response.rb +3 -3
- data/lib/a2a/types/client_credentials_oauth_flow.rb +16 -0
- data/lib/a2a/types/content_type_not_supported_error.rb +42 -0
- data/lib/a2a/types/data_part.rb +5 -8
- data/lib/a2a/types/delete_task_push_notification_config_params.rb +9 -0
- data/lib/a2a/types/delete_task_push_notification_config_request.rb +18 -0
- data/lib/a2a/types/delete_task_push_notification_config_response.rb +13 -0
- data/lib/a2a/types/error.rb +19 -0
- data/lib/a2a/types/error_codes.rb +6 -0
- data/lib/a2a/types/file_base.rb +12 -0
- data/lib/a2a/types/file_part.rb +7 -9
- data/lib/a2a/types/file_with_bytes.rb +9 -0
- data/lib/a2a/types/file_with_uri.rb +9 -0
- data/lib/a2a/types/get_authenticated_extended_card_request.rb +15 -0
- data/lib/a2a/types/get_authenticated_extended_card_response.rb +13 -0
- data/lib/a2a/types/get_task_push_notification_config_params.rb +9 -0
- data/lib/a2a/types/get_task_push_notification_config_request.rb +21 -0
- data/lib/a2a/types/get_task_push_notification_request.rb +5 -2
- data/lib/a2a/types/get_task_push_notification_response.rb +4 -4
- data/lib/a2a/types/get_task_request.rb +5 -2
- data/lib/a2a/types/get_task_response.rb +3 -3
- data/lib/a2a/types/http_auth_security_scheme.rb +18 -0
- data/lib/a2a/types/implicit_oauth_flow.rb +16 -0
- data/lib/a2a/types/invalid_agent_response_error.rb +41 -0
- data/lib/a2a/types/list_task_push_notification_config_params.rb +8 -0
- data/lib/a2a/types/list_task_push_notification_config_request.rb +18 -0
- data/lib/a2a/types/list_task_push_notification_config_response.rb +13 -0
- data/lib/a2a/types/message.rb +24 -4
- data/lib/a2a/types/message_send_configuration.rb +20 -0
- data/lib/a2a/types/message_send_params.rb +16 -0
- data/lib/a2a/types/mutual_tls_security_scheme.rb +9 -0
- data/lib/a2a/types/oauth2_security_scheme.rb +16 -0
- data/lib/a2a/types/oauth_flows.rb +20 -0
- data/lib/a2a/types/openid_connect_security_scheme.rb +12 -0
- data/lib/a2a/types/part.rb +2 -1
- data/lib/a2a/types/part_base.rb +9 -0
- data/lib/a2a/types/password_oauth_flow.rb +16 -0
- data/lib/a2a/types/push_notification_authentication_info.rb +12 -0
- data/lib/a2a/types/push_notification_config.rb +11 -6
- data/lib/a2a/types/push_notification_not_supported_error.rb +37 -10
- data/lib/a2a/types/request.rb +15 -0
- data/lib/a2a/types/security_scheme.rb +11 -0
- data/lib/a2a/types/security_scheme_base.rb +9 -0
- data/lib/a2a/types/send_message_request.rb +18 -0
- data/lib/a2a/types/send_message_response.rb +13 -0
- data/lib/a2a/types/send_streaming_message_request.rb +18 -0
- data/lib/a2a/types/send_streaming_message_response.rb +15 -0
- data/lib/a2a/types/set_task_push_notification_config_request.rb +18 -0
- data/lib/a2a/types/set_task_push_notification_request.rb +5 -2
- data/lib/a2a/types/set_task_push_notification_response.rb +4 -4
- data/lib/a2a/types/task.rb +15 -11
- data/lib/a2a/types/task_artifact_update_event.rb +18 -7
- data/lib/a2a/types/task_not_cancelable_error.rb +37 -10
- data/lib/a2a/types/task_not_found_error.rb +37 -10
- data/lib/a2a/types/task_resubscription_request.rb +5 -2
- data/lib/a2a/types/task_state.rb +2 -1
- data/lib/a2a/types/task_status_update_event.rb +13 -6
- data/lib/a2a/types/text_part.rb +5 -8
- data/lib/a2a/types/transport_protocol.rb +6 -0
- data/lib/a2a/types/unsupported_operation_error.rb +37 -10
- data/lib/a2a/types.rb +13 -0
- data/lib/a2a/version.rb +1 -1
- data/lib/a2a.rb +15 -5
- metadata +101 -19
- data/lib/a2a/types/agent_authentication.rb +0 -13
- data/lib/a2a/types/authentication_info.rb +0 -9
- data/lib/a2a/types/file_content.rb +0 -18
- data/lib/a2a/types/internal_error.rb +0 -15
- data/lib/a2a/types/invalid_params_error.rb +0 -15
- data/lib/a2a/types/invalid_request_error.rb +0 -15
- data/lib/a2a/types/json_parse_error.rb +0 -15
- data/lib/a2a/types/jsonrpc_error.rb +0 -15
- data/lib/a2a/types/jsonrpc_message.rb +0 -12
- data/lib/a2a/types/jsonrpc_request.rb +0 -15
- data/lib/a2a/types/jsonrpc_response.rb +0 -12
- data/lib/a2a/types/method_not_found_error.rb +0 -15
- data/lib/a2a/types/send_task_request.rb +0 -15
- data/lib/a2a/types/send_task_response.rb +0 -13
- data/lib/a2a/types/send_task_streaming_request.rb +0 -15
- data/lib/a2a/types/send_task_streaming_response.rb +0 -15
- data/lib/a2a/types/task_send_params.rb +0 -26
@@ -0,0 +1,218 @@
|
|
1
|
+
# A2A Protocol Overview
|
2
|
+
|
3
|
+
The A2A protocol is an open standard that enables seamless communication and
|
4
|
+
collaboration between AI agents. It provides a common language for agents built
|
5
|
+
using diverse frameworks and by different vendors, fostering interoperability
|
6
|
+
and breaking down silos. Agents are autonomous problem-solvers that act
|
7
|
+
independently within their environment. A2A allows agents from different
|
8
|
+
developers, built on different frameworks, and owned by different organizations
|
9
|
+
to unite and work together.
|
10
|
+
|
11
|
+
## Why Use the A2A Protocol
|
12
|
+
|
13
|
+
A2A addresses key challenges in AI agent collaboration. It provides
|
14
|
+
a standardized approach for agents to interact. This section explains the
|
15
|
+
problems A2A solves and the benefits it offers.
|
16
|
+
|
17
|
+
### Problems that A2A Solves
|
18
|
+
|
19
|
+
Consider a user request for an AI assistant to plan an international trip. This
|
20
|
+
task involves orchestrating multiple specialized agents, such as:
|
21
|
+
|
22
|
+
- A flight booking agent
|
23
|
+
- A hotel reservation agent
|
24
|
+
- An agent for local tour recommendations
|
25
|
+
- A currency conversion agent
|
26
|
+
|
27
|
+
Without A2A, integrating these diverse agents presents several challenges:
|
28
|
+
|
29
|
+
- **Agent Exposure**: Developers often wrap agents as tools to expose them to
|
30
|
+
other agents, similar to how tools are exposed in a Multi-agent Control
|
31
|
+
Platform (Model Context Protocol). However, this approach is inefficient because agents are
|
32
|
+
designed to negotiate directly. Wrapping agents as tools limits their capabilities.
|
33
|
+
A2A allows agents to be exposed as they are, without requiring this wrapping.
|
34
|
+
- **Custom Integrations**: Each interaction requires custom, point-to-point
|
35
|
+
solutions, creating significant engineering overhead.
|
36
|
+
- **Slow Innovation**: Bespoke development for each new integration slows
|
37
|
+
innovation.
|
38
|
+
- **Scalability Issues**: Systems become difficult to scale and maintain as
|
39
|
+
the number of agents and interactions grows.
|
40
|
+
- **Interoperability**: This approach limits interoperability,
|
41
|
+
preventing the organic formation of complex AI ecosystems.
|
42
|
+
- **Security Gaps**: Ad hoc communication often lacks consistent security
|
43
|
+
measures.
|
44
|
+
|
45
|
+
The A2A protocol addresses these challenges by establishing interoperability for
|
46
|
+
AI agents to interact reliably and securely.
|
47
|
+
|
48
|
+
### A2A Example Scenario
|
49
|
+
|
50
|
+
This section provides an example scenario to illustrate the benefits of using an A2A (Agent2Agent) protocol for complex interactions between AI agents.
|
51
|
+
|
52
|
+
#### A User's Complex Request
|
53
|
+
|
54
|
+
A user interacts with an AI assistant, giving it a complex prompt like "Plan an international trip."
|
55
|
+
|
56
|
+
```mermaid
|
57
|
+
graph LR
|
58
|
+
User --> Prompt --> AI_Assistant[AI Assistant]
|
59
|
+
```
|
60
|
+
|
61
|
+
#### The Need for Collaboration
|
62
|
+
|
63
|
+
The AI assistant receives the prompt and realizes it needs to call upon multiple specialized agents to fulfill the request. These agents include a Flight Booking Agent, a Hotel Reservation Agent, a Currency Conversion Agent, and a Local Tours Agent.
|
64
|
+
|
65
|
+
```mermaid
|
66
|
+
graph LR
|
67
|
+
subgraph "Specialized Agents"
|
68
|
+
FBA[✈️ Flight Booking Agent]
|
69
|
+
HRA[🏨 Hotel Reservation Agent]
|
70
|
+
CCA[💱 Currency Conversion Agent]
|
71
|
+
LTA[🚌 Local Tours Agent]
|
72
|
+
end
|
73
|
+
|
74
|
+
AI_Assistant[🤖 AI Assistant] --> FBA
|
75
|
+
AI_Assistant --> HRA
|
76
|
+
AI_Assistant --> CCA
|
77
|
+
AI_Assistant --> LTA
|
78
|
+
```
|
79
|
+
|
80
|
+
#### The Interoperability Challenge
|
81
|
+
|
82
|
+
The core problem: The agents are unable to work together because each has its own bespoke development and deployment.
|
83
|
+
|
84
|
+
The consequence of a lack of a standardized protocol is that these agents cannot collaborate with each other let alone discover what they can do. The individual agents (Flight, Hotel, Currency, and Tours) are isolated.
|
85
|
+
|
86
|
+
#### The "With A2A" Solution
|
87
|
+
|
88
|
+
The A2A Protocol provides standard methods and data structures for agents to communicate with one another, regardless of their underlying implementation, so the same agents can be used as an interconnected system, communicating seamlessly through the standardized protocol.
|
89
|
+
|
90
|
+
The AI assistant, now acting as an orchestrator, receives the cohesive information from all the A2A-enabled agents. It then presents a single, complete travel plan as a seamless response to the user's initial prompt.
|
91
|
+
|
92
|
+
{ width="70%" style="margin:20px auto;display:block;" }
|
93
|
+
|
94
|
+
### Core Benefits of A2A
|
95
|
+
|
96
|
+
Implementing the A2A protocol offers significant advantages across the AI ecosystem:
|
97
|
+
|
98
|
+
- **Secure collaboration**: Without a standard, it's difficult to ensure
|
99
|
+
secure communication between agents. A2A uses HTTPS for secure communication
|
100
|
+
and maintains opaque operations, so agents can't see the inner workings of
|
101
|
+
other agents during collaboration.
|
102
|
+
- **Interoperability**: A2A breaks down silos between different AI
|
103
|
+
agent ecosystems, enabling agents from various vendors and frameworks to work
|
104
|
+
together seamlessly.
|
105
|
+
- **Agent autonomy**: A2A allows agents to retain their individual capabilities
|
106
|
+
and act as autonomous entities while collaborating with other agents.
|
107
|
+
- **Reduced integration complexity**: The protocol standardizes agent
|
108
|
+
communication, enabling teams to focus on the unique value their agents
|
109
|
+
provide.
|
110
|
+
- **Support for LRO**: The protocol supports long-running operations (LRO) and
|
111
|
+
streaming with Server-Sent Events (SSE) and asynchronous execution.
|
112
|
+
|
113
|
+
### Key Design Principles of A2A
|
114
|
+
|
115
|
+
A2A development follows principles that prioritize broad adoption,
|
116
|
+
enterprise-grade capabilities, and future-proofing.
|
117
|
+
|
118
|
+
- **Simplicity**: A2A leverages existing standards like HTTP, JSON-RPC, and
|
119
|
+
Server-Sent Events (SSE). This avoids reinventing core technologies and
|
120
|
+
accelerates developer adoption.
|
121
|
+
- **Enterprise Readiness**: A2A addresses critical enterprise needs. It aligns
|
122
|
+
with standard web practices for robust authentication, authorization,
|
123
|
+
security, privacy, tracing, and monitoring.
|
124
|
+
- **Asynchronous**: A2A natively supports long-running tasks. It handles
|
125
|
+
scenarios where agents or users might not remain continuously connected. It
|
126
|
+
uses mechanisms like streaming and push notifications.
|
127
|
+
- **Modality Independent**: The protocol allows agents to communicate using a
|
128
|
+
wide variety of content types. This enables rich and flexible interactions
|
129
|
+
beyond plain text.
|
130
|
+
- **Opaque Execution**: Agents collaborate effectively without exposing their
|
131
|
+
internal logic, memory, or proprietary tools. Interactions rely on declared
|
132
|
+
capabilities and exchanged context. This preserves intellectual property and
|
133
|
+
enhances security.
|
134
|
+
|
135
|
+
### Understanding the Agent Stack: A2A, MCP, Agent Frameworks and Models
|
136
|
+
|
137
|
+
A2A is situated within a broader agent stack, which includes:
|
138
|
+
|
139
|
+
- **A2A:** Standardizes communication among agents deployed in different organizations and developed using diverse frameworks.
|
140
|
+
- **MCP:** Connects models to data and external resources.
|
141
|
+
- **Frameworks (like ADK):** Provide toolkits for constructing agents.
|
142
|
+
- **Models:** Fundamental to an agent's reasoning, these can be any Large Language Model (LLM).
|
143
|
+
|
144
|
+
{ width="70%" style="margin:20px auto;display:block;" }
|
145
|
+
|
146
|
+
#### A2A and MCP
|
147
|
+
|
148
|
+
In the broader ecosystem of AI communication, you might be familiar with protocols designed to facilitate interactions between agents, models, and tools. Notably, the Model Context Protocol (MCP) is an emerging standard focused on connecting Large Language Models (LLMs) with data and external resources.
|
149
|
+
|
150
|
+
The Agent2Agent (A2A) protocol is designed to standardize communication between AI agents, particularly those deployed in external systems. A2A is positioned to complement MCP, addressing a distinct yet related aspect of agent interaction.
|
151
|
+
|
152
|
+
- **MCP's Focus:** Reducing the complexity involved in connecting agents with tools and data. Tools are typically stateless and perform specific, predefined functions (e.g., a calculator, a database query).
|
153
|
+
- **A2A's Focus:** Enabling agents to collaborate within their native modalities, allowing them to communicate as agents (or as users) rather than being constrained to tool-like interactions. This enables complex, multi-turn interactions where agents reason, plan, and delegate tasks to other agents. For example, this facilitates multi-turn interactions, such as those involving negotiation or clarification when placing an order.
|
154
|
+
|
155
|
+
{ width="70%" style="margin:20px auto;display:block;" }
|
156
|
+
|
157
|
+
The practice of encapsulating an agent as a simple tool is fundamentally limiting, as it fails to capture the agent's full capabilities. This critical distinction is explored in the post, [Why Agents Are Not Tools](https://discuss.google.dev/t/agents-are-not-tools/192812).
|
158
|
+
|
159
|
+
For a more in-depth comparison, refer to the [A2A and MCP Comparison](a2a-and-mcp.md) document.
|
160
|
+
|
161
|
+
#### A2A and ADK
|
162
|
+
|
163
|
+
The [Agent Development Kit (ADK)](https://google.github.io/adk-docs)
|
164
|
+
is an open-source agent development toolkit developed by Google. A2A is a
|
165
|
+
communication protocol for agents that enables inter-agent communication,
|
166
|
+
regardless of the framework used for their construction (e.g., ADK, LangGraph,
|
167
|
+
or Crew AI). ADK is a flexible and modular framework for developing and
|
168
|
+
deploying AI agents. While optimized for Gemini AI and the Google ecosystem,
|
169
|
+
ADK is model-agnostic, deployment-agnostic, and built for compatibility with
|
170
|
+
other frameworks.
|
171
|
+
|
172
|
+
### A2A Request Lifecycle
|
173
|
+
|
174
|
+
The A2A request lifecycle is a sequence that details the four main steps a request follows: agent discovery, authentication, `sendMessage` API, and `sendMessageStream` API. The following diagram provides a deeper look into the operational flow, illustrating the interactions between the client, A2A server, and auth server.
|
175
|
+
|
176
|
+
```mermaid
|
177
|
+
sequenceDiagram
|
178
|
+
participant Client
|
179
|
+
participant A2A Server
|
180
|
+
participant Auth Server
|
181
|
+
|
182
|
+
rect rgb(240, 240, 240)
|
183
|
+
Note over Client, A2A Server: 1. Agent Discovery
|
184
|
+
Client->>A2A Server: GET agent card eg: (/.well-known/agent-card)
|
185
|
+
A2A Server-->>Client: Returns Agent Card
|
186
|
+
end
|
187
|
+
|
188
|
+
rect rgb(240, 240, 240)
|
189
|
+
Note over Client, Auth Server: 2. Authentication
|
190
|
+
Client->>Client: Parse Agent Card for securitySchemes
|
191
|
+
alt securityScheme is "openIdConnect"
|
192
|
+
Client->>Auth Server: Request token based on "authorizationUrl" and "tokenUrl".
|
193
|
+
Auth Server-->>Client: Returns JWT
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
rect rgb(240, 240, 240)
|
198
|
+
Note over Client, A2A Server: 3. sendMessage API
|
199
|
+
Client->>Client: Parse Agent Card for "url" param to send API requests to.
|
200
|
+
Client->>A2A Server: POST /sendMessage (with JWT)
|
201
|
+
A2A Server->>A2A Server: Process message and create task
|
202
|
+
A2A Server-->>Client: Returns Task Response
|
203
|
+
end
|
204
|
+
|
205
|
+
rect rgb(240, 240, 240)
|
206
|
+
Note over Client, A2A Server: 4. sendMessageStream API
|
207
|
+
Client->>A2A Server: POST /sendMessageStream (with JWT)
|
208
|
+
A2A Server-->>Client: Stream: Task (Submitted)
|
209
|
+
A2A Server-->>Client: Stream: TaskStatusUpdateEvent (Working)
|
210
|
+
A2A Server-->>Client: Stream: TaskArtifactUpdateEvent (artifact A)
|
211
|
+
A2A Server-->>Client: Stream: TaskArtifactUpdateEvent (artifact B)
|
212
|
+
A2A Server-->>Client: Stream: TaskStatusUpdateEvent (Completed)
|
213
|
+
end
|
214
|
+
```
|
215
|
+
|
216
|
+
## What's Next
|
217
|
+
|
218
|
+
Learn about the [Key Concepts](./key-concepts.md) that form the foundation of the A2A protocol.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Tutorials
|
2
|
+
|
3
|
+
## Python
|
4
|
+
|
5
|
+
Tutorial | Description | Difficulty
|
6
|
+
:--------|:------------|:-----------
|
7
|
+
[A2A and Python Quickstart](./python/1-introduction.md) | Learn to build a simple Python-based "echo" A2A server and client. | Easy
|
8
|
+
[ADK facts](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/adk_facts) | Build and test a simple Personal Assistant agent using the Agent Development Kit (ADK) that can provide interesting facts. | Easy
|
9
|
+
[ADK agent on Cloud Run](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/adk_cloud_run) | Deploy, manage, and observe an ADK-based agent as a scalable, serverless service on Google Cloud Run.| Easy
|
10
|
+
[Multi-agent collaboration using A2A](https://github.com/a2aproject/a2a-samples/tree/main/demo) | Learn how to set up an orchestrator (host agent) that routes and manages requests among several specialized A2A-compatible agents. | Easy
|
11
|
+
[Airbnb and weather multi-agent](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/airbnb_planner_multiagent) | Build a complex multi-agent system where agents collaborate using A2A to plan a trip, finding both Airbnb accommodations and weather information. | Medium
|
12
|
+
[A2A Client-Server example using remote ADK agent](https://goo.gle/adk-a2a) | Learn how a local A2A client agent discovers and consumes the capabilities of a separate, remote ADK-based agent (for example, a prime number checker). | Easy
|
13
|
+
[Colab Notebook](https://github.com/a2aproject/a2a-samples/blob/main/notebooks/multi_agents_eval_with_cloud_run_deployment.ipynb) | Use Colab Notebook to deploy A2A agents to Cloud Run from your browser, and then evaluate their performance with Vertex AI. | Easy
|
14
|
+
|
15
|
+
## Java
|
16
|
+
|
17
|
+
Tutorial | Description
|
18
|
+
:--------|:-----------
|
19
|
+
[Multi-language translator agent using Java](https://github.com/a2aproject/a2a-samples/tree/main/samples/java) | Implement the A2A protocol using Java SDK to create an interactive language translation service.
|
20
|
+
|
21
|
+
## JavaScript
|
22
|
+
|
23
|
+
Tutorial | Description
|
24
|
+
:--------|:------------
|
25
|
+
[Movie research agent using JavaScript](https://github.com/a2aproject/a2a-samples/tree/main/samples/js) | Build an A2A agent with Node.js that uses the TMDB (The Movie Database) API to handle movie searches and queries.
|
26
|
+
|
27
|
+
## C#/.NET
|
28
|
+
|
29
|
+
Tutorial | Description
|
30
|
+
:--------|:------------
|
31
|
+
[All .NET samples](https://github.com/a2aproject/a2a-dotnet/tree/main/samples) | Repository of foundational samples showing how to build A2A clients and servers, including an Echo Agent, using the C#/.NET SDK.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Python Quickstart Tutorial: Building an A2A Agent
|
2
|
+
|
3
|
+
Welcome to the Agent2Agent (A2A) Python Quickstart Tutorial!
|
4
|
+
|
5
|
+
In this tutorial, you will explore a simple "echo" A2A server using the Python SDK. This will introduce you to the fundamental concepts and components of an A2A server. You will then look at a more advanced example that integrates a Large Language Model (LLM).
|
6
|
+
|
7
|
+
This hands-on guide will help you understand:
|
8
|
+
|
9
|
+
- The basic concepts behind the A2A protocol.
|
10
|
+
- How to set up a Python environment for A2A development using the SDK.
|
11
|
+
- How Agent Skills and Agent Cards describe an agent.
|
12
|
+
- How an A2A server handles tasks.
|
13
|
+
- How to interact with an A2A server using a client.
|
14
|
+
- How streaming capabilities and multi-turn interactions work.
|
15
|
+
- How an LLM can be integrated into an A2A agent.
|
16
|
+
|
17
|
+
By the end of this tutorial, you will have a functional understanding of A2A agents and a solid foundation for building or integrating A2A-compliant applications.
|
18
|
+
|
19
|
+
## Tutorial Sections
|
20
|
+
|
21
|
+
The tutorial is broken down into the following steps:
|
22
|
+
|
23
|
+
1. **[Introduction (This Page)](./1-introduction.md)**
|
24
|
+
2. **[Setup](./2-setup.md)**: Prepare your Python environment and the A2A SDK.
|
25
|
+
3. **[Agent Skills & Agent Card](./3-agent-skills-and-card.md)**: Define what your agent can do and how it describes itself.
|
26
|
+
4. **[The Agent Executor](./4-agent-executor.md)**: Understand how the agent logic is implemented.
|
27
|
+
5. **[Starting the Server](./5-start-server.md)**: Run the Helloworld A2A server.
|
28
|
+
6. **[Interacting with the Server](./6-interact-with-server.md)**: Send requests to your agent.
|
29
|
+
7. **[Streaming & Multi-Turn Interactions](./7-streaming-and-multiturn.md)**: Explore advanced capabilities with the LangGraph example.
|
30
|
+
8. **[Next Steps](./8-next-steps.md)**: Explore further possibilities with A2A.
|
31
|
+
|
32
|
+
Let's get started!
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# 2. Setup Your Environment
|
2
|
+
|
3
|
+
## Prerequisites
|
4
|
+
|
5
|
+
- Python 3.10 or higher.
|
6
|
+
- Access to a terminal or command prompt.
|
7
|
+
- Git, for cloning the repository.
|
8
|
+
- A code editor (e.g., Visual Studio Code) is recommended.
|
9
|
+
|
10
|
+
## Clone the Repository
|
11
|
+
|
12
|
+
If you haven't already, clone the A2A Samples repository:
|
13
|
+
|
14
|
+
```bash
|
15
|
+
git clone https://github.com/a2aproject/a2a-samples.git -b main --depth 1
|
16
|
+
cd a2a-samples
|
17
|
+
```
|
18
|
+
|
19
|
+
## Python Environment & SDK Installation
|
20
|
+
|
21
|
+
We recommend using a virtual environment for Python projects. The A2A Python SDK uses `uv` for dependency management, but you can use `pip` with `venv` as well.
|
22
|
+
|
23
|
+
1. **Create and activate a virtual environment:**
|
24
|
+
|
25
|
+
Using `venv` (standard library):
|
26
|
+
|
27
|
+
=== "Mac/Linux"
|
28
|
+
|
29
|
+
```sh
|
30
|
+
python -m venv .venv
|
31
|
+
source .venv/bin/activate
|
32
|
+
```
|
33
|
+
|
34
|
+
=== "Windows"
|
35
|
+
|
36
|
+
```powershell
|
37
|
+
python -m venv .venv
|
38
|
+
.venv\Scripts\activate
|
39
|
+
```
|
40
|
+
|
41
|
+
2. **Install needed Python dependencies along with the A2A SDK and its dependencies:**
|
42
|
+
|
43
|
+
```bash
|
44
|
+
pip install -r samples/python/requirements.txt
|
45
|
+
```
|
46
|
+
|
47
|
+
## Verify Installation
|
48
|
+
|
49
|
+
After installation, you should be able to import the `a2a` package in a Python interpreter:
|
50
|
+
|
51
|
+
```bash
|
52
|
+
python -c "import a2a; print('A2A SDK imported successfully')"
|
53
|
+
```
|
54
|
+
|
55
|
+
If this command runs without error and prints the success message, your environment is set up correctly.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# 3. Agent Skills & Agent Card
|
2
|
+
|
3
|
+
Before an A2A agent can do anything, it needs to define what it _can_ do (its skills) and how other agents or clients can find out about these capabilities (its Agent Card).
|
4
|
+
|
5
|
+
We'll use the `helloworld` example located in [`a2a-samples/samples/python/agents/helloworld/`](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/helloworld).
|
6
|
+
|
7
|
+
## Agent Skills
|
8
|
+
|
9
|
+
An **Agent Skill** describes a specific capability or function the agent can perform. It's a building block that tells clients what kinds of tasks the agent is good for.
|
10
|
+
|
11
|
+
Key attributes of an `AgentSkill` (defined in `a2a.types`):
|
12
|
+
|
13
|
+
- `id`: A unique identifier for the skill.
|
14
|
+
- `name`: A human-readable name.
|
15
|
+
- `description`: A more detailed explanation of what the skill does.
|
16
|
+
- `tags`: Keywords for categorization and discovery.
|
17
|
+
- `examples`: Sample prompts or use cases.
|
18
|
+
- `inputModes` / `outputModes`: Supported Media Types for input and output (e.g., "text/plain", "application/json").
|
19
|
+
|
20
|
+
In `__main__.py`, you can see how a skill for the Helloworld agent is defined:
|
21
|
+
|
22
|
+
```python { .no-copy }
|
23
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py:AgentSkill"
|
24
|
+
```
|
25
|
+
|
26
|
+
This skill is very simple: it's named "Returns hello world" and primarily deals with text.
|
27
|
+
|
28
|
+
## Agent Card
|
29
|
+
|
30
|
+
The **Agent Card** is a JSON document that an A2A Server makes available, typically at a `.well-known/agent-card.json` endpoint. It's like a digital business card for the agent.
|
31
|
+
|
32
|
+
Key attributes of an `AgentCard` (defined in `a2a.types`):
|
33
|
+
|
34
|
+
- `name`, `description`, `version`: Basic identity information.
|
35
|
+
- `url`: The endpoint where the A2A service can be reached.
|
36
|
+
- `capabilities`: Specifies supported A2A features like `streaming` or `pushNotifications`.
|
37
|
+
- `defaultInputModes` / `defaultOutputModes`: Default Media Types for the agent.
|
38
|
+
- `skills`: A list of `AgentSkill` objects that the agent offers.
|
39
|
+
|
40
|
+
The `helloworld` example defines its Agent Card like this:
|
41
|
+
|
42
|
+
```python { .no-copy }
|
43
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py:AgentCard"
|
44
|
+
```
|
45
|
+
|
46
|
+
This card tells us the agent is named "Hello World Agent", runs at `http://localhost:9999/`, supports text interactions, and has the `hello_world` skill. It also indicates public authentication, meaning no specific credentials are required.
|
47
|
+
|
48
|
+
Understanding the Agent Card is crucial because it's how a client discovers an agent and learns how to interact with it.
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# 4. The Agent Executor
|
2
|
+
|
3
|
+
The core logic of how an A2A agent processes requests and generates responses/events is handled by an **Agent Executor**. The A2A Python SDK provides an abstract base class `a2a.server.agent_execution.AgentExecutor` that you implement.
|
4
|
+
|
5
|
+
## `AgentExecutor` Interface
|
6
|
+
|
7
|
+
The `AgentExecutor` class defines two primary methods:
|
8
|
+
|
9
|
+
- `async def execute(self, context: RequestContext, event_queue: EventQueue)`: Handles incoming requests that expect a response or a stream of events. It processes the user's input (available via `context`) and uses the `event_queue` to send back `Message`, `Task`, `TaskStatusUpdateEvent`, or `TaskArtifactUpdateEvent` objects.
|
10
|
+
- `async def cancel(self, context: RequestContext, event_queue: EventQueue)`: Handles requests to cancel an ongoing task.
|
11
|
+
|
12
|
+
The `RequestContext` provides information about the incoming request, such as the user's message and any existing task details. The `EventQueue` is used by the executor to send events back to the client.
|
13
|
+
|
14
|
+
## Helloworld Agent Executor
|
15
|
+
|
16
|
+
Let's look at `agent_executor.py`. It defines `HelloWorldAgentExecutor`.
|
17
|
+
|
18
|
+
1. **The Agent (`HelloWorldAgent`)**:
|
19
|
+
This is a simple helper class that encapsulates the actual "business logic".
|
20
|
+
|
21
|
+
```python { .no-copy }
|
22
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgent"
|
23
|
+
```
|
24
|
+
|
25
|
+
It has a simple `invoke` method that returns the string "Hello World".
|
26
|
+
|
27
|
+
2. **The Executor (`HelloWorldAgentExecutor`)**:
|
28
|
+
This class implements the `AgentExecutor` interface.
|
29
|
+
|
30
|
+
- **`__init__`**:
|
31
|
+
|
32
|
+
```python { .no-copy }
|
33
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_init"
|
34
|
+
```
|
35
|
+
|
36
|
+
It instantiates the `HelloWorldAgent`.
|
37
|
+
|
38
|
+
- **`execute`**:
|
39
|
+
|
40
|
+
```python { .no-copy }
|
41
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_execute"
|
42
|
+
```
|
43
|
+
|
44
|
+
When a `message/send` or `message/stream` request comes in (both are handled by `execute` in this simplified executor):
|
45
|
+
|
46
|
+
1. It calls `self.agent.invoke()` to get the "Hello World" string.
|
47
|
+
2. It creates an A2A `Message` object using the `new_agent_text_message` utility function.
|
48
|
+
3. It enqueues this message onto the `event_queue`. The underlying `DefaultRequestHandler` will then process this queue to send the response(s) to the client. For a single message like this, it will result in a single response for `message/send` or a single event for `message/stream` before the stream closes.
|
49
|
+
|
50
|
+
- **`cancel`**:
|
51
|
+
The Helloworld example's `cancel` method simply raises an exception, indicating that cancellation is not supported for this basic agent.
|
52
|
+
|
53
|
+
```python { .no-copy }
|
54
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_cancel"
|
55
|
+
```
|
56
|
+
|
57
|
+
The `AgentExecutor` acts as the bridge between the A2A protocol (managed by the request handler and server application) and your agent's specific logic. It receives context about the request and uses an event queue to communicate results or updates back.
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# 5. Starting the Server
|
2
|
+
|
3
|
+
Now that we have an Agent Card and an Agent Executor, we can set up and start the A2A server.
|
4
|
+
|
5
|
+
The A2A Python SDK provides an `A2AStarletteApplication` class that simplifies running an A2A-compliant HTTP server. It uses [Starlette](https://www.starlette.io/) for the web framework and is typically run with an ASGI server like [Uvicorn](https://www.uvicorn.org/).
|
6
|
+
|
7
|
+
## Server Setup in Helloworld
|
8
|
+
|
9
|
+
Let's look at `__main__.py` again to see how the server is initialized and started.
|
10
|
+
|
11
|
+
```python { .no-copy }
|
12
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py"
|
13
|
+
```
|
14
|
+
|
15
|
+
Let's break this down:
|
16
|
+
|
17
|
+
1. **`DefaultRequestHandler`**:
|
18
|
+
|
19
|
+
- The SDK provides `DefaultRequestHandler`. This handler takes your `AgentExecutor` implementation (here, `HelloWorldAgentExecutor`) and a `TaskStore` (here, `InMemoryTaskStore`).
|
20
|
+
- It routes incoming A2A RPC calls to the appropriate methods on your executor (like `execute` or `cancel`).
|
21
|
+
- The `TaskStore` is used by the `DefaultRequestHandler` to manage the lifecycle of tasks, especially for stateful interactions, streaming, and resubscription. Even if your agent executor is simple, the handler needs a task store.
|
22
|
+
|
23
|
+
2. **`A2AStarletteApplication`**:
|
24
|
+
|
25
|
+
- The `A2AStarletteApplication` class is instantiated with the `agent_card` and the `request_handler` (referred to as `http_handler` in its constructor).
|
26
|
+
- The `agent_card` is crucial because the server will expose it at the `/.well-known/agent-card.json` endpoint (by default).
|
27
|
+
- The `request_handler` is responsible for processing all incoming A2A method calls by interacting with your `AgentExecutor`.
|
28
|
+
|
29
|
+
3. **`uvicorn.run(server_app_builder.build(), ...)`**:
|
30
|
+
- The `A2AStarletteApplication` has a `build()` method that constructs the actual Starlette application.
|
31
|
+
- This application is then run using `uvicorn.run()`, making your agent accessible over HTTP.
|
32
|
+
- `host='0.0.0.0'` makes the server accessible on all network interfaces on your machine.
|
33
|
+
- `port=9999` specifies the port to listen on. This matches the `url` in the `AgentCard`.
|
34
|
+
|
35
|
+
## Running the Helloworld Server
|
36
|
+
|
37
|
+
Navigate to the `a2a-samples` directory in your terminal (if you're not already there) and ensure your virtual environment is activated.
|
38
|
+
|
39
|
+
To run the Helloworld server:
|
40
|
+
|
41
|
+
```bash
|
42
|
+
# from the a2a-samples directory
|
43
|
+
python samples/python/agents/helloworld/__main__.py
|
44
|
+
```
|
45
|
+
|
46
|
+
You should see output similar to this, indicating the server is running:
|
47
|
+
|
48
|
+
```console { .no-copy }
|
49
|
+
INFO: Started server process [xxxxx]
|
50
|
+
INFO: Waiting for application startup.
|
51
|
+
INFO: Application startup complete.
|
52
|
+
INFO: Uvicorn running on http://0.0.0.0:9999 (Press CTRL+C to quit)
|
53
|
+
```
|
54
|
+
|
55
|
+
Your A2A Helloworld agent is now live and listening for requests! In the next step, we'll interact with it.
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# 6. Interacting with the Server
|
2
|
+
|
3
|
+
With the Helloworld A2A server running, let's send some requests to it. The SDK includes a client (`A2AClient`) that simplifies these interactions.
|
4
|
+
|
5
|
+
## The Helloworld Test Client
|
6
|
+
|
7
|
+
The `test_client.py` script demonstrates how to:
|
8
|
+
|
9
|
+
1. Fetch the Agent Card from the server.
|
10
|
+
2. Create an `A2AClient` instance.
|
11
|
+
3. Send both non-streaming (`message/send`) and streaming (`message/stream`) requests.
|
12
|
+
|
13
|
+
Open a **new terminal window**, activate your virtual environment, and navigate to the `a2a-samples` directory.
|
14
|
+
|
15
|
+
Activate virtual environment (Be sure to do this in the same directory where you created the virtual environment):
|
16
|
+
|
17
|
+
=== "Mac/Linux"
|
18
|
+
|
19
|
+
```sh
|
20
|
+
source .venv/bin/activate
|
21
|
+
```
|
22
|
+
|
23
|
+
=== "Windows"
|
24
|
+
|
25
|
+
```powershell
|
26
|
+
.venv\Scripts\activate
|
27
|
+
```
|
28
|
+
|
29
|
+
Run the test client:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
# from the a2a-samples directory
|
33
|
+
python samples/python/agents/helloworld/test_client.py
|
34
|
+
```
|
35
|
+
|
36
|
+
## Understanding the Client Code
|
37
|
+
|
38
|
+
Let's look at key parts of `test_client.py`:
|
39
|
+
|
40
|
+
1. **Fetching the Agent Card & Initializing the Client**:
|
41
|
+
|
42
|
+
```python { .no-copy }
|
43
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:A2ACardResolver"
|
44
|
+
```
|
45
|
+
|
46
|
+
The `A2ACardResolver` class is a convenience. It first fetches the `AgentCard` from the server's `/.well-known/agent-card.json` endpoint (based on the provided base URL) and then initializes the client with it.
|
47
|
+
|
48
|
+
2. **Sending a Non-Streaming Message (`send_message`)**:
|
49
|
+
|
50
|
+
```python { .no-copy }
|
51
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:send_message"
|
52
|
+
```
|
53
|
+
|
54
|
+
- The `send_message_payload` constructs the data for `MessageSendParams`.
|
55
|
+
- This is wrapped in a `SendMessageRequest`.
|
56
|
+
- It includes a `message` object with the `role` set to "user" and the content in `parts`.
|
57
|
+
- The Helloworld agent's `execute` method will enqueue a single "Hello World" message. The `DefaultRequestHandler` will retrieve this and send it as the response.
|
58
|
+
- The `response` will be a `SendMessageResponse` object, which contains either a `SendMessageSuccessResponse` (with the agent's `Message` as the result) or a `JSONRPCErrorResponse`.
|
59
|
+
|
60
|
+
3. **Handling Task IDs (Illustrative Note for Helloworld)**:
|
61
|
+
|
62
|
+
The Helloworld client (`test_client.py`) doesn't attempt `get_task` or `cancel_task` directly because the simple Helloworld agent's `execute` method, when called via `message/send`, results in the `DefaultRequestHandler` returning a direct `Message` response rather than a `Task` object. More complex agents that explicitly manage tasks (like the LangGraph example) would return a `Task` object from `message/send`, and its `id` could then be used for `get_task` or `cancel_task`.
|
63
|
+
|
64
|
+
4. **Sending a Streaming Message (`send_message_streaming`)**:
|
65
|
+
|
66
|
+
```python { .no-copy }
|
67
|
+
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:send_message_streaming"
|
68
|
+
```
|
69
|
+
|
70
|
+
- This method calls the agent's `message/stream` endpoint. The `DefaultRequestHandler` will invoke the `HelloWorldAgentExecutor.execute` method.
|
71
|
+
- The `execute` method enqueues one "Hello World" message, and then the event queue is closed.
|
72
|
+
- The client will receive this single message as one `SendStreamingMessageResponse` event, and then the stream will terminate.
|
73
|
+
- The `stream_response` is an `AsyncGenerator`.
|
74
|
+
|
75
|
+
## Expected Output
|
76
|
+
|
77
|
+
When you run `test_client.py`, you'll see JSON outputs for:
|
78
|
+
|
79
|
+
- The non-streaming response (a single "Hello World" message).
|
80
|
+
- The streaming response (a single "Hello World" message as one chunk, after which the stream ends).
|
81
|
+
|
82
|
+
The `id` fields in the output will vary with each run.
|
83
|
+
|
84
|
+
```console { .no-copy }
|
85
|
+
// Non-streaming response
|
86
|
+
{"jsonrpc":"2.0","id":"xxxxxxxx","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"yyyyyyyy"}}
|
87
|
+
// Streaming response (one chunk)
|
88
|
+
{"jsonrpc":"2.0","id":"zzzzzzzz","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"wwwwwwww","final":true}}
|
89
|
+
```
|
90
|
+
|
91
|
+
_(Actual IDs like `xxxxxxxx`, `yyyyyyyy`, `zzzzzzzz`, `wwwwwwww` will be different UUIDs/request IDs)_
|
92
|
+
|
93
|
+
This confirms your server is correctly handling basic A2A interactions with the updated SDK structure!
|
94
|
+
|
95
|
+
Now you can shut down the server by typing Ctrl+C in the terminal window where `__main__.py` is running.
|