a2aproject / a2aproject/a2a-inspector
[Bug]: A2A Inspector Fails to Validate Spec-Compliant Streaming Events
- Lingua principale
- TypeScript
- Stelle
- 490
- Fork
- 152
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
### What happened?
When a spec-compliant A2A server (built with either the official a2a-js SDK or the [a2a-dart SDK](https://pub.dev/packages/a2a)) sends streaming events, the A2A Inspector tool fails with a series of Pydantic validation errors.
This indicates a likely bug in the Inspector's validation models, as it is incompatible with the event structure produced by the official SDKs.
Analysis: JS SDK vs. Dart SDK
A deep analysis was performed on both the a2a-js and a2a-dart server-side implementations. Both SDKs follow the exact same logic for serializing streaming responses:
An event object (e.g., TaskStatusUpdateEvent, TaskArtifactUpdateEvent) is generated by the agent's business logic.
The transport handler creates a JSON-RPC 2.0 success response object.
The entire event object from step 1 is placed inside the result field of the JSON-RPC response.
This complete JSON-RPC response object is then serialized and sent as the data payload of a Server-Sent Event (SSE).
Example of a Correct, Sent Payload (from both JS and Dart SDKs):
{
"jsonrpc": "2.0",
"id": "request-id",
"result": {
"kind": "status-update",
"taskId": "...",
"status": { ... }
}
}
The A2A Inspector's Error
The Inspector receives this payload but fails to validate it. The error messages (SendStreamingMessageSuccessResponse.result.Task.id Field required, etc.) show that it is incorrectly trying to parse the result object (which is a TaskStatusUpdateEvent) as a different type (like a Task or a Message).
The Inspector's validation logic does not seem to account for the result of a streaming response being an event object like TaskStatusUpdateEvent or TaskArtifactUpdateEvent.
Conclusion
The bug does not lie in the a2a-dart SDK's serialization logic, which is consistent with the reference a2a-js implementation. The bug is in the A2A Inspector tool's validation models, which are too strict and do not correctly handle the event structures sent by the official SDKs.
Recommendation for A2A Inspector
The Pydantic models for the SendStreamingMessageResponse in the Inspector's Python backend should be updated to correctly deserialize the result field as a union of all possible event types, including TaskStatusUpdateEvent and TaskArtifactUpdateEvent.
### Relevant log output
```shell
{
"error": "Failed to send message: 10 validation errors for SendStreamingMessageResponse\nJSONRPCErrorResponse.error\n Field required [type=missing, input_value={'id': 'e923073e-13c0-431...3a1-b6af-909ca19742d1'}}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\nSendStreamingMessageSuccessResponse.result.Task.id\n Field required [type=missing, input_value={'contextId': '59014184-9...43a1-b6af-909ca19742d1'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\nSendStreamingMessageSuccessResponse.result.Task.kind\n Input should be 'task' [type=literal_error, input_value='status-update', input_type=str]\n For further information visit https://errors.pydantic.dev/2.11/v/literal_error\nSendStreamingMessageSuccessResponse.result.Message.kind\n Input should be 'message' [type=literal_error, input_value='status-update', input_type=str]\n For further information visit https://errors.pydantic.dev/2.11/v/literal_error\nSendStreamingMessageSuccessResponse.result.Message.messageId\n Field required [type=missing, input_value={'contextId': '59014184-9...43a1-b6af-909ca19742d1'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\nSendStreamingMessageSuccessResponse.result.Message.parts\n Field required [type=missing, input_value={'contextId': '59014184-9...43a1-b6af-909ca19742d1'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\nSendStreamingMessageSuccessResponse.result.Message.role\n Field required [type=missing, input_value={'contextId': '59014184-9...43a1-b6af-909ca19742d1'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\nSendStreamingMessageSuccessResponse.result.TaskStatusUpdateEvent.final\n Field required [type=missing, input_value={'contextId': '59014184-9...43a1-b6af-909ca19742d1'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\nSendStreamingMessageSuccessResponse.result.TaskArtifactUpdateEvent.artifact\n Field required [type=missing, input_value={'contextId': '59014184-9...43a1-b6af-909ca19742d1'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.11/v/missing\nSendStreamingMessageSuccessResponse.result.TaskArtifactUpdateEvent.kind\n Input should be 'artifact-update' [type=literal_error, input_value='status-update', input_type=str]\n For further information visit https://errors.pydantic.dev/2.11/v/literal_error",
"id": "msg-1760866208968-4fkhgnvml"
}
```
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
The issue is in the Python backend's Pydantic models for SendStreamingMessageResponse. Look at the validation error logs to see which models are being used. The result field needs to accept a union of event types like TaskStatusUpdateEvent and TaskArtifactUpdateEvent. Start by examining the Pydantic model definitions in the backend code, likely in a file handling JSON-RPC or streaming responses. Update the model to correctly deserialize the event structures sent by the official SDKs.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python, typescript
- Ambito
- devtools, testing
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 45/100