feat(a2a): add A2AAgentSession with reference_task_ids and input-required support#5980
Open
giles17 wants to merge 8 commits into
Open
feat(a2a): add A2AAgentSession with reference_task_ids and input-required support#5980giles17 wants to merge 8 commits into
giles17 wants to merge 8 commits into
Conversation
Track the task_id from A2A responses (task, status_update, artifact_update, and message payloads) on session.state and include it as reference_task_ids on subsequent outgoing messages. This enables remote agents to correlate follow-up messages as task refinements per the A2A spec. Resolves microsoft#5938 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
reference_task_ids
Contributor
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
Contributor
There was a problem hiding this comment.
Pull request overview
Adds A2A task-refinement linking in the Python A2A agent by persisting the most recently observed task_id and attaching it to subsequent outbound messages via reference_task_ids, enabling remote agents to correlate follow-up turns to the prior task per the A2A “life of a task” refinement flow.
Changes:
- Persist the last seen A2A
task_idontosession.state["a2a_task_id"]while mapping A2A stream payloads (task,status_update,artifact_update,message). - When sending a new message with an existing session task id, append it to the outbound
A2AMessage.reference_task_ids. - Add a focused test suite covering first-turn behavior, follow-ups, and task_id tracking across payload types.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| python/packages/a2a/agent_framework_a2a/_agent.py | Tracks the last observed task id from incoming A2A stream items and includes it as reference_task_ids on follow-up outbound messages. |
| python/packages/a2a/tests/test_a2a_agent.py | Adds tests validating reference_task_ids behavior and task id persistence across different response payload types and session/no-session flows. |
Introduce A2AAgentSession (subclass of AgentSession) with context_id, task_id, and task_state properties. This follows the DurableAgentSession pattern and mirrors the .NET A2AAgentSession design. - Track task_id, context_id, and task_state from all response payload types - Validate context_id consistency (raise on mismatch) - Auto-assign server-generated context_id when not set - Only A2AAgentSession gets reference tracking (no state dict fallback) - Plain AgentSession continues to work without reference tracking - Add serialization support (to_dict/from_dict) - Export via agent_framework.a2a and agent_framework_a2a Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
reference_task_idsAvoids importing private _deserialize_state, matching the DurableAgentSession pattern. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
giles17
commented
May 21, 2026
Contributor
Author
giles17
left a comment
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 84% | Result: All clear
Reviewed: Correctness, Security Reliability, Test Coverage, Design Approach
Automated review by giles17's agents
Previously, context_id was only captured from task, status_update, and artifact_update payloads. Message-only responses (which carry context_id but may lack task_id) were silently lost. This fix: - Captures msg.context_id in the message handler - Persists session state when either last_task_id or last_context_id is present (not only when task_id is truthy) - Only updates task_id/task_state when a task_id was actually returned - Adds a test for message-only context_id tracking Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
# Conflicts: # python/packages/a2a/agent_framework_a2a/_agent.py
Match .NET's GetUserInputRequests pattern: only emit TaskStatusUpdateEvent message content when state is INPUT_REQUIRED or terminal. Intermediate status text (WORKING, SUBMITTED) is no longer surfaced to callers. When state is INPUT_REQUIRED, set additional_properties['input_required'] = True so callers can distinguish input requests from final responses. Closes microsoft#5937 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces
A2AAgentSession— a typed session class that tracks A2A conversation state (context_id,task_id,task_state) — and uses it to implement two features:reference_task_ids#5938): Follow-up messages link to previous tasks viareference_task_idsfor task refinementinput-requireduser input #5937): When the remote agent needs user input, the framework:task_id(notreference_task_ids) on the next outgoing message to continue the same taskGetUserInputRequestspattern)additional_properties["input_required"] = Truefor caller distinctionChanges
A2AAgentSession(new class)AgentSessionwith typedcontext_id,task_id,task_statepropertiesagent_framework.a2a(lazy-loaded)_prepare_message_for_a2asessionparameter, reads A2A state internallytask_state: INPUT_REQUIRED →task_id, else →reference_task_ids_updates_from_task_update_eventTaskStatusUpdateEventcontent: only emits parts for INPUT_REQUIRED and terminal statesinput_required: Truein additional_properties when state is INPUT_REQUIREDStream handler (
_map_a2a_stream)context_idfrom message payloadslast_task_idorlast_context_id.NET Parity
Mirrors the behavior of
A2AAgent.cs:CreateA2AMessage(lines 362-382): INPUT_REQUIRED → task_id, else → reference_task_idsGetUserInputRequestsextension: content only for INPUT_REQUIRED stateUpdateSession(lines 323-342): context_id validation, task_id/state trackingTesting
Closes
reference_task_ids#5938input-requireduser input #5937