Skip to content

feat: Add A2A.V0_3Compat server-side compat (v0.3 client → v1 server)#338

Open
xu-shanshan wants to merge 6 commits intoa2aproject:mainfrom
xu-shanshan:shanshan/issue-331-v03-client-v1-server-compat
Open

feat: Add A2A.V0_3Compat server-side compat (v0.3 client → v1 server)#338
xu-shanshan wants to merge 6 commits intoa2aproject:mainfrom
xu-shanshan:shanshan/issue-331-v03-client-v1-server-compat

Conversation

@xu-shanshan
Copy link
Copy Markdown
Contributor

@xu-shanshan xu-shanshan commented Mar 25, 2026

Summary

  • New project A2A.V0_3Compat — server-side compat layer so a v0.3 client (work-iq-cli) can call a v1.0 server (Sydney) without any changes on the client side.
  • MapA2AWithV03Compat endpoint extension — drop-in replacement for MapA2A; accepts v0.3 JSON-RPC wire format, translates to v1.0, calls IA2ARequestHandler, translates responses back to v0.3.
  • A2AClientFactory enhancementsCreate(string agentCardJson, Uri baseUrl, ...) detects protocol version from raw JSON; RegisterFallback/ClearFallback for global v0.3 client factory; per-call FallbackFactory on A2AClientOptions.
  • Agent-preference ordering restored in A2AClientFactory.Create(AgentCard, ...) — spec §8.3 requires agent's declared interface order to win; previous version iterated client preferences instead.

What it translates

Layer v0.3 wire → v1.0
Method names message/send, tasks/get, etc. SendMessage, GetTask, etc.
Enums kebab-case ("working") SCREAMING_SNAKE_CASE ("TASK_STATE_WORKING")
Part structure kind discriminator field-presence
Streaming SSE with v0.3 JsonRpcResponse wrapper v1 StreamResponse

Test plan

  • All existing tests pass (328 A2A.UnitTests + 68 A2A.AspNetCore.UnitTests + 262 A2A.V0_3.UnitTests)
  • 41 new A2A.V0_3Compat.UnitTests pass (factory detection, type conversion round-trips, V03ServerProcessor routing)
    • 30 unit tests for factory and type conversion
    • 11 unit tests for V03ServerProcessor — covers v1.0 method bypass (commit 49d5f02), CheckPreflight delegation (commit 06c0417), and all error cases
  • Sydney: call MapA2AWithV03Compat and send v0.3 request from work-iq-cli to verify end-to-end

Closes #331

🤖 Generated with Claude Code

…0.3 detection

- Add V03ServerProcessor: handles v0.3 JSON-RPC wire format (method names,
  param types, enum values) and translates to/from v1.0 before calling the
  IA2ARequestHandler. Supports both non-streaming and SSE streaming paths.
- Add V03ServerCompatEndpointExtensions.MapA2AWithV03Compat: drop-in
  replacement for MapA2A that accepts v0.3 client requests on a v1.0 server.
- Add V03JsonRpcResponseResult and V03JsonRpcStreamedResult: IResult
  implementations that serialize responses in v0.3 wire format.
- Extend V03TypeConverter with server-side conversion methods:
  v0.3 request params → v1.0 request types, and v1.0 responses → v0.3.
- Add A2AClientFactory.Create(string agentCardJson, Uri baseUrl, ...):
  detects protocol version from raw JSON and routes to v1 client or fallback.
- Add A2AClientFactory.RegisterFallback/ClearFallback for global v0.3 client
  factory registration; add per-call FallbackFactory on A2AClientOptions.
