Skip to content

feat(a2a): add A2AAgentSession with reference_task_ids and input-required support#5980

Open
giles17 wants to merge 8 commits into
microsoft:mainfrom
giles17:a2a-reference-task-ids
Open

feat(a2a): add A2AAgentSession with reference_task_ids and input-required support#5980
giles17 wants to merge 8 commits into
microsoft:mainfrom
giles17:a2a-reference-task-ids

Conversation

@giles17
Copy link
Copy Markdown
Contributor

@giles17 giles17 commented May 20, 2026

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:

  1. Reference task IDs (Python: [A2A] Link follow-up messages to the existing task via reference_task_ids #5938): Follow-up messages link to previous tasks via reference_task_ids for task refinement
  2. Input-required support (Python: [A2A] First-class support for input-required user input #5937): When the remote agent needs user input, the framework:
    • Sets task_id (not reference_task_ids) on the next outgoing message to continue the same task
    • Gates status content to only surface INPUT_REQUIRED and terminal states (matches .NET GetUserInputRequests pattern)
    • Marks updates with additional_properties["input_required"] = True for caller distinction

Changes

A2AAgentSession (new class)

  • Subclasses AgentSession with typed context_id, task_id, task_state properties
  • Tracks state from all stream payload types (task, status_update, artifact_update, message)
  • Validates context_id consistency across responses
  • Exported from agent_framework.a2a (lazy-loaded)

_prepare_message_for_a2a

  • Accepts session parameter, reads A2A state internally
  • Branches on task_state: INPUT_REQUIRED → task_id, else → reference_task_ids

_updates_from_task_update_event

  • Gates TaskStatusUpdateEvent content: only emits parts for INPUT_REQUIRED and terminal states
  • Intermediate status text (WORKING, SUBMITTED) is not surfaced to callers
  • Sets input_required: True in additional_properties when state is INPUT_REQUIRED

Stream handler (_map_a2a_stream)

  • Tracks context_id from message payloads
  • Treats INPUT_REQUIRED as immediate-yield (not accumulated) in non-streaming mode
  • Persists session state on last_task_id or last_context_id

.NET Parity

Mirrors the behavior of A2AAgent.cs:

  • CreateA2AMessage (lines 362-382): INPUT_REQUIRED → task_id, else → reference_task_ids
  • GetUserInputRequests extension: content only for INPUT_REQUIRED state
  • UpdateSession (lines 323-342): context_id validation, task_id/state tracking

Testing

  • 139 tests passing (includes new tests for content gating, input_required flag, reference_task_ids, session state tracking)
  • Pyright clean

Closes

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>
Copilot AI review requested due to automatic review settings May 20, 2026 20:57
@github-actions github-actions Bot changed the title feat(a2a): link follow-up messages via reference_task_ids Python: feat(a2a): link follow-up messages via reference_task_ids May 20, 2026
@giles17 giles17 changed the title Python: feat(a2a): link follow-up messages via reference_task_ids Python: feat(a2a): link follow-up messages via reference_task_ids May 20, 2026
@moonbox3
Copy link
Copy Markdown
Contributor

moonbox3 commented May 20, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/a2a/agent_framework_a2a
   _agent.py3672294%254, 262, 453, 458, 460, 515–516, 546–547, 551, 693, 709, 721, 748, 769, 816, 832, 842, 853, 860–861, 912
TOTAL35379410888% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
7036 30 💤 0 ❌ 0 🔥 1m 50s ⏱️

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_id onto session.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.

giles17 and others added 2 commits May 21, 2026 10:43
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>
@giles17 giles17 changed the title Python: feat(a2a): link follow-up messages via reference_task_ids feat(a2a): add A2AAgentSession and reference_task_ids linking May 21, 2026
Avoids importing private _deserialize_state, matching the
DurableAgentSession pattern.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@giles17 giles17 marked this pull request as draft May 21, 2026 17:58
@giles17 giles17 marked this pull request as ready for review May 21, 2026 17:58
Copy link
Copy Markdown
Contributor Author

@giles17 giles17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Comment thread python/packages/a2a/agent_framework_a2a/_agent.py Outdated
Comment thread python/packages/a2a/agent_framework_a2a/_agent.py Outdated
Comment thread python/packages/a2a/agent_framework_a2a/_agent.py
Comment thread python/packages/a2a/agent_framework_a2a/_agent.py Outdated
giles17 added 2 commits May 21, 2026 13:38
# Conflicts:
#	python/packages/a2a/agent_framework_a2a/_agent.py
@giles17 giles17 requested a review from SergeyMenshykh May 21, 2026 20:55
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>
@giles17 giles17 changed the title feat(a2a): add A2AAgentSession and reference_task_ids linking feat(a2a): add A2AAgentSession with reference_task_ids and input-required support May 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants