Context
.NET PR #5743 actually does three things in code:
- Tracks the A2A
TaskState on the session (A2AAgentSession.TaskState, threaded through UpdateSession).
- In
A2AAgent.CreateA2AMessage, branches on typedSession.TaskState == TaskState.InputRequired:
- InputRequired: sets
a2aMessage.TaskId = typedSession.TaskId so the reply is bound to the existing task as input.
- Otherwise: sets
a2aMessage.ReferenceTaskIds = [typedSession.TaskId] for task refinements.
- Surfaces the input-request message parts on
AgentResponseUpdate for TaskStatusUpdateEvent via a new AgentTaskStatusExtensions.GetUserInputRequests() helper that returns the status message''s AIContent parts only when State == InputRequired.
Current Python state
python/packages/a2a/agent_framework_a2a/_agent.py:
- The session has no equivalent
task_state tracking; only task_id / context_id are kept.
_prepare_message_for_a2a (~L621) never sets task_id, even when the prior task was TASK_STATE_INPUT_REQUIRED, so replies are not bound to the in-flight task on the server.
_updates_from_task_update_event does emit parts from status.message, but it does not gate on INPUT_REQUIRED or signal to the caller that the surfaced content is an input request rather than ordinary intermediate output.
Proposed change
- Track the current
TaskState on the A2A session (mirror A2AAgentSession.TaskState).
- In
_prepare_message_for_a2a, branch on the previous task state:
- if
INPUT_REQUIRED → set a2a_message.task_id = previous_task_id;
- else → set
a2a_message.reference_task_ids = [previous_task_id] (see the companion "Link follow-up messages via reference_task_ids" issue).
- Add a helper analogous to
GetUserInputRequests that returns the status-message parts only when state == INPUT_REQUIRED, and use it when building AgentResponseUpdates for input-required status events so callers can distinguish input requests from regular intermediate content.
Context
.NET PR #5743 actually does three things in code:
TaskStateon the session (A2AAgentSession.TaskState, threaded throughUpdateSession).A2AAgent.CreateA2AMessage, branches ontypedSession.TaskState == TaskState.InputRequired:a2aMessage.TaskId = typedSession.TaskIdso the reply is bound to the existing task as input.a2aMessage.ReferenceTaskIds = [typedSession.TaskId]for task refinements.AgentResponseUpdateforTaskStatusUpdateEventvia a newAgentTaskStatusExtensions.GetUserInputRequests()helper that returns the status message''sAIContentparts only whenState == InputRequired.Current Python state
python/packages/a2a/agent_framework_a2a/_agent.py:task_statetracking; onlytask_id/context_idare kept._prepare_message_for_a2a(~L621) never setstask_id, even when the prior task wasTASK_STATE_INPUT_REQUIRED, so replies are not bound to the in-flight task on the server._updates_from_task_update_eventdoes emit parts fromstatus.message, but it does not gate onINPUT_REQUIREDor signal to the caller that the surfaced content is an input request rather than ordinary intermediate output.Proposed change
TaskStateon the A2A session (mirrorA2AAgentSession.TaskState)._prepare_message_for_a2a, branch on the previous task state:INPUT_REQUIRED→ seta2a_message.task_id = previous_task_id;a2a_message.reference_task_ids = [previous_task_id](see the companion "Link follow-up messages viareference_task_ids" issue).GetUserInputRequeststhat returns the status-message parts only whenstate == INPUT_REQUIRED, and use it when buildingAgentResponseUpdates for input-required status events so callers can distinguish input requests from regular intermediate content.