Skip to content

Commit ebc4157

Browse files
authored
docs!: update spec & doc topic with non-restartable tasks (#770)
1 parent c2dbd58 commit ebc4157

File tree

5 files changed

+218
-4
lines changed

5 files changed

+218
-4
lines changed

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ objc
169169
octicons
170170
ollama
171171
oneof
172+
pqr
172173
prefecthq
173174
protoc
174175
protolint

docs/specification.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ These objects define the structure of data exchanged within the JSON-RPC methods
316316

317317
### 6.1. `Task` Object
318318

319-
Represents the stateful unit of work being processed by the A2A Server for an A2A Client. A task encapsulates the entire interaction related to a specific goal or request.
319+
Represents the stateful unit of work being processed by the A2A Server for an A2A Client. A task encapsulates the entire interaction related to a specific goal or request. A task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md).
320320

321321
```ts { .no-copy }
322322
--8<-- "types/src/types.ts:Task"
@@ -568,7 +568,7 @@ The A2A Server's HTTP response body **MUST** be a `JSONRPCResponse` object (or,
568568

569569
### 7.1. `message/send`
570570

571-
Sends a message to an agent to initiate a new interaction or to continue an existing one. This method is suitable for synchronous request/response interactions or when client-side polling (using `tasks/get`) is acceptable for monitoring longer-running tasks.
571+
Sends a message to an agent to initiate a new interaction or to continue an existing one. This method is suitable for synchronous request/response interactions or when client-side polling (using `tasks/get`) is acceptable for monitoring longer-running tasks. A task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Sending a message to such a task will result in an error. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md).
572572

573573
- **Request `params` type**: [`MessageSendParams`](#711-messagesendparams-object)
574574
- **Response `result` type (on success)**: [`Task` | `Message`](#61-task-object) (A message object or the current or final state of the task after processing the message).
@@ -590,7 +590,7 @@ Sends a message to an agent to initiate a new interaction or to continue an exis
590590

591591
### 7.2. `message/stream`
592592

593-
Sends a message to an agent to initiate/continue a task AND subscribes the client to real-time updates for that task via Server-Sent Events (SSE). This method requires the server to have `AgentCard.capabilities.streaming: true`.
593+
Sends a message to an agent to initiate/continue a task AND subscribes the client to real-time updates for that task via Server-Sent Events (SSE). This method requires the server to have `AgentCard.capabilities.streaming: true`. Just like `message/send`, a task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Sending a message to such a task will result in an error. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md).
594594

595595
- **Request `params` type**: [`MessageSendParams`](#711-messagesendparams-object) (same as `message/send`).
596596
- **Response (on successful subscription)**:

docs/topics/key-concepts.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ The Agent2Agent (A2A) protocol is built around a set of core concepts that defin
2424
- When a client sends a message to an agent, the agent might determine that fulfilling the request requires a stateful task to be completed (e.g., "generate a report," "book a flight," "answer a question").
2525
- Each task has a unique ID defined by the agent and progresses through a defined lifecycle (e.g., `submitted`, `working`, `input-required`, `completed`, `failed`).
2626
- Tasks are stateful and can involve multiple exchanges (messages) between the client and the server.
27-
- See details in the [Protocol Specification: Task Object](../specification.md#61-task-object).
27+
- See details in the [Life of a Task](./life-of-a-task.md).
28+
- Protocol specification: [Task Object](../specification.md#61-task-object).
2829

2930
- **Message:**
3031

@@ -70,6 +71,10 @@ The Agent2Agent (A2A) protocol is built around a set of core concepts that defin
7071
- This requires the server to advertise the `pushNotifications` capability in its Agent Card.
7172
- Learn more about [Streaming & Asynchronous Operations](./streaming-and-async.md).
7273

74+
## Agent Response: Task or Message
75+
76+
See details in the [Life of a Task](./life-of-a-task.md).
77+
7378
## Other Important Concepts
7479

7580
- **Context (`contextId`):** A server-generated identifier that can be used to logically group multiple related `Task` objects, providing context across a series of interactions.

docs/topics/life-of-a-task.md

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# Life of a Task
2+
3+
When a message is sent to an agent, it can choose to reply with either:
4+
5+
- A stateless `Message`.
6+
- A stateful `Task` and zero or more `TaskStatusUpdateEvent` or `TaskArtifactUpdateEvent`.
7+
8+
If the response is a `Message`, the interaction is completed. On the other hand, A `Task` will keep getting updated until it is in a interrupted state ()`input-required` or `auth-required`) or a terminal state (`completed`, `cancelled`, `rejected` or `failed`).
9+
10+
## Context
11+
12+
A contextId logically composes many Tasks and independent Messages. Agent implementor can manage the llm context based on these interactions, utilizing the `contextId`.
13+
14+
For the first time a message is sent, agent replies back with a contextId. If the agent responded with a task, then it will also have a taskId. Clients can send subsequent messages and attach the same contextID to indicate to the agent that they are continuing their previous interaction within the same context. Client also optionally attach the taskID to indicate that the message is in continuation of that specific task.
15+
16+
ContextId allows collaboration over a goal or share one session across multiple tasks.
17+
18+
## Agent: Message or a Task
19+
20+
Messages can be used for trivial interactions which do not require long-running processing or collaboration. An agent can use messages to negotiate the acceptance of a task. Once an agent maps the intent of an incoming message to a supported capability, it can reply back with a `Task`.
21+
22+
So conceptually there can be three levels of agents:
23+
24+
1. Always responds with Messages only. Doesn't do complex state management, no long running execution and uses contextID to tie messages together. Agent most probably directly wraps around an LLM invocation and simple tools.
25+
2. Generates a task, does more substantial work that can be tracked and runs over extended life time.
26+
3. Generates messages and tasks. Uses messages to negotiate agent capability and scope of work for a task. Then sends task to track its execution and collaborate over task states like more input-needed, error handling, etc.
27+
28+
An agent can choose to always reply back with task objects and model simple responses as tasks in `completed` state.
29+
30+
## Task Refinements & Follow-ups
31+
32+
Client may want to follow up with new asks based on the results of a task, refine upon the task results. This can be modeled by starting another interaction using the same contextID as the original task. Client can further hint the agent by providing the reference to the original task using `referenceTaskIds` in `Message` object. Agent would then either create a new `Task` or a `Message`.
33+
34+
Once a task has reached a terminal state (`completed`, `cancelled`, `rejected` or `failed`), it can't be restarted. There are some benefits to this:
35+
36+
- **Task Immutability**: Clients can reliably reference tasks and their associated state, artifacts, and messages. This provides a clean mapping of inputs to outputs. Useful for mapping client planner nodes to task execution.
37+
- **Clear Unit of Work**: Every new request, refinement, or follow-up becomes a distinct task, simplifying bookkeeping and allowing for granular tracking of an agent's work.
38+
- Each artifact can be traced to a unit task.
39+
- This unit of work can be referenced much more granularly by parent agents or other systems like agent optimizers. Instead of restartable tasks, where all the subsequent refinements are clubbed together and would need to resort to some kind of message index range.
40+
- **Easier Implementation**: Agent developers follow a simple rule: always create a new task for a request referring a task in terminal state.
41+
42+
### Parallel Follow-ups
43+
44+
Parallel work is supported by having the agent create distinct, parallel tasks for each follow-up message sent within the same contextId. This allows clients to track individual sub-tasks and create new dependent tasks as soon as a prerequisite task is complete.
45+
46+
For example:
47+
48+
```none
49+
Task 1: Book a flight to Helsinki.
50+
(After Task 1 finishes)
51+
Task 2: Based on Task 1, book a hotel.
52+
Task 3: Based on Task 1, book a snowmobile activity.
53+
(After Task 2 finishes, while Task 3 is still in progress)
54+
Task 4: Based on Task 2, add a spa reservation to the hotel booking.
55+
```
56+
57+
### Referencing Previous Artifacts
58+
59+
The agent is responsible for inferring the relevant artifact from the referenced task or from the contextID. The serving agent is best suited to resolve ambiguity or identify missing information.
60+
61+
If there is ambiguity (e.g., multiple artifacts could fit the request), the agent will ask the client for clarification by returning an input-required state. The client can then specify the artifact in its response. Client can optionally populate artifact reference {artifactId, taskId} in part metadata. This allows for linkage between inputs for follow-up tasks and previous generated artifacts.
62+
63+
This approach allows for the client implementation to be simple.
64+
65+
### Tracking Artifact Mutation
66+
67+
A follow up or refinement can result in an older artifact being modified and newer artifacts being generated. It would be good to know this linkage and maybe track all mutations of the artifact to make sure only the latest copy is used for future context. Something like a linked list, with a head as the latest.
68+
69+
But the client is best suited, as well as is the real decider of what it considers as a result. And in fact can reject the mutation as well. Hence, the serving agent should not own this linkage and hence does not need to be part of A2A protocol spec. The serving agent should maintain the same artifact-name when generating a refinement on the original artifact.
70+
71+
For follow-up or refinement tasks, the client is best suited to refer to the "latest" or what it considers to be the intended artifact to be refined upon. If artifact reference is not explicitly specified, the serving agent can:
72+
73+
Use context to figure out the latest artifact.
74+
Or in case of ambiguity or context not supported, agent can use "input-required".
75+
76+
### Example Follow-up
77+
78+
#### Client sends message to agent
79+
80+
```json
81+
{
82+
"jsonrpc": "2.0",
83+
"id": "req-001",
84+
"method": "message/send",
85+
"params": {
86+
"message": {
87+
"role": "user",
88+
"parts": [
89+
{
90+
"kind": "text",
91+
"text": "Generate an image of a sailboat on the ocean."
92+
}
93+
],
94+
"messageId": "msg-user-001"
95+
}
96+
}
97+
}
98+
```
99+
100+
#### Agent responds with boat image
101+
102+
```json
103+
{
104+
"jsonrpc": "2.0",
105+
"id": "req-001",
106+
"result": {
107+
"id": "task-boat-gen-123",
108+
"contextId": "ctx-conversation-abc",
109+
"status": {
110+
"state": "completed",
111+
},
112+
"artifacts": [
113+
{
114+
"artifactId": "artifact-boat-v1-xyz",
115+
"name": "sailboat_image.png",
116+
"description": "A generated image of a sailboat on the ocean.",
117+
"parts": [
118+
{
119+
"kind": "file",
120+
"file": {
121+
"name": "sailboat_image.png",
122+
"mimeType": "image/png",
123+
"bytes": "<base64_encoded_png_data_of_a_sailboat>"
124+
}
125+
}
126+
]
127+
}
128+
],
129+
"kind": "task"
130+
}
131+
}
132+
```
133+
134+
#### Client asks for coloring the boat red
135+
136+
Refers to previous taskID and uses same contextId.
137+
138+
```json
139+
{
140+
"jsonrpc": "2.0",
141+
"id": "req-002",
142+
"method": "message/send",
143+
"params": {
144+
"message": {
145+
"role": "user",
146+
"messageId": "msg-user-002",
147+
"contextId": "ctx-conversation-abc", // Same contextId
148+
"referenceTaskIds": ["task-boat-gen-123"] // Optional: Referencing the previous task
149+
"parts": [
150+
{
151+
"kind": "text",
152+
"text": "That's great! Can you make the sailboat red?"
153+
// Optional: In case the agent asked for actual relevant artifact.
154+
// Client could provide the artifact data in parts.
155+
// Also it could add metadata to the part to
156+
// reference the specific artifact.
157+
// "metadata": {
158+
// "referenceArtifacts: [
159+
// {
160+
// "artifactId": "artifact-boat-v1-xyz",
161+
// "taskId": "task-boat-gen-123"
162+
// }
163+
// ]
164+
// }
165+
}
166+
],
167+
}
168+
}
169+
}
170+
```
171+
172+
#### Agent responds with new image artifact
173+
174+
- Creates new task in same contextId.
175+
- Boat image artifact has same name. but a new artifactId.
176+
177+
```json
178+
{
179+
"jsonrpc": "2.0",
180+
"id": "req-002",
181+
"result": {
182+
"id": "task-boat-color-456", // New task ID
183+
"contextId": "ctx-conversation-abc", // Same contextId
184+
"status": {
185+
"state": "completed",
186+
},
187+
"artifacts": [
188+
{
189+
"artifactId": "artifact-boat-v2-red-pqr", // New artifactId
190+
"name": "sailboat_image.png", // Same name as the original artifact
191+
"description": "A generated image of a red sailboat on the ocean.",
192+
"parts": [
193+
{
194+
"kind": "file",
195+
"file": {
196+
"name": "sailboat_image.png",
197+
"mimeType": "image/png",
198+
"bytes": "<base64_encoded_png_data_of_a_RED_sailboat>"
199+
}
200+
}
201+
]
202+
}
203+
],
204+
"kind": "task"
205+
}
206+
}
207+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ nav:
1919
- Enterprise-Ready Features: topics/enterprise-ready.md
2020
- Streaming & Asynchronous Operations: topics/streaming-and-async.md
2121
- Extensions: topics/extensions.md
22+
- Life of a Task: topics/life-of-a-task.md
2223
- Specification: specification.md
2324
- Community: community.md
2425
- Partners: partners.md

0 commit comments

Comments
 (0)