-
Notifications
You must be signed in to change notification settings - Fork 134
Description
What happened?
Summary
SendMessage to a task in a terminal state (e.g., completed) succeeds instead of returning UnsupportedOperationError. Fails on all three transports (JSON-RPC, gRPC, HTTP+JSON).
Requirement
- ID: CORE-SEND-002
- Section: 3.1.1 — SendMessage rejects messages to terminal tasks
- Level: MUST
- Spec: https://github.com/a2aproject/A2A/blob/173695755607e884aa9acf8ce4feed90e32727a1/docs/specification.md#311-send-message
Specification
UnsupportedOperationError: Messages sent to Tasks that are in a terminal state (e.g., completed, canceled, rejected) cannot accept further messages.
Expected behavior
When a client sends a SendMessage request with a taskId referencing a task that has already reached a terminal state (completed, canceled, rejected), the SDK framework MUST intercept the request and return an UnsupportedOperationError before the message reaches the AgentExecutor.
Actual behavior
The SDK accepts the message and forwards it to the AgentExecutor, which processes it as if the task were still active. No error is returned.
Reproducer
The TCK test creates a task that immediately completes, then sends a follow-up message referencing that task's ID.
The SUT executor that produces the completed task looks like this (from the generated TckAgentExecutorProducer.java):
// Any message with this prefix completes the task immediately,
// putting it in a terminal state (TASK_STATE_COMPLETED).
if (messageId.startsWith("tck-task-helper")) {
emitter.complete(A2A.toAgentMessage("Task helper response"));
return;
}After this task completes, the TCK sends another SendMessage with taskId set to the completed task's ID. The SDK should reject this with UnsupportedOperationError at the framework level, but instead it forwards the message to the executor.
JSON-RPC reproducer:
# Step 1: Create a task that completes immediately
curl -s -X POST http://localhost:9999/ \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"1","method":"SendMessage","params":{"message":{"messageId":"tck-task-helper-abcd1234","role":"ROLE_USER","parts":[{"text":"Create task"}]}}}'
# → Returns task with status.state = "TASK_STATE_COMPLETED"
# Extract the task ID from result.task.id
# Step 2: Send a message to the terminal task (replace <TASK_ID> with the ID from step 1)
curl -s -X POST http://localhost:9999/ \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"2","method":"SendMessage","params":{"message":{"messageId":"tck-follow-up-1234","role":"ROLE_USER","parts":[{"text":"Follow-up"}],"taskId":"<TASK_ID>"}}}'
# Expected: JSON-RPC error with code -32004 (UnsupportedOperationError)
# Actual: Succeeds with a new task resultTCK test
tests/compatibility/core_operations/test_task_lifecycle.py::TestMultiTurn::test_send_message_to_terminal_task[grpc]
tests/compatibility/core_operations/test_task_lifecycle.py::TestMultiTurn::test_send_message_to_terminal_task[http_json]
tests/compatibility/core_operations/test_task_lifecycle.py::TestMultiTurn::test_send_message_to_terminal_task[jsonrpc]
Relevant log output
Code of Conduct
- I agree to follow this project's Code of Conduct