Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion python/packages/a2a/agent_framework_a2a/_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,8 @@ async def _map_a2a_stream(
update = AgentResponseUpdate(
contents=contents,
role="assistant" if item.role == A2ARole.agent else "user",
response_id=str(getattr(item, "message_id", uuid.uuid4())),
response_id=item.task_id or str(uuid.uuid4()),
message_id=item.message_id,
raw_representation=item,
)
all_updates.append(update)
Expand Down
34 changes: 30 additions & 4 deletions python/packages/a2a/tests/test_a2a_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,20 @@ def __init__(self) -> None:
self.resubscribe_responses: list[Any] = []
self.get_task_response: Task | None = None

def add_message_response(self, message_id: str, text: str, role: str = "agent") -> None:
def add_message_response(
self, message_id: str, text: str, role: str = "agent", task_id: str | None = None
) -> None:
"""Add a mock Message response."""

# Create actual TextPart instance and wrap it in Part
text_part = Part(root=TextPart(text=text))

# Create actual Message instance
message = A2AMessage(
message_id=message_id, role=A2ARole.agent if role == "agent" else A2ARole.user, parts=[text_part]
message_id=message_id,
role=A2ARole.agent if role == "agent" else A2ARole.user,
parts=[text_part],
task_id=task_id,
)
self.responses.append(message)

Expand Down Expand Up @@ -224,7 +229,9 @@ async def test_run_with_message_response(a2a_agent: A2AAgent, mock_a2a_client: M
assert len(response.messages) == 1
assert response.messages[0].role == "assistant"
assert response.messages[0].text == "Hello from agent!"
assert response.response_id == "msg-123"
# Without task_id, response_id is a generated UUID (not the message_id)
assert response.response_id is not None
assert response.response_id != "msg-123"
assert mock_a2a_client.call_count == 1


Expand Down Expand Up @@ -460,10 +467,29 @@ async def test_run_streaming_with_message_response(a2a_agent: A2AAgent, mock_a2a
assert content.type == "text"
assert content.text == "Streaming response from agent!"

assert updates[0].response_id == "msg-stream-123"
# Without task_id, response_id is a generated UUID, message_id carries the message identifier
assert updates[0].response_id is not None
assert updates[0].response_id != "msg-stream-123"
assert updates[0].message_id == "msg-stream-123"
assert mock_a2a_client.call_count == 1


@mark.asyncio
async def test_message_response_id_uses_task_id_and_propagates_message_id(
a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient
) -> None:
"""Test that response_id uses task_id and message_id is separately propagated (fixes #5263)."""
mock_a2a_client.add_message_response("msg-100", "Hello!", "agent", task_id="task-200")

updates: list[AgentResponseUpdate] = []
async for update in a2a_agent.run("Hi", stream=True):
updates.append(update)

assert len(updates) == 1
assert updates[0].response_id == "task-200"
assert updates[0].message_id == "msg-100"


async def test_context_manager_cleanup() -> None:
"""Test context manager cleanup of http client."""

Expand Down