Agent Tasks¶
An Agent Task represents an observable Agent execution that can outlive one HTTP exchange. After sending a message, save the Task id and contextId, and drive the UI and subsequent operations from status.state rather than treating the end of the HTTP request as task completion.
Task shape¶
Task fields can expand with the Agent and A2A protocol version. A client commonly uses:
{
"kind": "task",
"id": "task_123",
"contextId": "ctx_123",
"status": {
"state": "working"
},
"artifacts": []
}
Field |
Client use |
|---|---|
|
Stable Task identifier for inspection, cancellation, and resubscription |
|
Context to put on a follow-up user message |
|
Current lifecycle state |
|
Optional message associated with the state; parse it as Parts |
|
Text or structured output produced so far |
|
Message or state history when the Agent provides it |
Common states include working, input-required, completed, failed, and canceled. A client must tolerate unknown states and must not interpret an unrecognized value as success. Treat completed, failed, and canceled as terminal. input-required means that execution is paused for a user response, not that it failed.
Get a Task¶
Use tasks/get to read the latest state. params.id is the Task ID, not the JSON-RPC request ID:
{
"agent_code": "explore",
"jsonrpc": "2.0",
"id": "req_task_get_01",
"method": "tasks/get",
"params": {
"id": "task_123"
}
}
Use the same Agent selector that created the Task. A Task ID alone does not route the request to the correct Agent.
An application that did not open a stream can poll while the Task remains nonterminal:
import time
while True:
task = call_a2a("tasks/get", {"id": task_id})["result"]
state = task["status"]["state"]
if state in {"completed", "failed", "canceled"}:
break
if state == "input-required":
show_requested_input(task)
break
time.sleep(2)
Here, call_a2a denotes the application’s wrapper around POST /newmoi/agents/a2a; it is not a method in the current official Python SDK. Production polling should have an overall deadline, exponential backoff, and jitter so that many Tasks do not poll in lockstep.
Cancel a Task¶
tasks/cancel asks the server to stop a Task:
{
"agent_code": "explore",
"jsonrpc": "2.0",
"id": "req_task_cancel_01",
"method": "tasks/cancel",
"params": {
"id": "task_123"
}
}
Cancellation is a state-transition request and cannot guarantee reversal of external side effects that already occurred. Inspect the returned Task state after a cancellation response; if the outcome is ambiguous, confirm it with tasks/get. Closing a local browser view or process does not imply that the server-side Task was canceled.
Resubscribe to events¶
If a streaming connection ends before the Task reaches a terminal state, recover with tasks/resubscribe. Its parameter name differs from the get and cancel methods:
{
"agent_code": "explore",
"jsonrpc": "2.0",
"id": "req_task_resubscribe_01",
"method": "tasks/resubscribe",
"params": {
"taskId": "task_123",
"afterSeq": 12
}
}
taskIdselects the Task to recover.afterSeqis the last SSEidthat the client fully processed and persisted.The response remains
text/event-streamand uses the same parser asmessage/stream.
Advance the stored sequence only after the corresponding local state is durable. If the process then fails during a write, it can replay from an earlier sequence safely. Consumers should also deduplicate by event sequence or business event identity because network recovery can redeliver an event.
Omit afterSeq if no valid event was received. Retention is controlled by the server; clients must not assume Task events are stored forever. If resubscription fails, call tasks/get first to determine the latest state before asking the user to retry, starting a new execution, or escalating the incident.
Handle input-required¶
When the state becomes input-required, read the Agent’s question from the status message or related Artifact and present its options and context clearly. Submit the user’s answer as another ordinary A2A user message with the Task’s contextId:
{
"kind": "message",
"role": "user",
"messageId": "msg_answer_01",
"contextId": "ctx_123",
"parts": [
{
"kind": "text",
"text": "Save the result to the knowledge base"
}
]
}
This section does not promise a separate “resume Task” SDK method for the current generic gateway. Continue through message/send or message/stream; do not invent an unconfirmed input-submission method.
Persistence and operations¶
Store the Agent selector, Task
id,contextId, state, last event sequence, and related business record together.Apply status updates idempotently. A late or duplicated event must not move a terminal Task back to
working.Record cancellation, failure, and client timeout separately. A client timeout does not mean the server-side Task failed.
Artifacts may contain large structured values. Project them by type, cap log size, and preserve workspace data-access rules.
During diagnosis, first check for confusion between the JSON-RPC
idand Taskid, then inspect the Agent selector, authorization, last event sequence, and terminal event.
Return to Messages and Streaming Calls for request and SSE parsing examples.