.NET: Track and update A2A task state - #7998
Conversation
Use the streaming agent API for new A2A messages so task responses continue receiving status and artifact updates. Aggregate updates for non-immediate requests and preserve response metadata in completed task artifacts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82ccdf82-97a9-4d31-a66a-9641edbccd35
There was a problem hiding this comment.
Pull request overview
Updates A2A hosting to stream agent responses into task state and artifacts.
Changes:
- Routes new messages through streaming execution.
- Supports immediate streaming and aggregated task/message responses.
- Adds coverage for response modes, empty responses, and metadata.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
dotnet/src/Microsoft.Agents.AI.Hosting.A2A/A2AAgentHandler.cs |
Implements streaming and task aggregation. |
dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/A2AAgentHandlerTests.cs |
Tests routing and task lifecycle behavior. |
dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/A2AServerServiceCollectionExtensionsTests.cs |
Adds end-to-end server response tests. |
Suppressed comments (1)
dotnet/src/Microsoft.Agents.AI.Hosting.A2A/A2AAgentHandler.cs:102
- Routing the non-streaming endpoint through this helper drops the run-mode value that the previous path passed as
AgentRunOptions.AllowBackgroundResponses: the shared helper callsCreateRunOptions(context)without the result of_runMode. Implementations such asFoundryHostedRequestAgentandChatClientAgentuse this option to activate background/resumable execution, soAllowBackgroundIfSupportednow only wraps a foreground run in a task andDisallowBackgroundno longer explicitly disables it. Evaluate the run mode before creating the options and pass that result into the streaming run.
await this.HandleNewMessageStreamingAsync(context, eventQueue, aggregateTaskUpdates, cancellationToken).ConfigureAwait(false);
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (1 commit(s)): b811d678ea46
Model: gpt-5.6-sol
Overview
The review found 4 verified inline finding(s).
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
4 verified findings remained after source verification (1 high, 3 medium) across 1 file. Details are attached to the affected lines below.
Affected areas: dotnet/src/Microsoft.Agents.AI.Hosting.A2A/A2AAgentHandler.cs
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82ccdf82-97a9-4d31-a66a-9641edbccd35
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82ccdf82-97a9-4d31-a66a-9641edbccd35
There was a problem hiding this comment.
MAF Automated Review — Iteration 2
Result: No findings
Scope: 2 net-new commit(s): a123466c41cf, c6f388123935
Model: gpt-5.6-sol-fast
Overview
This incremental change closes the previously reported post-submission lifecycle gap by transitioning aggregated tasks to Canceled or Failed with an uncancelled token when result emission fails. The extracted artifact helper preserves the existing event shape, and focused tests exercise both cancellation and serialization failure after submission. No new Critical, High, or Medium defect was established in the authoritative incremental range.
Reviewed the supplied incremental change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.
| /// </description></item> | ||
| /// </list> | ||
| /// </remarks> | ||
| private async Task HandleNewMessageStreamingAsync(RequestContext context, AgentEventQueue eventQueue, bool aggregateTaskUpdates, CancellationToken cancellationToken) |
There was a problem hiding this comment.
Suggest renaming this method as this is not a streaming-only behavior and now has more responsibility.
| private async Task HandleNewMessageStreamingAsync(RequestContext context, AgentEventQueue eventQueue, bool aggregateTaskUpdates, CancellationToken cancellationToken) | |
| private async Task HandleNewMessageCoreAsync(RequestContext context, AgentEventQueue eventQueue, bool aggregateTaskUpdates, CancellationToken cancellationToken) |
Motivation & Context
A2A hosting can return either a message or a task. Previously, when it returned a background task, subsequent agent updates were not applied, leaving the task indefinitely in the
Workingstate.This change uses the agent streaming API for both response types. The server either aggregates updates into a message, returns an initial task and continues updating it, or waits for the stream to finish and returns the completed task.
Description & Review Guide
ReturnImmediately. Background-disabled registrations aggregate the stream into a message. The task aggregation path also preserves response metadata on artifacts, and the four server/client response combinations have dedicated coverage.AgentRunModeandReturnImmediately, and on task artifact construction in the aggregate path.Related Issue
Fixes #5362
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.