Skip to content

[Bug]: A2A Inspector Fails to Validate Spec-Compliant Streaming EventsΒ #104

@shamblett

Description

@shamblett

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions