{"record":{"id":"a26fbe94396ea27f","repo":"BerriAI/litellm","slug":"a2a-send-message-failed-non-streaming-message-sen","errorCode":null,"errorMessage":"A2A send_message failed: non-streaming message/send expects the agent's final event to be a Message or Task result.","messagePattern":"A2A send_message failed: non-streaming message/send expects the agent's final event to be a Message or Task result\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"litellm/a2a_protocol/main.py","lineNumber":262,"sourceCode":"\nasync def _send_message(a2a_client: \"A2AClientType\", request: \"SendMessageRequest\") -> \"SendMessageResponse\":\n    \"\"\"Send a non-streaming message via a2a-sdk 1.x and return JSON-RPC response.\"\"\"\n    if _a2a_conversions is None:\n        raise ImportError(\n            \"The 'a2a' package is required for A2A agent invocation. Install it with: pip install a2a-sdk\"\n        )\n\n    pb_request: Final = _to_core_send_message_request(request)\n    last_event = None\n    async for event in a2a_client.send_message(pb_request, context=_get_a2a_call_context(a2a_client)):\n        last_event = event\n    if last_event is None:\n        raise RuntimeError(\"A2A send_message failed: no response received from agent.\")\n\n    stream_compat: Final = _to_compat_stream_response(last_event, request_id=request.id)\n    result: Final = stream_compat.result\n    if not isinstance(result, (Message, Task)):\n        raise RuntimeError(\n            \"A2A send_message failed: non-streaming message/send expects the \"\n            \"agent's final event to be a Message or Task result.\"\n        )\n    return SendMessageResponse(\n        root=SendMessageSuccessResponse(\n            id=request.id,\n            result=result,\n        )\n    )\n\n\nasync def _execute_a2a_send_with_retry(\n    a2a_client: \"A2AClientType\",\n    request: \"SendMessageRequest\",\n    agent_card: Optional[\"AgentCard\"],\n    card_url: str | None,\n    api_base: str | None,\n    agent_name: str | None,","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/a2a_protocol/main.py#L244-L280","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# On the agent side: guarantee a non-streaming message/send ends with\n# a terminal result. In an a2a-sdk agent handler, return the Task/Message:\nasync def handle(self, ctx, msg):\n    task = self._tasks[msg.context_id]  # ...do work...\n    return Task(state=TaskState.completed, ...)  # NOT a bare status-update event","typeGuard":null,"tryCatchPattern":"try:\n    resp = await asend_message(a2a_client=client, request=req)\nexcept RuntimeError as e:\n    if 'expects the agent' in str(e) and 'Message or Task' in str(e):\n        # protocol-shape mismatch: align SDK versions, then retry once\n        _align_and_warn_sdk_versions()\n        resp = await asend_message(a2a_client=client, request=req)\n    else:\n        raise","preventionTips":["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"],"tags":["a2a","protocol","type-mismatch","runtime-error"],"backgroundTag":"unexpected-response-type","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}