Skip to content

[Bug]: REST client creates A2A-incompatible payloads #548

@martina-zxy

Description

@martina-zxy

What happened?

The REST transport's _prepare_send_message method (line 81-101 in rest.py) uses MessageToDict() from google.protobuf.json_format to convert protobuf messages to JSON payloads. This creates payloads that are not compatible with the A2A REST API specification. _apply_interceptors might have been written to deal with this, but the method is still empty.

Location

a2a/client/transports/rest.py:95

async def _prepare_send_message(
    self, request: MessageSendParams, context: ClientCallContext | None
) -> tuple[dict[str, Any], dict[str, Any]]:
    pb = a2a_pb2.SendMessageRequest(
        request=proto_utils.ToProto.message(request.message),
        configuration=proto_utils.ToProto.message_send_configuration(
            request.configuration
        ),
        metadata=(
            proto_utils.ToProto.metadata(request.metadata)
            if request.metadata
            else None
        ),
    )
    payload = MessageToDict(pb) 
    payload, modified_kwargs = await self._apply_interceptors(
        payload,
        self._get_http_args(context),
        context,
    )
    return payload, modified_kwargs

a2a/client/transports/rest.py:65-74

async def _apply_interceptors(
    self,
    request_payload: dict[str, Any],
    http_kwargs: dict[str, Any] | None,
    context: ClientCallContext | None,
) -> tuple[dict[str, Any], dict[str, Any]]:
    final_http_kwargs = http_kwargs or {}
    final_request_payload = request_payload
    # TODO: Implement interceptors for other transports
    return final_request_payload, final_http_kwargs

Impact

This causes the REST transport to send message payload that is invalid according to the specification:

  • send parts as content
  • use the wrong enum of role, e.g., ROLE_USER instead of user

Example payload

{
  "message": {
    "messageId": "msg-1763370750463-w0jfn5g2n",
    "role": "ROLE_USER",
    "content": [
      {
        "text": "hello"
      }
    ],
    "metadata": {}
  },
  "configuration": {
    "blocking": true
  }
}

This affects both send_message() (line 103-118) and send_message_streaming() (line 120-156) methods.

Related Code

Similar issues may exist in other methods using MessageToDict:

  • cancel_task() - line 233
  • set_task_callback() - line 258
  • get_task_callback() - line 281

Relevant log output

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions