mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Propagate thread_id and forwarded_props through AG-UI to A2A context_id (#5383)
* Propagate session.service_session_id as A2A context_id When A2AAgent is used behind the AG-UI protocol, the client thread_id is stored in session.service_session_id but was never forwarded as the A2A context_id. This broke session continuity across the AG-UI → A2A boundary. Add an optional context_id keyword argument to _prepare_message_for_a2a() and pass session.service_session_id from run(). The explicit message.additional_properties["context_id"] still takes precedence. Fixes #5345 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add integration tests for session context_id wiring in run() (#5345) - Enhance MockA2AClient.send_message to capture last_message for assertions - Add test_run_passes_session_service_session_id_as_context_id: verifies run() passes session.service_session_id through to A2A message context_id - Add test_run_message_context_id_takes_precedence_over_session: verifies explicit message context_id wins over session fallback - Update _prepare_message_for_a2a docstring to document context_id param and its precedence rules Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback for #5345: Python: [Bug]: Inconvenient passing of context_id / thread_id in A2A/AG-UI implementations --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot
Copilot
parent
fffd0acb3e
commit
3ae86f098e
@@ -295,7 +295,10 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
|
||||
else:
|
||||
if not normalized_messages:
|
||||
raise ValueError("At least one message is required when starting a new task (no continuation_token).")
|
||||
a2a_message = self._prepare_message_for_a2a(normalized_messages[-1])
|
||||
a2a_message = self._prepare_message_for_a2a(
|
||||
normalized_messages[-1],
|
||||
context_id=session.service_session_id if session else None,
|
||||
)
|
||||
a2a_stream = self.client.send_message(a2a_message)
|
||||
|
||||
provider_session = session
|
||||
@@ -584,7 +587,7 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
|
||||
return AgentResponse.from_updates(updates)
|
||||
return AgentResponse(messages=[], response_id=task.id, raw_representation=task)
|
||||
|
||||
def _prepare_message_for_a2a(self, message: Message) -> A2AMessage:
|
||||
def _prepare_message_for_a2a(self, message: Message, *, context_id: str | None = None) -> A2AMessage:
|
||||
"""Prepare a Message for the A2A protocol.
|
||||
|
||||
Transforms Agent Framework Message objects into A2A protocol Messages by:
|
||||
@@ -593,6 +596,13 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
|
||||
- Converting file references (URI/data/hosted_file) to FilePart objects
|
||||
- Preserving metadata and additional properties from the original message
|
||||
- Setting the role to 'user' as framework messages are treated as user input
|
||||
|
||||
Args:
|
||||
message: The framework Message to convert.
|
||||
context_id: Optional fallback context identifier (e.g. derived from
|
||||
``AgentSession.service_session_id``). When the *message* already
|
||||
carries a ``context_id`` in its ``additional_properties`` that
|
||||
value takes precedence; otherwise this fallback is used.
|
||||
"""
|
||||
parts: list[A2APart] = []
|
||||
if not message.contents:
|
||||
@@ -672,7 +682,7 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
|
||||
role=A2ARole("user"),
|
||||
parts=parts,
|
||||
message_id=message.message_id or uuid.uuid4().hex,
|
||||
context_id=message.additional_properties.get("context_id"),
|
||||
context_id=message.additional_properties.get("context_id") or context_id,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user