-
Notifications
You must be signed in to change notification settings - Fork 102
Description
What happened?
When a spec-compliant A2A server (built with either the official a2a-js SDK or the a2a-dart SDK) 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
{
"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
- I agree to follow this project's Code of Conduct