You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AdkApp and A2aAgent (the vertexai.agent_engines / google-cloud-aiplatform
templates) are mutually exclusive on a single Agent Engine, so there is no
supported way to deploy one reasoning engine that serves both the ADK data plane
and A2A:
AdkApp.register_operations() returns only the ADK data-plane modes
("", async, stream, async_stream → stream_query, sessions, artifacts, …).
A2aAgent.register_operations() returns only a2a_extension
(on_message_send, on_get_task, …).
An agent that needs its ADK data plane (e.g. it relies on :streamQuery, or on
the durable self-:asyncQuery query-job pattern) and wants to be reachable
by external A2A clients must hand-build a custom hybrid template. We built and
verified one, but this should be first-class.
This is distinct from two existing issues: #6274 (upgrade a2a-sdk to 1.x)
fixes the version conflict but does not provide a hybrid deployment; #6220
(adk deploy doesn't provision :asyncQuery) is orthogonal. Neither removes the
need for the workaround here. (Treating this as a bug rather than a feature: the
platform already accepts a hybrid spec — see Observed Behavior — there is just no
template/option that produces one.)
Steps to Reproduce:
Mutual exclusivity is visible with no deploy and no credentials — just inspect
what each template registers:
Install google-adk and google-cloud-aiplatform (+ a2a-sdk 1.x).
Run the snippet under "Minimal Reproduction Code" below.
Observe that AdkApp registers only the ADK modes and A2aAgent registers
only a2a_extension — with no option/flag/helper to get both on one engine.
Expected Behavior:
A first-class way to expose A2A alongside the ADK data plane on one Agent
Engine — e.g. an AdkApp(..., a2a=True, agent_card=...) option, or a supported
composition helper / template — so one engine exposes both :streamQuery
(+ sessions, + the durable self-:asyncQuery) and /a2a.
Observed Behavior:
Each template exposes only its own half:
AdkApp.register_operations() -> ['', 'async', 'stream', 'async_stream'] # no A2A
A2aAgent.register_operations()-> ['a2a_extension'] # no data plane
The platform itself does accept a hybrid: our hand-built subclass (an AdkApp
that composes an A2aAgent around the same ADK Runner and merges register_operations()), deployed via the GenAI client, produced a single engine
whose spec has both surfaces, and both :streamQuery and /a2a (message:send)
respond on it:
So the gap is purely the missing template/option, not a backend limitation.
Environment Details:
ADK Library Version (pip show google-adk): 2.2.0 (2.3.0 still pins a2a-sdk>=0.3.4,<0.4)
Desktop OS: Linux
Python Version (python -V): 3.13
Model Information:
Are you using LiteLLM: No
Which model is being used: gemini-2.5-flash (irrelevant — this is a deploy/templating issue)
🟡 Optional Information
Additional Context:
Use case. An ADK orchestrator on Agent Engine that (1) runs long-running work
as durable query jobs it submits against itself (run_query_job / :asyncQuery,
which needs the ADK stream_query op registered on the engine) and (2) must be
reachable from a UI over the A2A protocol. A pure A2aAgent satisfies (2) but
drops the ADK ops, breaking (1); a pure AdkApp satisfies (1) but has no A2A.
What we had to build. Subclass AdkApp, compose an A2aAgent around the same Runner, and merge the op maps:
Deployed via the GenAI client (client.agent_engines.update/create), because
only that path writes the top-level spec.agent_card; the vertexai.agent_engines.create/update proto (ReasoningEngineSpec) in this SDK
version has no agent_card field.
Related version conflict (mostly covered by #6274). We could not use google.adk.a2a (A2aAgentExecutor): google-adk pins a2a-sdk>=0.3.4,<0.4,
but the Agent Engine A2A runtime and A2aAgent template are a2a-sdk 1.x /
protocol 1.0 (create_agent_card emits supported_interfaces at HTTP+JSON/1.0;
the handler is validate_version(PROTOCOL_VERSION_1_0)). So we installed a2a-sdk[http-server]>=1.0,<2, avoided google.adk.a2a, and wrapped an ADK coreRunner in a hand-written a2a-sdk 1.x AgentExecutor. If #6274 lands,
that executor could be ADK's own — but the hybrid registration/deploy is still
needed.
Papercuts encountered (may be separate/docs):
A2A-Version: 1.0 header is mandatory. Missing → read as 0.3 and
rejected (400 VERSION_NOT_SUPPORTED, "A2A version '0.3' is not supported by
this handler. Expected version '1.0'."). The a2a-sdk ClientFactory sets it
via setdefault, so SDK clients are fine; hand-rolled HTTP must add it.
Executor event ordering. Emitting a TaskStatusUpdateEvent
(TaskUpdater.start_work()) before enqueuing the initial Task → 500 INVALID_AGENT_RESPONSE ("Agent should enqueue Task before
TaskStatusUpdateEvent event"). A clearer error / guardrail would help.
Default in-memory task store.A2aAgent defaults to InMemoryTaskStore,
so a tasks/{id} GET after the request returns 404 TASK_NOT_FOUND
(surprising on a multi-instance serverless runtime; message:send returns the
completed task synchronously, so it's survivable).
Request. Provide one of: an AdkApp(..., a2a=True, agent_card=...) option that
merges a2a_extension into register_operations() and wires an A2aAgentExecutor around the app's Runner; or a supported composition helper
(e.g. to_a2a(app, keep_adk_ops=True)) / Agent-Engine template yielding a
deployable object with both surfaces; plus clearer runtime errors for papercuts
(1)–(2). The templates live in google-cloud-aiplatform while to_a2a / A2aAgentExecutor live in adk-python, so the fix may span both repos; filing
here to start the conversation.
🔴 Required Information
Describe the Bug:
AdkAppandA2aAgent(thevertexai.agent_engines/google-cloud-aiplatformtemplates) are mutually exclusive on a single Agent Engine, so there is no
supported way to deploy one reasoning engine that serves both the ADK data plane
and A2A:
AdkApp.register_operations()returns only the ADK data-plane modes(
"",async,stream,async_stream→stream_query, sessions, artifacts, …).A2aAgent.register_operations()returns onlya2a_extension(
on_message_send,on_get_task, …).An agent that needs its ADK data plane (e.g. it relies on
:streamQuery, or onthe durable self-
:asyncQueryquery-job pattern) and wants to be reachableby external A2A clients must hand-build a custom hybrid template. We built and
verified one, but this should be first-class.
This is distinct from two existing issues: #6274 (upgrade
a2a-sdkto 1.x)fixes the version conflict but does not provide a hybrid deployment; #6220
(
adk deploydoesn't provision:asyncQuery) is orthogonal. Neither removes theneed for the workaround here. (Treating this as a bug rather than a feature: the
platform already accepts a hybrid spec — see Observed Behavior — there is just no
template/option that produces one.)
Steps to Reproduce:
Mutual exclusivity is visible with no deploy and no credentials — just inspect
what each template registers:
google-adkandgoogle-cloud-aiplatform(+a2a-sdk1.x).AdkAppregisters only the ADK modes andA2aAgentregistersonly
a2a_extension— with no option/flag/helper to get both on one engine.Expected Behavior:
A first-class way to expose A2A alongside the ADK data plane on one Agent
Engine — e.g. an
AdkApp(..., a2a=True, agent_card=...)option, or a supportedcomposition helper / template — so one engine exposes both
:streamQuery(+ sessions, + the durable self-
:asyncQuery) and/a2a.Observed Behavior:
Each template exposes only its own half:
The platform itself does accept a hybrid: our hand-built subclass (an
AdkAppthat composes an
A2aAgentaround the same ADKRunnerand mergesregister_operations()), deployed via the GenAI client, produced a single enginewhose spec has both surfaces, and both
:streamQueryand/a2a(message:send)respond on it:
So the gap is purely the missing template/option, not a backend limitation.
Environment Details:
a2a-sdk>=0.3.4,<0.4)Model Information:
🟡 Optional Information
Additional Context:
Use case. An ADK orchestrator on Agent Engine that (1) runs long-running work
as durable query jobs it submits against itself (
run_query_job/:asyncQuery,which needs the ADK
stream_queryop registered on the engine) and (2) must bereachable from a UI over the A2A protocol. A pure
A2aAgentsatisfies (2) butdrops the ADK ops, breaking (1); a pure
AdkAppsatisfies (1) but has no A2A.What we had to build. Subclass
AdkApp, compose anA2aAgentaround the sameRunner, and merge the op maps:Deployed via the GenAI client (
client.agent_engines.update/create), becauseonly that path writes the top-level
spec.agent_card; thevertexai.agent_engines.create/updateproto (ReasoningEngineSpec) in this SDKversion has no
agent_cardfield.Related version conflict (mostly covered by #6274). We could not use
google.adk.a2a(A2aAgentExecutor):google-adkpinsa2a-sdk>=0.3.4,<0.4,but the Agent Engine A2A runtime and
A2aAgenttemplate are a2a-sdk 1.x /protocol 1.0 (
create_agent_cardemitssupported_interfacesatHTTP+JSON/1.0;the handler is
validate_version(PROTOCOL_VERSION_1_0)). So we installeda2a-sdk[http-server]>=1.0,<2, avoidedgoogle.adk.a2a, and wrapped an ADKcore
Runnerin a hand-written a2a-sdk 1.xAgentExecutor. If #6274 lands,that executor could be ADK's own — but the hybrid registration/deploy is still
needed.
Papercuts encountered (may be separate/docs):
A2A-Version: 1.0header is mandatory. Missing → read as0.3andrejected (
400 VERSION_NOT_SUPPORTED, "A2A version '0.3' is not supported bythis handler. Expected version '1.0'."). The a2a-sdk
ClientFactorysets itvia
setdefault, so SDK clients are fine; hand-rolled HTTP must add it.TaskStatusUpdateEvent(
TaskUpdater.start_work()) before enqueuing the initialTask→500 INVALID_AGENT_RESPONSE("Agent should enqueue Task beforeTaskStatusUpdateEvent event"). A clearer error / guardrail would help.
A2aAgentdefaults toInMemoryTaskStore,so a
tasks/{id}GET after the request returns404 TASK_NOT_FOUND(surprising on a multi-instance serverless runtime;
message:sendreturns thecompleted task synchronously, so it's survivable).
adk api_server --a2asilently mounts no A2A routes (UnboundLocalErroron
jsoninget_fast_api_app). Filed separately — seeadk api_server --a2asilently mounts no A2A routes:UnboundLocalErroronjsoninget_fast_api_app#6332.Request. Provide one of: an
AdkApp(..., a2a=True, agent_card=...)option thatmerges
a2a_extensionintoregister_operations()and wires anA2aAgentExecutoraround the app'sRunner; or a supported composition helper(e.g.
to_a2a(app, keep_adk_ops=True)) / Agent-Engine template yielding adeployable object with both surfaces; plus clearer runtime errors for papercuts
(1)–(2). The templates live in
google-cloud-aiplatformwhileto_a2a/A2aAgentExecutorlive inadk-python, so the fix may span both repos; filinghere to start the conversation.
Minimal Reproduction Code:
Also relevant:
google-cloud-aiplatform1.159.0,a2a-sdk1.1.0 (protocol 1.0),target Vertex AI Agent Engine (
us-central1).How often has this issue occurred?: