Skip to content

feat(app): let an extension supply the A2A handler - #2544

Merged
EItanya merged 1 commit into
kagent-dev:mainfrom
jjamroga:extension-a2a-handler
Aug 25, 2026
Merged

feat(app): let an extension supply the A2A handler#2544
EItanya merged 1 commit into
kagent-dev:mainfrom
jjamroga:extension-a2a-handler

Conversation

@jjamroga

Copy link
Copy Markdown
Collaborator

Problem

grpcserver registers the A2A service only when A2AHandler is non-nil, and core/pkg/app never sets it. A controller built on app.Start can create AgentInstances but cannot talk to them:

Unimplemented: unknown service lf.a2a.v1.A2AService

core/cmd/controller-v2 does set it, but that is package main, so the capability is unreachable to anything embedding app.Start.

Change

ExtensionConfig gains an A2AHandler field, passed through to grpcserver. That's it — one file, two lines of code.

Nothing else changes. The field defaults to nil and grpcserver skips registration exactly as it does today, so this is inert unless an extension opts in.

It also needs no reordering: getExtensionConfig is called with the DbClient in BootstrapConfig well before the gRPC server is constructed, so an extension can build a handler with a2agateway.New and return it.

Alternative considered

I first went at this by exporting core/internal/grpcserver and adding a public constructor for the store, so the v2 stack could be assembled outside package main (#2543). This is much smaller, keeps the internals internal, and covers the actual need — so I've closed that one in favour of this.

The larger export still has an independent argument: it would let an external module stand up the gRPC surface with a real Postgres and fakes for a2agateway's dialer and agentinstance's actor client, and test AgentInstance lifecycle, ownership checks, A2A routing and DefaultMethodPolicies without a cluster or Substrate. Happy to revive it if that's wanted, but it shouldn't be bundled with this.

Testing

go build ./..., go vet, and go test ./core/pkg/app/ ./core/internal/grpcserver/ all pass.

grpcserver registers the A2A service only when A2AHandler is set, and
core/pkg/app never sets it. A controller built on app.Start can therefore
create AgentInstances but cannot talk to them:

  Unimplemented: unknown service lf.a2a.v1.A2AService

core/cmd/controller-v2 sets it, but that is package main, so the capability
is unreachable to anything embedding app.Start.

ExtensionConfig gains an A2AHandler field, passed through to grpcserver.
Nothing else changes: the field defaults to nil and grpcserver skips
registration exactly as it does today.

The extension can build a handler with a2agateway.New using the DbClient it
already receives in BootstrapConfig, which is resolved well before the gRPC
server is constructed, so no ordering change is needed either.

Signed-off-by: Jonathan Jamroga <jjamroga@gmail.com>
@jjamroga
jjamroga force-pushed the extension-a2a-handler branch from e588244 to 33b5ea1 Compare August 25, 2026 13:25
@EItanya
EItanya merged commit 2393ef7 into kagent-dev:main Aug 25, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants