Skip to content

Align A2A client, hosting, and examples with .NET - #1268

Merged
Quim Muntal (qmuntal) merged 2 commits into
mainfrom
feat/a2a-dotnet-parity
Oct 8, 2026
Merged

Quim Muntal (qmuntal) merged 2 commits into
mainfrom
feat/a2a-dotnet-parity

Conversation

@qmuntal

Copy link
Copy Markdown
Member

Summary

  • Align A2A client conversion, sessions, factories, hosting modes, and lifecycle behavior with the pinned .NET Agent Framework source.
  • Add card/resolver factories, unified AgentRunMode factories, owned session persistence, and isolation-key-scoped native task storage.
  • Use the SDK handler for request-configuration forwarding and preservation of terminal responses; keep task metadata separate from artifact/status message metadata.
  • Update the A2A API assessments and direct test mappings in the existing symbol catalog.
  • Remove 30 redundant unpaired tests while preserving all 174 mapped A2A test bodies and 126 distinct Go-specific tests.
  • Align all seven existing A2A example programs with the current .NET scenarios: SDK factories, one whole-agent function tool, first-update stream interruption, and a direct policy client/server with both HTTP+JSON and JSON-RPC.

Parity Scope

Source and sample behavior were checked against microsoft/agent-framework commit 0c9944cc9f577d51277ac7c55dbc388b60a577af (Agent Framework 1.22.0; A2A assemblies are preview).

  • Preserve the Go SDK's single-run API and existing continuation-token representation.
  • Do not add DI or service lookup.
  • Leave core response collection unchanged. With artifact/status messages, response raw values retain the existing Go collector behavior rather than an independent raw task object.
  • Keep native protocol adaptations explicit instead of pairing analogous tests as direct .NET ports.
  • The policy server explicitly uses in-memory sessions, binds locally, and documents caller-isolation requirements before production exposure.

The branch is based on current main and contains only the A2A SDK, catalog, and example changes; earlier catalog-refactor commits are not included.

Validation

Validated the exact publication tree on Windows ARM64 with Go 1.26.1 and Go 1.27.0:

  • Full agent, provider/a2aprovider, and tool/agenttool unit suites.
  • Vet for affected SDK packages and all A2A examples; SDK/example compile checks.
  • Offline HTTP+JSON and JSON-RPC card-discovery, request-configuration, and shared-context probes.
  • Offline reconnection after the first streaming update, preserving the original continuation representation and context.
  • Strict API reconciliation: 874 linked rows, no invalid targets or reconciliation errors.
  • Strict test reconciliation: 558 linked pairs, no invalid targets or reconciliation errors.
  • AST audit confirms every retained A2A test signature/body is unchanged by duplicate cleanup; formatting and whitespace checks pass.

No cloud-backed E2E/replay suites, .NET test execution, benchmarks, or race runs were performed. Race execution is unsupported on the native Windows ARM64 toolchain. Temporary probes and build artifacts remain outside the repository.

@qmuntal
Quim Muntal (qmuntal) requested a review from a team as a code owner October 8, 2026 08:54
Copilot AI balanced review requested due to automatic review settings October 8, 2026 08:54
@github-actions github-actions Bot added area:examples Changes files in the examples area area:provider Changes files in the provider area area:provider/a2a Changes files in the provider / a2a area size:xlarge More than 300 changed lines or 10 files labels Oct 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Task-mode handler paths can silently discard session persistence failures after emitting terminal success.

1 open finding
What changed in this PR

Aligns the A2A provider, hosting lifecycle, persistence, factories, and examples with the pinned .NET implementation.

Changes:

  • Adds agent/card factories, run modes, session persistence, and isolation-scoped task storage.
  • Refines conversion, metadata, streaming, continuation, and handler behavior.
  • Updates A2A tests and examples for the revised APIs.
File Description
provider/​a2aprovider/​taskstore.go Adds isolation-key task storage.
provider/​a2aprovider/​taskstore_test.go Tests partitioning, pagination, and concurrency.
provider/​a2aprovider/​task.go Adds task conversion helpers.
provider/​a2aprovider/​sessionstore.go Adds persistent session-store abstraction.
provider/​a2aprovider/​session.go Exposes stored task state.
provider/​a2aprovider/​hosting_convert.go Filters and converts hosted output.
provider/​a2aprovider/​hosting_convert_test.go Updates conversion coverage.
provider/​a2aprovider/​handler.go Adds native handler and terminal-event handling.
provider/​a2aprovider/​factory_test.go Tests card and resolver factories.
provider/​a2aprovider/​executor.go Adds session persistence and run-mode execution.
provider/​a2aprovider/​convert_test.go Expands task and content conversion tests.
provider/​a2aprovider/​card.go Adds card-based agent factories.
provider/​a2aprovider/​artifact_stream.go Revises streamed artifact identity.
provider/​a2aprovider/​artifact_stream_test.go Updates artifact-ID expectations.
provider/​a2aprovider/​agentrunmode.go Adds configurable response modes.
provider/​a2aprovider/​a2a.go Revises client conversion and metadata handling.
provider/​a2aprovider/​a2a_test.go Expands client behavior coverage.
examples/​05-end-to-end/​a2a_client_server/​README.md Documents the policy-client scenario.
examples/​05-end-to-end/​a2a_client_server/​a2a_server/​main.go Hosts the policy agent over two transports.
examples/​05-end-to-end/​a2a_client_server/​a2a_client/​main.go Uses direct discovery and shared sessions.
examples/​02-agents/​providers/​a2a/​main.go Uses the resolver factory.
examples/​02-agents/​a2a/​stream_reconnection/​main.go Reconnects after the first update.
examples/​02-agents/​a2a/​protocol_selection/​main.go Uses factory transport selection.
examples/​02-agents/​a2a/​polling_for_task_completion/​main.go Uses the card factory.
examples/​02-agents/​a2a/​as_function_tools/​main.go Wraps the whole remote agent as one tool.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread provider/a2aprovider/executor.go
@github-actions github-actions Bot added kind:code Changes production behavior or code kind:examples Changes examples or example-support metadata kind:tests Changes tests, fixtures, or test infrastructure labels Oct 8, 2026
@github-actions

This comment has been minimized.

@github-actions github-actions Bot added parity-approved Go API consistency review found no parity issues public-api-change Pull Request changes public APIs labels Oct 8, 2026
@github-actions github-actions Bot added the kind:docs Changes documentation or comments label Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

API consistency review

Result Scope
aligned public API / user-visible behavior / examples

Changed Go contract

  • New exported AgentRunMode type (provider/a2aprovider/agentrunmode.go) with ReturnMessage(), ReturnTask(), ReturnTaskWhen(decide), and (AgentRunMode).String(), consumed via ExecutorConfig.AgentRunMode.
  • New exported NewAgentFromCard / NewAgentFromResolver factory functions (provider/a2aprovider/card.go) that construct a client from an a2a.AgentCard / agentcard.Resolver, defaulting to HTTP+JSON-preferred transport and filling Name/Description from the card.
  • New exported NewHandler (provider/a2aprovider/handler.go) wrapping a2asrv.NewHandler with a configuration-forwarding call interceptor and a terminal-event-suppressing executor; new exported WithConfiguration run option.
  • New exported NewIsolationKeyScopedTaskStore/IsolationKeyScopedTaskStoreConfig (provider/a2aprovider/taskstore.go) that scopes a taskstore.Store by a resolved isolation key, opt-in via AllowUnscoped.
  • New exported SessionStore interface and NewInMemorySessionStore (provider/a2aprovider/sessionstore.go); new exported TaskStateFromSession (provider/a2aprovider/session.go).
  • Hosted-output conversion now filters FunctionCallContent/FunctionResultContent from outgoing A2A parts (hostedContentsToParts in hosting_convert.go).
  • All seven A2A examples were rewritten to use the new factories/handler and simplified scenarios.

Upstream evidence reviewed

Implementation Source Contract checked
.NET AgentRunMode.cs ReturnMessage/ReturnTask/ReturnTaskWhen semantics, default-to-message behavior, continuations skipping the decision delegate
.NET A2AServerRegistrationOptions.cs Null AgentRunMode defaults to ReturnMessage — matches Go's zero-value AgentRunMode{}
.NET A2AAgentHandler.cs Task vs. message aggregation combinations for streaming/non-streaming × ReturnImmediately, matching executeResponseMode in Go
.NET IsolationKeyScopedTaskStore.cs Escaped-prefix scoping/unscoping of task and context IDs, opt-in strict/AllowUnscoped gating
.NET A2AServerServiceCollectionExtensions.cs Isolation wrapping is opt-in (only applied when an AgentIsolationKeyProvider is registered) — Go mirrors this as an explicit constructor the caller must choose to use
.NET A2AAgentCardExtensions.cs, A2ACardResolverExtensions.cs AsAIAgent(card, ...) / resolver-based discovery helpers defaulting Name/Description from the card and preferring HTTP+JSON — matches Go's NewAgentFromCard/NewAgentFromResolver
.NET MessageConverterTests.cs FunctionCallContent is filtered out of outgoing A2A parts (ToParts returns only supported content) — matches Go's hostedContentsToParts filtering

Assessment

This PR is a parity-focused rewrite that introduces several new exported Go types/functions whose names, defaults, and behavior track existing .NET counterparts closely: AgentRunMode (value semantics and the message/task/dynamic decision table match AgentRunMode.ShouldReturnTaskAsync in .NET, including that continuations never invoke the decision delegate and the zero/default value returns a message); the isolation-scoped task store (escaping, prefix scoping/unscoping, opt-in strictness) mirrors IsolationKeyScopedTaskStore; the card/resolver-based agent factories mirror A2AAgentCardExtensions/A2ACardResolverExtensions; and the filtering of function-call/result content from hosted A2A output matches the .NET converter's behavior verified by its unit tests. The _catalog/dotnet-go-sdk-symbol-mapping.json updates reflect a systematic re-reconciliation of these mappings. No unconditional-enablement or default-divergence issues were found relative to the cited .NET sources; the example rewrites simplify scenarios but keep sample intent aligned with the hosting/factory APIs being exercised.

Generated by Go API Consistency Review Agent for #1268 · copilot · auto · 123.3 AIC · ⌖ 7.54 AIC · ⊞ 13.9K · ◷

@qmuntal
Quim Muntal (qmuntal) added this pull request to the merge queue Oct 8, 2026
Merged via the queue into main with commit bcee90f Oct 8, 2026
28 checks passed
@qmuntal
Quim Muntal (qmuntal) deleted the feat/a2a-dotnet-parity branch October 8, 2026 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:examples Changes files in the examples area area:provider/a2a Changes files in the provider / a2a area area:provider Changes files in the provider area kind:code Changes production behavior or code kind:docs Changes documentation or comments kind:examples Changes examples or example-support metadata kind:tests Changes tests, fixtures, or test infrastructure parity-approved Go API consistency review found no parity issues public-api-change Pull Request changes public APIs size:xlarge More than 300 changed lines or 10 files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants