Skip to content

Conversation

@majiayu000
Copy link
Contributor

@majiayu000 majiayu000 commented Jan 1, 2026

Summary

This PR adds convenient http.Handler constructors to the adka2a package, addressing the feedback in #419.

New Functions

Function Return Type Description
NewJSONRPCHandler http.Handler Ready-to-use handler for A2A JSON-RPC transport
NewServeMux *http.ServeMux Complete server with agent card + invoke endpoints
NewRequestHandler a2asrv.RequestHandler Transport-agnostic handler for custom transports (gRPC, etc.)

Design Rationale

The key insight from the initial review was that returning a2asrv.RequestHandler doesn't provide enough value—users still need to import a2asrv and wrap it themselves. This revision takes a different approach:

  1. Complete abstraction: NewJSONRPCHandler and NewServeMux return standard library types (http.Handler / *http.ServeMux), so users don't need to know about a2asrv at all.

  2. Layered API: Three functions at different abstraction levels:

    • NewServeMux - Highest level, one-liner server setup
    • NewJSONRPCHandler - Mid level, for custom routing
    • NewRequestHandler - Low level, for custom transports
  3. Consistency with adkrest: Follows the same pattern as adkrest.NewHandler.

Before/After Comparison

Before (current):

mux := http.NewServeMux()
mux.Handle(a2asrv.WellKnownAgentCardPath, a2asrv.NewStaticAgentCardHandler(agentCard))

executor := adka2a.NewExecutor(adka2a.ExecutorConfig{...})
requestHandler := a2asrv.NewHandler(executor)
mux.Handle("/invoke", a2asrv.NewJSONRPCHandler(requestHandler))

After (with this PR):

mux := adka2a.NewServeMux(adka2a.HandlerConfig{
    ExecutorConfig: adka2a.ExecutorConfig{...},
    AgentCard:      agentCard,
})

Test Plan

  • Added unit tests for all new functions
  • Tests verify handler creation and basic HTTP responses
  • All existing tests pass
  • Updated example in examples/a2a/main.go to use new API

Related Issues

Fixes #419

🤖 Generated with Claude Code

Add NewHandler function that creates and returns an http.Handler for the
A2A JSON-RPC API. This follows the same pattern as the adkrest package,
providing a convenient way to create an A2A handler without having to
manually create the executor and wrap it with a2asrv handlers.

Fixes google#419

Signed-off-by: majiayu000 <1835304752@qq.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @majiayu000, 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 enhances the adka2a package by providing a convenient, pre-configured HTTP handler for its JSON-RPC API. This change abstracts away the manual setup of executors and request handlers, offering a streamlined way to integrate the A2A service into HTTP servers, mirroring existing patterns for ease of use and consistency.

Highlights

  • New HTTP Handler for A2A JSON-RPC API: Introduced a new NewHandler function that returns an http.Handler for the A2A JSON-RPC API, simplifying the setup process.
  • Handler Configuration: Added a HandlerConfig struct to provide a structured way to configure the A2A HTTP handler, including executor and A2A request handler options.
  • Consistent Pattern: The new handler implementation follows the established pattern seen in adkrest.NewHandler, ensuring consistency across the codebase.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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
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 new http.Handler for the A2A JSON-RPC API, simplifying the setup for consumers of this package. The implementation is clean and follows existing patterns. My review includes a minor suggestion to improve the test code by removing a redundant check. Overall, the changes look good and improve the library's API.

