.NET: [Breaking] Migrate A2A agent and hosting to A2A SDK v1#5423
.NET: [Breaking] Migrate A2A agent and hosting to A2A SDK v1#5423SergeyMenshykh merged 13 commits intomainfrom
Conversation
Move the A2A sample projects (A2AAgent_AsFunctionTools and A2AAgent_PollingForTaskCompletion) from samples/04-hosting/A2A/ to samples/02-agents/A2A/ to better align with the sample directory structure. Update solution file and samples README accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add SSE stream reconnection support to A2AAgent Implement automatic reconnection for SSE streams that disconnect mid-task, using the Last-Event-ID header to resume from where the stream left off. Changes: - Add InvokeStreamingWithReconnectAsync method to A2AAgent with configurable max retries and delay between attempts - Add new log messages for reconnection events - Add A2AAgent_StreamReconnection sample demonstrating the feature - Update existing polling sample to use simplified SendMessageAsync API - Add unit tests for stream reconnection logic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * address comments * Address PR review feedback - Dispose SSE enumerator before GetTaskAsync fallback to release HTTP connection - Wrap StreamWriter in using blocks with leaveOpen:true and explicit UTF-8 encoding - Print update.Text instead of update object in stream reconnection sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Refactor A2A extensions to use IA2AClientFactory and add ProtocolSelection sample - Update A2AAgentCardExtensions to accept IA2AClientFactory instead of A2AClientOptions - Update A2ACardResolverExtensions to accept IA2AClientFactory - Update A2AClientExtensions to accept IA2AClientFactory - Update A2AAgent to use IA2AClientFactory for client creation - Add A2AAgent_ProtocolSelection sample demonstrating protocol selection - Add comprehensive unit tests for all changes - Update README files with new sample reference Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Reorder params: options before loggerFactory in A2A extensions Move A2AClientOptions parameter before ILoggerFactory in AsAIAgent and GetAIAgentAsync extension methods to follow the repo convention of keeping LoggerFactory and CancellationToken as the last parameters. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* .NET: Migrate A2A hosting to A2A SDK v1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * remove unused agent card --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* .NET: Refactor A2A hosting registration into A2AServerServiceCollectionExtensions - Rename A2AHostingOptions to A2AServerRegistrationOptions - Move server registration logic from A2AEndpointRouteBuilderExtensions and AIAgentExtensions into new A2AServerServiceCollectionExtensions - Remove A2AProtocolBinding and AIAgentExtensions (consolidated) - Update samples and tests to use the new registration API Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * address copilot comments --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Migrates the .NET A2A agent + hosting layers to align with A2A SDK 1.0.0-preview2, including updated request/response models, hosting registration/mapping APIs, and refreshed samples/tests reflecting v1 behaviors (including stream reconnection patterns).
Changes:
- Update core A2A agent + extension APIs to v1 SDK types (
IA2AClient,SendMessageRequest/Response,StreamResponse,SupportedInterfaces, etc.). - Replace legacy hosting mapping/extensions with
AddA2AServer(...)registration + protocol-specific endpoint mapping (MapA2AHttpJson,MapA2AJsonRpc) and a newA2AAgentHandler. - Reorganize/extend samples and significantly expand/modernize unit tests for the new API surface.
Reviewed changes
Copilot reviewed 50 out of 54 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/Converters/MessageConverterTests.cs | Updates converter tests for v1 request/message types. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/AgentRunModeTests.cs | Adds unit tests for the new/updated AgentRunMode behavior. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/AIAgentExtensionsTests.cs | Removes tests tied to deleted legacy hosting extensions. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/A2AIntegrationTests.cs | Removes integration tests tied to the old hosting surface. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/A2AEndpointRouteBuilderExtensionsTests.cs | Updates tests for new endpoint mapping + server registration APIs. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/A2AAgentHandlerTests.cs | Adds coverage for the new A2AAgentHandler execution/cancel flows. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Microsoft.Agents.AI.A2A.UnitTests.csproj | Adjusts test TFMs to match updated dependencies/compatibility. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/ChatMessageExtensionsTests.cs | Updates message conversion tests for v1 Part model. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AClientExtensionsTests.cs | Adds tests ensuring extensions work on IA2AClient. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2ACardResolverExtensionsTests.cs | Updates card resolver tests for SupportedInterfaces + protocol selection options. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AArtifactExtensionsTests.cs | Updates artifact conversion tests for new Part creation APIs. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AAgentTaskExtensionsTests.cs | Updates task conversion tests for v1 status/task types. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AAgentCardExtensionsTests.cs | Expands tests for protocol binding selection and error cases. |
| dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/Extensions/A2AAIContentExtensionsTests.cs | Updates AIContent→A2A part conversion tests for v1 part model. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A/Converters/MessageConverter.cs | Switches message conversion to v1 SendMessageRequest model. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A/AgentRunMode.cs | Fixes default/dynamic run-mode decision semantics and docs. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A/AIAgentExtensions.cs | Removes legacy hosting extension entrypoints. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A/A2AServerServiceCollectionExtensions.cs | Introduces AddA2AServer DI registration keyed by agent name. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A/A2AServerRegistrationOptions.cs | Adds options object for A2A server registration configuration. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A/A2ARunDecisionContext.cs | Updates run-decision context to v1 RequestContext input. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A/A2AAgentHandler.cs | Adds new handler bridging AIAgent to A2A v1 hosting model. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/Microsoft.Agents.AI.Hosting.A2A.AspNetCore.csproj | Adjusts packaging/warnings to keep Hosting.A2A transitively referenced. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/EndpointRouteBuilderExtensions.cs | Removes old monolithic MapA2A endpoint mapping extensions. |
| dotnet/src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/A2AEndpointRouteBuilderExtensions.cs | Adds protocol-specific endpoint mapping (HTTP+JSON vs JSON-RPC). |
| dotnet/src/Microsoft.Agents.AI.A2A/Microsoft.Agents.AI.A2A.csproj | Updates TFMs to align with the repo’s core target frameworks. |
| dotnet/src/Microsoft.Agents.AI.A2A/Extensions/ChatMessageExtensions.cs | Updates chat message conversion to v1 Message/Role. |
| dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AClientExtensions.cs | Moves extension surface from A2AClient to IA2AClient. |
| dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2ACardResolverExtensions.cs | Adds A2AClientOptions support for protocol binding preference. |
| dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AAgentCardExtensions.cs | Switches client creation to A2AClientFactory.Create with options. |
| dotnet/src/Microsoft.Agents.AI.A2A/A2AAgentLogMessages.cs | Adds log message for SubscribeToTask→GetTask fallback path. |
| dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs | Migrates to v1 SDK APIs, adds SubscribeToTask fallback handling, updates streaming event handling. |
| dotnet/samples/README.md | Updates sample category descriptions after A2A sample move. |
| dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs | Updates web chat client for v1 SendMessageResponse union model. |
| dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.AgentHost/Program.cs | Switches hosting to AddA2AServer + MapA2AHttpJson endpoint mapping. |
| dotnet/samples/05-end-to-end/A2AClientServer/A2AServer/Program.cs | Updates server sample to new registration + mapping model and well-known card mapping. |
| dotnet/samples/05-end-to-end/A2AClientServer/A2AServer/HostAgentFactory.cs | Updates agent card creation for SupportedInterfaces and multi-url support. |
| dotnet/samples/05-end-to-end/A2AClientServer/A2AClient/Program.cs | Simplifies output handling using AgentResponse.Text. |
| dotnet/samples/02-agents/README.md | Adds A2A section entry under 02-agents. |
| dotnet/samples/02-agents/A2A/README.md | Fixes links and lists new A2A samples. |
| dotnet/samples/02-agents/A2A/A2AAgent_StreamReconnection/README.md | Adds documentation for stream reconnection sample. |
| dotnet/samples/02-agents/A2A/A2AAgent_StreamReconnection/Program.cs | Adds sample demonstrating continuation-token-based stream reconnection. |
| dotnet/samples/02-agents/A2A/A2AAgent_StreamReconnection/A2AAgent_StreamReconnection.csproj | Adds project for the new stream reconnection sample. |
| dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/README.md | Adds documentation for protocol selection sample. |
| dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/Program.cs | Adds sample demonstrating A2AClientOptions.PreferredBindings usage. |
| dotnet/samples/02-agents/A2A/A2AAgent_ProtocolSelection/A2AAgent_ProtocolSelection.csproj | Adds project for the protocol selection sample. |
| dotnet/samples/02-agents/A2A/A2AAgent_PollingForTaskCompletion/README.md | Adds documentation for polling-for-completion sample. |
| dotnet/samples/02-agents/A2A/A2AAgent_PollingForTaskCompletion/Program.cs | Updates polling sample to explicitly enable background responses. |
| dotnet/samples/02-agents/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj | Normalizes TFM property name and removes unnecessary package reference. |
| dotnet/samples/02-agents/A2A/A2AAgent_AsFunctionTools/README.md | Adds documentation for A2A-as-tools sample under new location. |
| dotnet/samples/02-agents/A2A/A2AAgent_AsFunctionTools/Program.cs | Adds sample wiring A2A agent skills into function tools for another agent. |
| dotnet/samples/02-agents/A2A/A2AAgent_AsFunctionTools/A2AAgent_AsFunctionTools.csproj | Adds project for A2A-as-tools sample under new location. |
| dotnet/agent-framework-dotnet.slnx | Moves A2A samples folder and adds new sample projects to the solution. |
| dotnet/Directory.Packages.props | Bumps A2A + related dependency versions to match SDK v1 requirements. |
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 86%
✓ Correctness
No actionable issues found in this dimension.
✓ Security Reliability
The changes are well-structured with proper input validation, async patterns, resource management, and cancellation support. No blocking security or reliability issues were found. Minor suggestions relate to defensive error handling edge cases in the new A2AgentHandler and continuation token deserialization.
✓ Test Coverage
Existing tests (on the base branch) reference old APIs (
MapA2A,typeof(A2AClient),MessageSendParams) that are changed or removed by this PR. TheAllowBackgroundResponses → ReturnImmediatelymapping andContinuationTokenon streaming task updates are new behaviors without test coverage. Test files may appear in later review chunks, but the gaps are noted here for tracking. The new tests are well-structured and cover important new behaviors: IA2AClient constructor, streaming with continuation tokens (SubscribeToTask with fallback to GetTask), ReturnImmediately/blocking configuration, preferred protocol bindings, and GetService for IA2AClient vs concrete A2AClient. Test assertions are meaningful (not just no-exception checks) and the mock stub was properly extended to support new error simulation scenarios. The only minor gap is that the AgentRunMode fallback path (line 82) changed from true to false but remains unreachable through the public API and thus untestable without reflection. However, several test scenarios from the deleted AIAgentExtensionsTests.cs were not carried forward into the new files. Notably: (1) no test verifies that non-null RequestContext.Metadata is forwarded as AdditionalProperties to the agent — only the null-metadata path is tested; (2) the AIAgent overloads of MapA2AHttpJson/MapA2AJsonRpc and AddA2AServer(IServiceCollection, AIAgent) lost all argument-validation tests when AIAgentExtensionsTests was deleted; (3) MessageConverter.ToParts has no test coverage despite being exercised in production paths. The new A2AAgentHandlerTests are well-structured with meaningful assertions and proper mock setup, and AgentRunModeTests provides thorough equality/hashing/toString coverage.
✗ Design Approach
There is also a weaker API-design concern in the new ASP.NET mapping surface: it hard-codes a stub
AgentCard, which pushes agent-card wiring out to separate manual setup and makes discovery behavior depend on implementation details of the hosting split. The other visible changes here look like API-shape and test updates rather than approach problems. I also see a smaller API-contract concern where the new AgentRunMode tests lock in value equality for dynamic modes even when their callbacks do opposite things.
Flagged Issues
- MapA2AHttpJson hard-codes a stub AgentCard, so the
{path}/cardendpoint loses the meaningful metadata and URL population that the previousMapA2A(..., AgentCard)flow provided. Wire the real AgentCard through theAddA2AServer/mapping API instead.
Suggestions
- In
A2AAgentHandler.HandleTaskUpdateAsync, thecatch(Exception)block callsfailUpdater.FailAsyncwith the samecancellationToken. If the token is already cancelled,FailAsynccould throw and mask the original exception. Consider usingCancellationToken.Nonefor theFailAsynccall. - In
A2AContinuationToken.FromToken(line 55),reader.GetString()!uses the null-forgiving operator for thetaskIdvalue. If the JSON contains a nulltaskId, this silently becomes null and is only caught later by the constructor'sThrow.IfNullOrEmpty. Add an explicit null check with a descriptiveJsonExceptionfor better diagnostics. - The new production classes
A2AAgentHandler,SubscribeToTaskWithFallbackAsync,A2AServerServiceCollectionExtensions, andA2AEndpointRouteBuilderExtensionsall lack test coverage. Each has significant branching or DI wiring logic that would only surface failures at runtime. See inline comments for per-class test scenarios. - The AgentRunMode fallback at line 82 (changed from
truetofalse) is unreachable through the public API. While the fix correctly aligns with the comment ('fall back to message behavior'), consider adding a code comment noting this is a defensive fallback. - Add argument-validation tests for the
AIAgentoverloads ofMapA2AHttpJsonandMapA2AJsonRpc(null agent, null/whitespaceagent.Name). The oldAIAgentExtensionsTestscovered these scenarios but was deleted without replacement. - Add argument-validation tests for
AddA2AServer(IServiceCollection, AIAgent, ...)— the overload at A2AServerServiceCollectionExtensions line 117 has null checks forservices,agent, andagent.Namewith no test coverage. - Consider adding at least one test for
MessageConverter.ToParts, which is used inA2AAgentHandler(lines 148, 170) to produce artifact and message parts. Currently only the reverse direction (ToChatMessages) is tested.
Automated review by SergeyMenshykh's agents
There was a problem hiding this comment.
Automated Code Review
Reviewers: 2 | Confidence: 89%
✗ Security Reliability
The new AgentRunModeTests.cs contains a test (
Equals_AllowBackgroundWhen_DifferentDelegates_AreNotEqual) that will fail at runtime: it asserts two AllowBackgroundWhen instances with different delegates are not equal, but AgentRunMode.Equals (AgentRunMode.cs:86-87) only compares the internal_valuestring (both are "dynamic"), ignoring delegate identity. Either the implementation must be updated to compare delegates, or the test expectation is wrong. The MessageConverterTests updates (type renames to SendMessageRequest, Message, Role, Part) and new ToParts tests look sound. The deletion of EndpointRouteA2ABuilderExtensionsTests.cs removes 21 unit tests covering the 23 MapA2A production overloads with no replacement tests.
✗ Design Approach
The new endpoint/server split drops agent-card metadata from the A2A hosting abstraction and replaces it with a hard-coded stub, which makes discovery an opt-in side path instead of part of server registration. Separately, the
IA2AClientrefactor narows an existing compatibility surface by stoppingA2Agent.GetService(typeof(A2AClient))from resolving the client, even though the current public extension/tests still treat the concreteA2AClientas the contract. Moving A2Agent to work with IA2AClient is a reasonable direction, but the new tests explicitly codify that GetService(typeof(A2AClient)) now returns null. That changes an existing retrieval contract without a strong reason: callers that previously obtained the concrete client from A2Agent will break even when the underlying instance is still an A2AClient. The rest of the changes here mostly look like a straightforward SDK-shape migration and added coverage. The test split is headed in a better direction, but two parts of the new approach still miss the contract they claim to protect. The handler tests route null session-store cases through a helper that eagerly substitutesInMemoryAgentSessionStore, so those tests never exercise the production defaulting path at all. And the newAddA2AServerDI tests only prove thatA2AServercan be resolved, not that keyed custom stores/handlers are actually wired through, so the main registration risk could still slip by. I also think dropping the only end-to-end agent-card URL test leaves an important cross-layer behavior unguarded. The addedAgentRunModeandMessageConvertertests improve coverage of the new behavior, but deletingEndpointRouteA2ABuilderExtensionsTestsleaves the ASP.NET entry-point layer largely unverified. The remaining coverage I found only exercises one happy-path card endpoint (A2AIntegrationTests.cs:22-83) plus lower-levelAIAgentExtensionsbehavior, so the publicMapA2A(...)overloads, their null-guard contracts, keyed-agent resolution, andconfigureTaskManagerdelegation inEndpointRouteBuilderExtensions.cs:36-377are no longer directly protected.
Flagged Issues
- AgentRunModeTests.Equals_AllowBackgroundWhen_DifferentDelegates_AreNotEqual will fail: AgentRunMode.Equals (AgentRunMode.cs:86-87) only compares the _value string field, not the delegate. Both AllowBackgroundWhen instances have _value="dynamic", so Equals returns true, causing Assert.False(true) to throw. Either update AgentRunMode.Equals to include delegate identity or fix the test expectation.
- Removing
EndpointRouteA2ABuilderExtensionsTestsleaves the ASP.NET entry-point layer largely unverified. The publicMapA2A(...)overloads inEndpointRouteBuilderExtensions.cs:36-377perform distinct outer-layer work (keyed DI lookup, callback delegation, null guards), but the only remaining route-level coverage is a single integration happy path. Keep a slim set of focused unit tests for the route-builder layer alongside the integration test.
Suggestions
- Keep the internal field/constructor typed as
IA2AClientif desired, but preserveGetService(typeof(A2AClient))compatibility (or support both service types when the underlying instance is concrete). - Keep one black-box HTTP test for agent-card URL population. That behavior spans endpoint mapping and
AIAgentExtensionsmutatingagentCard.UrlinOnAgentCardQuery, and deleting it removes the only end-to-end check of that contract.
Automated review by SergeyMenshykh's agents
Add three tests to A2AServerServiceCollectionExtensionsTests that verify custom keyed services are actually wired through to the A2AServer, not just that the server resolves non-null: - Custom IAgentHandler: verifies the keyed handler is invoked when processing a SendMessageRequest instead of the default A2AAgentHandler. - Custom AgentSessionStore (no handler): verifies the keyed session store's GetSessionAsync is called during request processing when no custom handler is registered. - Default stores end-to-end: verifies the InMemoryAgentSessionStore and InMemoryTaskStore defaults successfully process a request. Uses a new CreateAgentMockForRequests helper that includes SerializeSessionCoreAsync setup needed by InMemoryAgentSessionStore. All tests call A2AServer.SendMessageAsync directly (no HTTP layer needed) and use CancellationToken timeouts to guard against hangs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Migrate the .NET A2A agent and hosting packages from A2A SDK
0.3.4-previewto1.0.0-preview2. This is a comprehensive update that reworks the agent, hosting, and extension APIs to align with the v1 SDK, adds SSE stream reconnection support, and reorganizes samples.What Changed
Core Agent (
Microsoft.Agents.AI.A2A)A2AAgentfor v1 SDK APIs — updated message/task handling and streaming logic.A2AAgentCardExtensionsandA2ACardResolverExtensionsto useA2AClientFactory.Create()for client creation and accept an optionalA2AClientOptionsfor protocol binding preference.A2AClientExtensionsto operate onIA2AClientinterface instead of concreteA2AClient.Hosting (
Microsoft.Agents.AI.Hosting.A2A/.AspNetCore)A2AAgentHandler— new handler aligned with v1 SDK hosting model.A2AServerRegistrationOptions— configuration for server registration.A2AServerServiceCollectionExtensions— consolidated DI registration for A2A servers.A2AEndpointRouteBuilderExtensions— protocol-specific endpoint mapping methods.EndpointRouteBuilderExtensions(replaced byA2AEndpointRouteBuilderExtensions).AIAgentExtensions(logic consolidated intoA2AServerServiceCollectionExtensions).Samples
samples/04-hosting/A2A/tosamples/02-agents/A2A/.A2AAgent_ProtocolSelection— demonstrates protocol selection.A2AAgent_StreamReconnection— demonstrates SSE stream reconnection.A2AClientServer,AgentWebChat, andA2AAgent_PollingForTaskCompletionto use the new APIs.Closes: