feat(core): build the A2A handler in core instead of exposing it to extensions - #2578
Draft
jjamroga wants to merge 1 commit into
Draft
feat(core): build the A2A handler in core instead of exposing it to extensions#2578jjamroga wants to merge 1 commit into
jjamroga wants to merge 1 commit into
Conversation
…xtensions The A2A gateway should not be injectable. It is a core component, not a policy decision, and the only parts of it an extension should influence are the ones it already supplies through pluggable interfaces: Authenticator and Authorizer. ExtensionConfig.A2AHandler inverts that: the one gRPC service that reaches agent runtimes gets whatever auth the embedder assembles for it, separately from the authenticator and authorizer it hands core for every other method. Every input a2agateway.New needs is already in scope in Start -- the db client, the instance workflow, the gateway URL, and the extension's own authenticator and authorizer -- so build the handler here and drop the field. Replaces -a2a-base-url with -a2a-gateway-url. The two described different endpoints: a2a-base-url named the HTTP A2A server on :8083 and has been dead config since kagent-dev#2565 removed the legacy ACP runtime, while the gateway URL is published in agent cards as the agent's gRPC interface and so must address the gRPC listener on :8084. The flag now matches the A2A_GATEWAY_URL env var and controller.a2aGatewayUrl chart value that core/cmd/controller-v2 and the chart already carry, and the dead a2aBaseUrl value, helper and configmap key are removed. Substrate is a required component. Start already dials ate-api unconditionally and exits when that fails, so -substrate-atenet-router-url now carries DefaultAtenetRouterURL as its actual default rather than treating "" as a sentinel meaning "use the default". An empty value is rejected where it is used: NewRuntimeDialer returns "atenet router URL must include a host", which is fatal at startup. Existing deployments are unaffected. build-controller builds core/cmd/controller-v2, which sets A2AHandler on grpcserver.Config directly and never reads ExtensionConfig, and the config that drives the gateway is unchanged. Only embedders of app.Start need a code change. Signed-off-by: Jonathan Jamroga <jjamroga@gmail.com>
jjamroga
force-pushed
the
core-builds-a2a-handler
branch
from
August 26, 2026 16:39
af343c5 to
87f7fae
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The A2A gateway should not be injectable. It is a core component, not a policy
decision, and the only parts of it an extension should influence are the ones it
already supplies through pluggable interfaces:
AuthenticatorandAuthorizer.Today
ExtensionConfig.A2AHandlerinverts that — the one gRPC service that reachesagent runtimes gets whatever auth the embedder assembles for it, separately from the
authenticator and authorizer it hands core for every other method. Everything
a2agateway.Newneeds is already in scope inStart, so build it there and drop thefield.
Existing deployments are unaffected.
build-controllerbuilds controller-v2, whichsets
A2AHandlerongrpcserver.Configdirectly and never readsExtensionConfig,and the config that drives the gateway —
A2A_GATEWAY_URLandcontroller.a2aGatewayUrl— is unchanged. Only embedders ofapp.Startneed a codechange.
Breaking changes
ExtensionConfig.A2AHandlerremoved — core builds the handler from theauthenticator and authorizer embedders already supply.
-a2a-base-url→-a2a-gateway-url— different endpoints.a2a-base-urlnamedthe HTTP server on
:8083and has been dead config since chore: remove legacy ACP and controller runtime #2565; the gateway URL ispublished in agent cards as the agent's gRPC interface and must address
:8084.The new flag matches the
A2A_GATEWAY_URLenv var andcontroller.a2aGatewayUrlchart value already in use, so deployments need no change.
-substrate-atenet-router-urldefaults toDefaultAtenetRouterURLinstead of"", which never meant "substrate absent".NewRuntimeDialerrejects an empty valueat startup.
A stale
A2A_BASE_URLenv var is silently ignored, but a stale-a2a-base-urlargument is a hard startup failure, since
flagrejects unknown flags. The chartconfigures by env, not args.
Testing
go build,go vet,go testclean. Chart suite 268/272 — the 4 failures arekagent-toolssubchart tests that fail identically on a clean checkout. Verified end toend in kind with Substrate against a downstream embedder of
app.Start:CreateAgentInstance,SendMessage,DeleteAgentInstanceallOK, agent reachedthrough the gateway and atenet router, no auth errors.
🤖 Generated with Claude Code