- Restore agent-preference ordering in A2AClientFactory.Create(AgentCard, ...)
  (agent's declared interface order wins per spec §8.3).
- Add A2A.V0_3Compat.UnitTests covering factory detection and type conversion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new compatibility layer (A2A.V0_3Compat) to enable seamless communication between older v0.3 clients and newer v1.0 servers. It achieves this by providing automatic translation of requests and responses between the two protocol versions, both on the client and server sides. Additionally, the A2AClientFactory has been enhanced to intelligently detect protocol versions from agent cards and utilize fallback mechanisms for older clients, ensuring a smoother migration path.

Highlights

  • New project A2A.V0_3Compat: A server-side compatibility layer has been introduced to allow v0.3 clients (like work-iq-cli) to interact with v1.0 servers (Sydney) without requiring client-side modifications.
  • MapA2AWithV03Compat endpoint extension: This new endpoint acts as a drop-in replacement for MapA2A, translating incoming v0.3 JSON-RPC requests to v1.0, processing them with IA2ARequestHandler, and converting responses back to v0.3 wire format.
  • A2AClientFactory enhancements: The A2AClientFactory now includes a Create overload that detects the protocol version from raw agent card JSON. It also supports global and per-call fallback factories (RegisterFallback/ClearFallback and A2AClientOptions.FallbackFactory) for handling v0.3 clients.
  • Agent-preference ordering restored: The A2AClientFactory.Create(AgentCard, ...) method now correctly prioritizes the agent's declared interface order as per spec §8.3, resolving an issue where client preferences were previously iterated instead.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a compatibility layer to enable A2A v0.3 clients to interact with v1.0 servers and vice-versa. Key changes include a new A2A.V0_3Compat project with a V03ClientAdapter for client-side protocol translation, and V03ServerProcessor and V03ServerCompatEndpointExtensions for server-side handling of mixed v0.3/v1.0 requests. The A2AClientFactory has been extended to automatically detect protocol versions from agent cards and use a configurable fallback mechanism for v0.3. A critical issue was identified in the V03ServerProcessor where, despite documentation, it currently only processes v0.3 methods, causing v1.0 requests to fail with a 'Method not found' error. This requires either implementing v1.0 request handling or updating the documentation to reflect v0.3-only support.

Shanshan Xu (from Dev Box) and others added 3 commits March 26, 2026 22:12
…zation

V03.JsonRpcRequestConverter rejects v1.0 method names (e.g. SendMessage,
GetTask, SendStreamingMessage) with MethodNotFound during deserialization,
making the default passthrough case in HandleSingleAsync unreachable.

Fix: parse the request body once via JsonDocument to peek at the method
field, then route to a new HandleV1RequestAsync path if the method is not
a recognized v0.3 name. HandleV1RequestAsync bypasses the V03 deserializer
entirely and delegates directly to A2AJsonRpcProcessor.

Also:
- Promote A2AJsonRpcProcessor.SingleResponseAsync and StreamResponse to
  public so V03ServerProcessor can call them
- Add MapAgentCardGetWithV03Compat extension: serves AgentCard in v0.3 or
  v1.0 format based on A2A-Version header negotiation
- Add V03TypeConverter.ToV03AgentCard for v1.0→v0.3 AgentCard conversion
- Bump version to 1.0.0-preview3

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sor.CheckPreflight

Extract version header validation from A2AJsonRpcProcessor.ProcessRequestAsync
into a new public static CheckPreflight method. V03ServerProcessor now calls
CheckPreflight instead of duplicating the logic, making it a true extension
of the v1.0 processor rather than a parallel implementation.

Any future protocol-level checks added to CheckPreflight automatically apply
to both the v1.0 and v0.3 compat paths.

Bump version to 1.0.0-preview4.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@xu-shanshan xu-shanshan reopened this Mar 26, 2026
Shanshan Xu (from Dev Box) and others added 2 commits March 26, 2026 23:24
…eckPreflight delegation

Tests for commit 49d5f02 (v1.0 method bypass) and 06c0417 (CheckPreflight delegation):
- v1.0 method names (SendMessage, GetTask) route via HandleV1RequestAsync, bypass V03 deserializer
- unsupported A2A-Version header returns -32009 before body is parsed
- v0.3 method names (message/send, tasks/get, tasks/cancel) translate and return v0.3 wire format
- v0.3 response uses lowercase state, not TASK_STATE_*
- malformed JSON and missing method field return parse error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A2A.V0_3Compat and A2A.V0_3Compat.UnitTests were missing from A2A.slnx,
so dotnet test run by CI skipped all 41 compat unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@xu-shanshan
Copy link
Copy Markdown
Contributor Author

CI failure note (commit 4fe0513):

The buildSamples / .NET check failed with:

A2A.UnitTests.Server.ChannelEventNotifierTests.AcquireTaskLockAsync_BlocksConcurrentAccess
Assert.True() Failure — Expected: True, Actual: False

This is a pre-existing flaky timing testgit diff origin/main ... -- tests/A2A.UnitTests/ shows an empty diff; the test file was last touched in 464beb6 before this PR. The test uses Task.Delay(200) to wait for a Task.Run task to start, which fails on slow CI runners.

Fix in latest commit (a6a3f5f):

A2A.V0_3Compat and A2A.V0_3Compat.UnitTests were missing from A2A.slnx, so CI was skipping all 41 compat unit tests. Added both projects to the solution. 41 compat tests pass locally on net8.0 and net10.0.

A maintainer re-approval of CI workflows is needed to trigger a new run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A2AClient does not fall back to v0.3 when server does not support v1.0

1 participant