Skip to content

Commit 79aac23

Browse files
committed
few fixes and improvements
1 parent 0fcafad commit 79aac23

1 file changed

Lines changed: 60 additions & 68 deletions

File tree

docs/migrations/v1_0/README.md

Lines changed: 60 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ dependencies = ["a2a-sdk>=1.0.0"]
3939
Types are now **Protobuf-based** instead of Pydantic models.
4040

4141

42-
### Enum values: kebab-case → SCREAMING_SNAKE_CASE
42+
### Enum values: snake_case → SCREAMING_SNAKE_CASE
4343

44-
All enum values have been renamed from kebab-case strings to `SCREAMING_SNAKE_CASE`.
44+
All enum values have been renamed from snake_case strings to `SCREAMING_SNAKE_CASE`.
4545

4646
This affects every enum in the SDK: `TaskState`, `Role`.
4747

@@ -60,6 +60,8 @@ This affects every enum in the SDK: `TaskState`, `Role`.
6060
| `Role` | `Role.user` | `Role.ROLE_USER` |
6161
| `Role` | `Role.agent` | `Role.ROLE_AGENT` |
6262

63+
> **Example**: [`a2a-mcp-without-framework/server/agent_executor.py` in PR #509](https://github.com/a2aproject/a2a-samples/pull/509/changes#diff-1f9b098f9f82ee40666ee61db56dc2246281423c445bcf017079c53a0a05954f)
64+
6365
### Message and Part construction
6466

6567
**Before (v0.3):**
@@ -100,13 +102,18 @@ Key differences:
100102
- `Role.user``Role.ROLE_USER`, `Role.agent``Role.ROLE_AGENT`
101103
- `TextPart` is no longer needed; use `Part(text=...)` directly
102104

105+
> **Example**: [`helloworld/test_client.py` in PR #474](https://github.com/a2aproject/a2a-samples/pull/474/files#diff-f62c07d3b00364a3100b7effb3e2a1cca0624277d3e40da1bdb07bb46b6a8cef)
106+
103107
### AgentCard Structure
104108

105109
The `AgentCard` has been significantly restructured to support multiple transport interfaces.
106110

107-
#### `url``supported_interfaces`
108-
109-
The top-level `url` field is replaced by a list of `AgentInterface` objects, each describing a specific transport endpoint.
111+
Key differences:
112+
- `url` is gone; use `supported_interfaces` with one or more `AgentInterface` entries
113+
- `AgentCapabilities.input_modes` and `AgentCapabilities.output_modes` are removed from `AgentCapabilities`; use `AgentCard.default_input_modes` / `AgentCard.default_output_modes` for card-level defaults, or `AgentSkill.input_modes` / `AgentSkill.output_modes` for per-skill overrides
114+
- `supports_authenticated_extended_card` is no longer a top-level `AgentCard` field; it has moved into `AgentCapabilities` and is renamed to `extended_agent_card`
115+
- `AgentInterface.protocol_binding` accepted values: `'JSONRPC'`, `'HTTP+JSON'`, `'GRPC'`
116+
- `examples` field has moved to `AgentSkill.examples` (set it per skill instead)
110117

111118
**Before (v0.3):**
112119
```python
@@ -117,15 +124,16 @@ agent_card = AgentCard(
117124
description='...',
118125
url='http://localhost:9999/',
119126
version='1.0.0',
120-
default_input_modes=['text'],
121-
default_output_modes=['text'],
127+
default_input_modes=['text/plain'],
128+
default_output_modes=['text/plain'],
122129
supports_authenticated_extended_card=True,
123130
capabilities=AgentCapabilities(
124-
input_modes=['text'],
125-
output_modes=['text'],
131+
input_modes=['text/plain'],
132+
output_modes=['text/plain'],
126133
streaming=True,
127134
),
128135
skills=[skill],
136+
examples=['example'],
129137
)
130138
```
131139

@@ -143,8 +151,8 @@ agent_card = AgentCard(
143151
)
144152
],
145153
version='1.0.0',
146-
default_input_modes=['text'],
147-
default_output_modes=['text'],
154+
default_input_modes=['text/plain'],
155+
default_output_modes=['text/plain'],
148156
capabilities=AgentCapabilities(
149157
streaming=True,
150158
extended_agent_card=True,
@@ -153,11 +161,7 @@ agent_card = AgentCard(
153161
)
154162
```
155163

156-
Key differences:
157-
- `url` is gone; use `supported_interfaces` with one or more `AgentInterface` entries
158-
- `AgentCapabilities.input_modes` and `AgentCapabilities.output_modes` are removed
159-
- `supports_authenticated_extended_card` is no longer a top-level `AgentCard` field; it has moved into `AgentCapabilities` and is renamed to `extended_agent_card`
160-
- `AgentInterface.protocol_binding` accepted values: `'JSONRPC'`, `'HTTP_JSON'`, `'GRPC'`
164+
> **Example**: [`a2a-mcp-without-framework/server/__main__.py` in PR #509](https://github.com/a2aproject/a2a-samples/pull/509/files#diff-d15d39ae64c3d4e3a36cc6fb442302caf4e32a6dbd858792e7a4bed180a625ac)
161165
162166
---
163167

@@ -184,6 +188,8 @@ request_handler = DefaultRequestHandler(
184188
)
185189
```
186190

191+
> **Example**: [`a2a-mcp-without-framework/server/__main__.py` in PR #509](https://github.com/a2aproject/a2a-samples/pull/509/files#diff-d15d39ae64c3d4e3a36cc6fb442302caf4e32a6dbd858792e7a4bed180a625ac)
192+
187193
---
188194

189195
## 4. Server: Application Setup
@@ -231,11 +237,13 @@ app = Starlette(routes=routes)
231237
uvicorn.run(app, host=host, port=port)
232238
```
233239

240+
> **Example**: [`a2a-mcp-without-framework/server/__main__.py` in PR #509](https://github.com/a2aproject/a2a-samples/pull/509/files#diff-d15d39ae64c3d4e3a36cc6fb442302caf4e32a6dbd858792e7a4bed180a625ac)
241+
234242
---
235243

236244
## 5. Client: Creating a Client
237245

238-
The `A2AClient` class has been removed. Use the new `create_client()` factory function or `ClientFactory`.
246+
The `A2AClient` class has been removed. Use the new `create_client()` factory function.
239247

240248
### Simple usage: `create_client()`
241249

@@ -256,34 +264,18 @@ async with httpx.AsyncClient() as httpx_client:
256264
from a2a.client import create_client
257265

258266
# From URL — resolves the agent card automatically
259-
async with await create_client('http://localhost:9999/') as client:
267+
client = await create_client('http://localhost:9999/')
268+
async with client:
260269
# use client...
261270

262271
# From an already-resolved AgentCard
263-
async with await create_client(agent_card) as client:
272+
client = await create_client(agent_card)
273+
async with client:
264274
# use client...
265275
```
266276

267-
### Advanced usage: `ClientFactory`
268-
269-
For reusing connections across multiple agents, registering custom transports, or configuring timeouts:
270-
271-
```python
272-
from a2a.client import ClientFactory, ClientConfig
273-
274-
config = ClientConfig(streaming=True)
275-
factory = ClientFactory(config)
276-
277-
# Create from URL (async)
278-
client = await factory.create_from_url('http://localhost:9999/')
279-
280-
# Create from AgentCard (sync)
281-
client = factory.create(agent_card)
282-
```
283-
284-
### `ClientTaskManager` and `Consumers` removed
285277

286-
The `ClientTaskManager` class and `Consumers` abstraction have been removed. Response handling is now done directly by iterating the stream returned from `send_message()`.
278+
> **Example**: [`a2a-mcp-without-framework/client/agent.py` in PR #509](https://github.com/a2aproject/a2a-samples/pull/509/files#diff-56cfce97ff9686166e4b14790ffb7ed46f4c14519261ce5c18365a53cf05e9aa) (`create_client()` usage)
287279
288280
---
289281

@@ -297,7 +289,7 @@ There is now a single `send_message()` method on the client that returns a strea
297289
```python
298290
from a2a.types import (
299291
Message, MessageSendParams, Part, Role, SendStreamingMessageRequest,
300-
SendStreamingMessageSuccessResponse, TaskStatusUpdateEvent, TextPart,
292+
TextPart,
301293
)
302294
from uuid import uuid4
303295

@@ -311,39 +303,42 @@ message_params = MessageSendParams(
311303
)
312304
request = SendStreamingMessageRequest(id=uuid4().hex, params=message_params)
313305

314-
async for chunk in client.send_message_streaming(request):
315-
if isinstance(chunk.root, SendStreamingMessageSuccessResponse) and \
316-
isinstance(chunk.root.result, TaskStatusUpdateEvent):
317-
msg = chunk.root.result.status.message
318-
if msg:
319-
print(msg.parts[0].root.text)
306+
response = client.send_message_streaming(request)
307+
320308
```
321309

322310
**After (v1.0):**
323311
```python
324-
from a2a.helpers import get_artifact_text, new_text_message
325-
from a2a.types import SendMessageRequest
312+
from a2a.types import (
313+
Message, Part, Role, SendMessageRequest,
314+
)
315+
from uuid import uuid4
326316

327-
message = new_text_message(text=user_input)
317+
parts = [Part(text=user_input)]
318+
message = Message(
319+
role=Role.ROLE_USER,
320+
parts=parts,
321+
message_id=uuid4().hex,
322+
)
328323
request = SendMessageRequest(message=message)
329324

330325
async for chunk in client.send_message(request):
331326
if chunk.HasField('artifact_update'):
332-
text = get_artifact_text(chunk.artifact_update.artifact)
333-
if text:
334-
print(text)
327+
print(get_artifact_text(chunk.artifact_update.artifact))
335328
elif chunk.HasField('status_update'):
336-
# handle status updates
337-
...
329+
print(chunk.status_update.status.state)
338330
```
339331

340332
Key differences:
341333
- `send_message_streaming()``send_message()` (unified method)
342334
- `SendStreamingMessageRequest``SendMessageRequest`
343335
- `MessageSendParams` wrapper is gone; `message` is a field directly on `SendMessageRequest`
344-
- Response chunks are `StreamResponse` proto messages; use `HasField()` to check the payload type
336+
- `send_message()` returns `AsyncIterator[StreamResponse]`; iterate with `async for`
337+
- Each `StreamResponse` has a `payload` oneof — use `HasField()` to check which field is set (`'task'`, `'message'`, `'status_update'`, `'artifact_update'`)
345338
- Agent outputs should now be published as **Artifacts**, not status message text
346339

340+
> **Example**: [`helloworld/test_client.py` in PR #474](https://github.com/a2aproject/a2a-samples/pull/474/files#diff-f62c07d3b00364a3100b7effb3e2a1cca0624277d3e40da1bdb07bb46b6a8cef)
341+
347342
---
348343

349344
## 7. Client: Push Notifications Config
@@ -368,26 +363,23 @@ config = ClientConfig(
368363

369364
## 8. Helper Utilities
370365

371-
A new `a2a.helpers` module provides convenience functions previously scattered across `a2a.utils.*` and adds new helpers for v1.0 proto types.
366+
A new `a2a.helpers` module consolidates helper functions into a single import. Most were previously available under `a2a.utils.*`; a few are new in v1.0.
372367

373368
```python
374369
from a2a.helpers import (
375-
# --- moved from a2a.utils.* ---
376-
new_text_message, # was a2a.utils.message.new_agent_text_message; gained role param
377-
new_message, # was a2a.utils.message.new_agent_parts_message; gained role param
378-
get_message_text, # was a2a.utils.message.get_message_text
379-
new_text_artifact, # was a2a.utils.artifact.new_text_artifact; gained artifact_id param
380-
new_artifact, # was a2a.utils.artifact.new_artifact; gained artifact_id param
381-
get_artifact_text, # was a2a.utils.artifact.get_artifact_text
382-
get_text_parts, # was a2a.utils.parts.get_text_parts
383-
new_task_from_user_message, # was a2a.utils.task.new_task; renamed, now validates role == ROLE_USER
384-
385-
# --- new in v1.0 ---
370+
display_agent_card, # print a human-readable summary of an AgentCard to stdout
371+
get_artifact_text, # join all text parts of an Artifact into a single string (delimiter='\n')
372+
get_message_text, # join all text parts of a Message into a single string (delimiter='\n')
373+
get_stream_response_text, # extract text from a StreamResponse proto message
374+
get_text_parts, # return a list of raw text strings from a sequence of Parts (skips non-text parts)
375+
new_artifact, # create an Artifact from a list of Parts, name, optional description and artifact_id
376+
new_message, # create a Message from a list of Parts with role (default ROLE_AGENT), optional task_id/context_id
386377
new_task, # create a Task with explicit task_id, context_id, and state
378+
new_task_from_user_message, # create a TASK_STATE_SUBMITTED Task from a user Message; raises if role != ROLE_USER or parts are empty
379+
new_text_artifact, # create an Artifact with a single text Part, name, optional description and artifact_id
387380
new_text_artifact_update_event, # create a TaskArtifactUpdateEvent with a text artifact
381+
new_text_message, # create a Message with a single text Part; role defaults to ROLE_AGENT
388382
new_text_status_update_event, # create a TaskStatusUpdateEvent with a text message
389-
get_stream_response_text, # extract text from a StreamResponse proto message
390-
display_agent_card, # print a human-readable summary of an AgentCard to stdout
391383
)
392384
```
393385

0 commit comments

Comments
 (0)