Comment on lines 47 to 49
if _, ok := handler.(http.Handler); !ok {
t.Fatal("NewHandler() did not return an http.Handler")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The function signature for NewHandler already specifies a return type of http.Handler. The Go compiler guarantees that the returned value will be of this type, so this type assertion is redundant. The nil check on line 43 is sufficient to ensure a valid handler was returned.

@baptmont baptmont requested a review from yarolegovich January 2, 2026 11:20
func NewHandler(config HandlerConfig) http.Handler {
executor := NewExecutor(config.ExecutorConfig)
reqHandler := a2asrv.NewHandler(executor, config.A2AOptions...)
return a2asrv.NewJSONRPCHandler(reqHandler)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is very opinionated towards JSONRPC, I will revisit this PR after we confirm the intention behind the issue reported. Thank you for your contribution

@majiayu000
Copy link
Contributor Author

majiayu000 commented Jan 4, 2026

@baptmont Updated the change to be transport-agnostic: adka2a.NewRequestHandler now returns an a2asrv.RequestHandler that callers can wrap with the transport they want (e.g., a2asrv.NewJSONRPCHandler). Removed the JSONRPC-specific handler and the redundant type assertion in the test. Please take another look.

@yarolegovich
Copy link
Member

I think it's a very shallow utility, which is close to a simple re-export of a function provided by a2a SDK. Developers will need to import a2asrv anyway to init server with infra connectors (a2asrv.WithTaskStore etc.), so why not just create a handler using a2asrv.NewHandler?

This addresses the review feedback by providing a higher-level API that
eliminates the need for users to import and understand the a2asrv package.

Changes:
- NewJSONRPCHandler: Returns http.Handler directly (recommended for most users)
- NewServeMux: Returns complete http.ServeMux with agent card + invoke endpoints
- NewRequestHandler: Kept for custom transport layers (gRPC, etc.)
- Updated HandlerConfig to include optional AgentCard field
- Added comprehensive tests for all new functions
- Updated example to use the simplified NewServeMux API

Before (required understanding a2asrv):
```go
executor := adka2a.NewExecutor(config)
requestHandler := a2asrv.NewHandler(executor)
mux.Handle("/invoke", a2asrv.NewJSONRPCHandler(requestHandler))
mux.Handle(a2asrv.WellKnownAgentCardPath, a2asrv.NewStaticAgentCardHandler(card))
```

After (one-liner):
```go
mux := adka2a.NewServeMux(adka2a.HandlerConfig{
    ExecutorConfig: config,
    AgentCard:      card,
})
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@majiayu000
Copy link
Contributor Author

@yarolegovich Thanks for the feedback! I've refactored the implementation to address your concern.

The key insight from your comment was that returning a2asrv.RequestHandler alone doesn't provide enough value since users still need to import a2asrv.

In this update, I've taken a different approach with a layered API:

Function Return Type Use Case
NewServeMux *http.ServeMux One-liner setup with agent card + invoke endpoints
NewJSONRPCHandler http.Handler Integration with custom HTTP routers
NewRequestHandler a2asrv.RequestHandler Custom transports (gRPC, etc.)

The value proposition:

  1. For common use cases (most users): NewServeMux and NewJSONRPCHandler return standard library types. Users don't need to import or understand a2asrv at all:
// Before: 5 lines, requires a2asrv import
mux := http.NewServeMux()
mux.Handle(a2asrv.WellKnownAgentCardPath, a2asrv.NewStaticAgentCardHandler(card))
executor := adka2a.NewExecutor(config)
requestHandler := a2asrv.NewHandler(executor)
mux.Handle("/invoke", a2asrv.NewJSONRPCHandler(requestHandler))

// After: 1 call, no a2asrv import needed
mux := adka2a.NewServeMux(adka2a.HandlerConfig{...})
  1. For advanced users (need WithTaskStore, etc.): NewRequestHandler accepts ...a2asrv.RequestHandlerOption, so they can still use all the a2asrv options while benefiting from the convenience:
handler := adka2a.NewJSONRPCHandler(config, 
    a2asrv.WithTaskStore(customDB),
    a2asrv.WithPushNotifications(store, sender),
)

This follows the same pattern as adkrest.NewHandler - providing high-level convenience while preserving flexibility for advanced configurations.

Copy link

@Virt10n01 Virt10n01 left a comment

Choose a reason for hiding this comment

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

locale?
Diff.txt

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.

adka2a should provide a http.Handler

4 participants