message/send JSON-RPC result is wrapped in the SendMessageResponse oneof instead of returning the Task/Message directly
I maintainer di solito rispondono entro 1 giorno
@rohityan ci sta già lavorando.
Dal 19/8/2026.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 70/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Ambito
- api
Direzione di ricerca
Il problema si trova in a2a/server/routes/jsonrpc_dispatcher.py, nella funzione _handle_send_message. Confrontala con _handle_get_task e _handle_cancel_task per vedere la differenza nel modo in cui serializzano il valore restituito. La correzione consiste nel rimuovere il wrapper SendMessageResponse e restituire direttamente Task o Message tramite MessageToDict. Esegui i test esistenti per le route JSON-RPC per verificare che la modifica produca la struttura JSON prevista.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Environment
- a2a-sdk 1.0.3
- Python 3.13
- Transport: JSON-RPC (
create_jsonrpc_routes,DefaultRequestHandlerV2),enable_v0_3_compat=True
Summary
For a 1.x message/send call, the JSON-RPC result comes back as {"task": {…}} (or {"message": {…}}) rather than the Task or Message object itself. A client that reads result.status and result.artifacts, which the A2A 1.0 spec describes for the unary send, finds nothing, because the payload sits one level deeper under result.task.
The task/message oneof belongs to the streaming StreamResponse. The unary message/send should return the Task or Message directly, the way tasks/get and tasks/cancel already do.
Expected
{ "jsonrpc": "2.0", "id": "1", "result": { "id": "…", "contextId": "…", "status": {…}, "artifacts": [ … ] } }
Actual
{ "jsonrpc": "2.0", "id": "1", "result": { "task": { "id": "…", "contextId": "…", "status": {…}, "artifacts": [ … ] } } }
Root cause
In a2a/server/routes/jsonrpc_dispatcher.py, _handle_send_message wraps the return value in a SendMessageResponse before serializing:
async def _handle_send_message(self, request_obj, context):
task_or_message = await self.request_handler.on_message_send(request_obj, context)
if isinstance(task_or_message, Task):
return MessageToDict(SendMessageResponse(task=task_or_message))
return MessageToDict(SendMessageResponse(message=task_or_message))
MessageToDict on a SendMessageResponse emits the oneof field name (task or message) as a key, which becomes the JSON-RPC result. The sibling handlers serialize the object directly and do not show this wrapper:
async def _handle_get_task(self, request_obj, context):
task = await self.request_handler.on_get_task(request_obj, context)
return MessageToDict(task, preserving_proto_field_name=False)
Impact
A2A 1.0 clients that follow the spec read the Task at result, not at result.task. Against this SDK they see an empty result and report the call as incomplete. The two shapes also disagree within one SDK: tasks/get returns the Task un-nested, message/send nests it, so a client cannot use one code path for both.
Reproduce
- Stand up any agent with
create_jsonrpc_routes(...). - POST a 1.x
message/send(method: "SendMessage"). - Read the response:
resulthas a single key,task.
Suggested fix
Return the Task or Message directly from _handle_send_message, matching _handle_get_task and _handle_cancel_task:
async def _handle_send_message(self, request_obj, context):
task_or_message = await self.request_handler.on_message_send(request_obj, context)
return MessageToDict(task_or_message, preserving_proto_field_name=False)
The v0.3 compat path is unaffected. It already returns the Task/Message directly through the v0.3 adapter.
- Lingua principale
- Python
- Stelle
- 2.2k
- Fork
- 499
- Merge medio
- 3g 14h
- PR unite (30g)
- 36
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di a2aproject/a2a-python
-
[Bug]: REST task/request id sanitizationForse già presa @Linux2010 l’ha presa 99 giorni fa. Apertamaintainers-only
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
a2aproject/a2a-python#805 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: Push notification store failure rewrites a completed task as FAILED (DefaultRequestHandlerV2)Forse già presa @rohityan l’ha presa oggi. Aperta
a2aproject/a2a-python#1313 · 2 assegnatari ·
I maintainer di solito rispondono entro 1 giorno
-
v0.3 JSON-RPC and REST GetTask return no history when history_length is 0Forse già presa @rohityan l’ha presa oggi. Aperta
a2aproject/a2a-python#1311 · 2 assegnatari ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: QueueShutDown spans still end as ERROR (and exceptions are recorded twice) because start_as_current_span sets status on exceptionForse già presa @rohityan l’ha presa 1 giorno fa. Aperta
a2aproject/a2a-python#1308 · 2 assegnatari ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: DefaultRequestHandlerV2 keeps the ActiveTask (producer, consumer, 2 dispatchers) alive forever after a direct Message or input-required responseForse già presa @rohityan l’ha presa 3 giorni fa. Aperta
a2aproject/a2a-python#1296 · 2 assegnatari ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di a2aproject/a2a-python
Issue simili
-
json_params_matcher fails on falsy top-level JSON primitives (0, False, "")Forse già presa @mayureshsonawane17 l’ha presa oggi. ApertaWaiting for: Product Owner
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 5 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
bojieli/ai-agent-book#1169 ·
I maintainer di solito rispondono entro 1 giorno
-
priority:low ready-for-dev
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
OpenHands/extensions#738 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
micronaut-projects/micronaut-core#13677 ·
I maintainer di solito rispondono entro 1 giorno