Skip to content

Commit 0481cd9

Browse files
CopilotCopilot
andcommitted
Fix context_id extraction in A2AAgent to use service_session_id (#5353)
AgentSession.service_session_id now takes precedence over message.additional_properties['context_id'] in _prepare_message_for_a2a(), making the session the authoritative source for context_id. The message property is still used as a fallback when no session is provided. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3f23e1d commit 0481cd9

2 files changed

Lines changed: 29 additions & 11 deletions

File tree

python/packages/a2a/agent_framework_a2a/_agent.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -599,10 +599,11 @@ def _prepare_message_for_a2a(self, message: Message, *, context_id: str | None =
599599
600600
Args:
601601
message: The framework Message to convert.
602-
context_id: Optional fallback context identifier (e.g. derived from
603-
``AgentSession.service_session_id``). When the *message* already
604-
carries a ``context_id`` in its ``additional_properties`` that
605-
value takes precedence; otherwise this fallback is used.
602+
context_id: Optional context identifier derived from
603+
``AgentSession.service_session_id``. When provided, this takes
604+
precedence as the authoritative session-level identifier. Falls
605+
back to ``message.additional_properties["context_id"]`` when
606+
not provided.
606607
"""
607608
parts: list[A2APart] = []
608609
if not message.contents:
@@ -682,7 +683,7 @@ def _prepare_message_for_a2a(self, message: Message, *, context_id: str | None =
682683
role=A2ARole("user"),
683684
parts=parts,
684685
message_id=message.message_id or uuid.uuid4().hex,
685-
context_id=message.additional_properties.get("context_id") or context_id,
686+
context_id=context_id or message.additional_properties.get("context_id"),
686687
metadata=metadata,
687688
)
688689

python/packages/a2a/tests/test_a2a_agent.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,8 @@ def test_prepare_message_for_a2a_uses_fallback_context_id() -> None:
556556
assert result.context_id == "session-ctx-1"
557557

558558

559-
def test_prepare_message_for_a2a_message_context_id_takes_precedence() -> None:
560-
"""Test that message.additional_properties context_id wins over the fallback."""
559+
def test_prepare_message_for_a2a_session_context_id_takes_precedence() -> None:
560+
"""Test that context_id kwarg (from session) takes precedence over additional_properties."""
561561

562562
agent = A2AAgent(client=MagicMock(), http_client=None)
563563

@@ -569,7 +569,7 @@ def test_prepare_message_for_a2a_message_context_id_takes_precedence() -> None:
569569

570570
result = agent._prepare_message_for_a2a(message, context_id="session-ctx-1")
571571

572-
assert result.context_id == "explicit-ctx"
572+
assert result.context_id == "session-ctx-1"
573573

574574

575575
def test_parse_contents_from_a2a_with_data_part() -> None:
@@ -918,8 +918,8 @@ async def test_run_passes_session_service_session_id_as_context_id(mock_a2a_clie
918918

919919

920920
@mark.asyncio
921-
async def test_run_message_context_id_takes_precedence_over_session(mock_a2a_client: MockA2AClient) -> None:
922-
"""Test that an explicit context_id on the message wins over session.service_session_id."""
921+
async def test_run_session_context_id_takes_precedence_over_message(mock_a2a_client: MockA2AClient) -> None:
922+
"""Test that session.service_session_id takes precedence over message additional_properties context_id."""
923923
agent = A2AAgent(name="Test Agent", id="test-agent", client=mock_a2a_client, http_client=None)
924924
mock_a2a_client.add_message_response("msg-ctx2", "reply")
925925

@@ -932,7 +932,24 @@ async def test_run_message_context_id_takes_precedence_over_session(mock_a2a_cli
932932
await agent.run(messages=[message], session=session)
933933

934934
assert mock_a2a_client.last_message is not None
935-
assert mock_a2a_client.last_message.context_id == "explicit-ctx"
935+
assert mock_a2a_client.last_message.context_id == "svc-session-42"
936+
937+
938+
@mark.asyncio
939+
async def test_run_message_context_id_used_when_no_session(mock_a2a_client: MockA2AClient) -> None:
940+
"""Test that message additional_properties context_id is used as fallback when no session is provided."""
941+
agent = A2AAgent(name="Test Agent", id="test-agent", client=mock_a2a_client, http_client=None)
942+
mock_a2a_client.add_message_response("msg-ctx3", "reply")
943+
944+
message = Message(
945+
role="user",
946+
contents=[Content.from_text(text="Hello")],
947+
additional_properties={"context_id": "fallback-ctx"},
948+
)
949+
await agent.run(messages=[message])
950+
951+
assert mock_a2a_client.last_message is not None
952+
assert mock_a2a_client.last_message.context_id == "fallback-ctx"
936953

937954

938955
# endregion

0 commit comments

Comments
 (0)