BerriAI/litellm · error · RuntimeError
A2A send_message failed: non-streaming message/send expects…
Error message
A2A send_message failed: non-streaming message/send expects the agent's final event to be a Message or Task result.
What it means
After collecting the final event of a non-streaming message/send, LiteLLM converts it via the a2a.compat.v0_3 layer and requires the result to be a Message or Task — the terminal results the A2A protocol defines for that method. If the agent's final event yields anything else (a status-update event, artifact event, or unexpected compat object), this RuntimeError is raised. It signals a protocol-shape mismatch between the agent and litellm's conversions, not a transport failure.
Solutions
- Align a2a-sdk versions on both sides (litellm pins a2a-sdk>=1.1.0,<2.0) and retest
- Upgrade litellm — compat-conversion fixes for new a2a-sdk releases land frequently
- On the agent side, ensure a non-streaming message/send terminates with a Message or Task result, not a bare status-update event
Defensive patterns
Strategy: try-catch
Validate before calling
# On the agent side: guarantee a non-streaming message/send ends with
# a terminal result. In an a2a-sdk agent handler, return the Task/Message:
async def handle(self, ctx, msg):
task = self._tasks[msg.context_id] # ...do work...
return Task(state=TaskState.completed, ...) # NOT a bare status-update event Try / catch
try:
resp = await asend_message(a2a_client=client, request=req)
except RuntimeError as e:
if 'expects the agent' in str(e) and 'Message or Task' in str(e):
# protocol-shape mismatch: align SDK versions, then retry once
_align_and_warn_sdk_versions()
resp = await asend_message(a2a_client=client, request=req)
else:
raise Prevention
- Pin the same a2a-sdk line on agent and litellm sides (>=1.1.0,<2.0)
- Contract-test agents: assert a non-streaming send terminates with Message/Task
- Upgrade litellm alongside a2a-sdk releases; conversions live in a2a.compat.v0_3
When it happens
Trigger: An agent whose last emitted event for a non-streaming send is a TaskStatusUpdateEvent or custom artifact instead of a completed Task/Message; version skew between the agent's a2a-sdk and the one litellm converts through (a2a.compat.v0_3).
Common situations: Agent frameworks emitting streaming-style terminal events for non-streaming sends; upgrading the agent SDK but not litellm (or vice versa); draft/0.3-era agents talking to the 1.x code path.
Related errors
- A2A send_message failed: no response received from agent.
- A2A send_message failed: no response received after retry…
- A2A send_message_streaming failed: no response received…
- Cannot retry A2A localhost URL fix: no agent card is…
- Cannot retry A2A localhost URL fix: the client was not…
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/a26fbe94396ea27f.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/a2a_protocol/main.py:262
async def _send_message(a2a_client: "A2AClientType", request: "SendMessageRequest") -> "SendMessageResponse":
"""Send a non-streaming message via a2a-sdk 1.x and return JSON-RPC response."""
if _a2a_conversions is None:
raise ImportError(
"The 'a2a' package is required for A2A agent invocation. Install it with: pip install a2a-sdk"
)
pb_request: Final = _to_core_send_message_request(request)
last_event = None
async for event in a2a_client.send_message(pb_request, context=_get_a2a_call_context(a2a_client)):
last_event = event
if last_event is None:
raise RuntimeError("A2A send_message failed: no response received from agent.")
stream_compat: Final = _to_compat_stream_response(last_event, request_id=request.id)
result: Final = stream_compat.result
if not isinstance(result, (Message, Task)):
raise RuntimeError(
"A2A send_message failed: non-streaming message/send expects the "
"agent's final event to be a Message or Task result."
)
return SendMessageResponse(
root=SendMessageSuccessResponse(
id=request.id,
result=result,
)
)
async def _execute_a2a_send_with_retry(
a2a_client: "A2AClientType",
request: "SendMessageRequest",
agent_card: Optional["AgentCard"],
card_url: str | None,
api_base: str | None,
agent_name: str | None,View on GitHub (pinned to 77b7c6c40c)