Repository navigation
A2A with agent engine session service in api_server runtime #3458
Description
Describe the bug
It's not possible to use agent-engine session service with A2A
To Reproduce
Run your ADK agent like this
adk api_server --a2a --host 0.0.0.0 --port 8080 --session_service_uri "agentengine://${AGENT_ENGINE_ID}" --memory_service_uri "agentengine://${AGENT_ENGINE_ID}"
You get this error when you use the A2A Endpoint (I use it with Agent Space (a.k.a Gemini Enterprise))
Traceback (most recent call last):
File "/usr/local/lib/python3.12/site-packages/google/adk/a2a/executor/a2a_agent_executor.py", line 167, in execute
await self._handle_request(context, event_queue)
File "/usr/local/lib/python3.12/site-packages/google/adk/a2a/executor/a2a_agent_executor.py", line 208, in _handle_request
session = await self._prepare_session(context, run_request, runner)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/adk/a2a/executor/a2a_agent_executor.py", line 303, in _prepare_session
session = await runner.session_service.get_session(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/adk/sessions/vertex_ai_session_service.py", line 162, in get_session
get_session_response, events_iterator = await asyncio.gather(
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/vertexai/_genai/sessions.py", line 882, in get
response = await self._api_client.async_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1365, in async_request
result = await self._async_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1310, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1290, in _async_request_once
await errors.APIError.raise_for_async_response(client_response)
File "/usr/local/lib/python3.12/site-packages/google/genai/errors.py", line 166, in raise_for_async_response
raise ClientError(status_code, response_json, response)
google.genai.errors.ClientError: 400 INVALID_ARGUMENT. {'error': {'code': 400, 'message': 'List of found errors:\t1.Field: name; Message: Invalid Session resource name.\t', 'status': 'INVALID_ARGUMENT', 'details': [{'@type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'field': 'name', 'description': 'Invalid Session resource name.'}]}]}}
If you start the agent without the session and memory service
adk api_server --a2a --host 0.0.0.0 --port 8080
You will use the InMemoryService and it works well
Expected behavior
I expect no error when I use AgentEngine memory service and A2A.
A2A invocation belonging to an external process/flow/session management, I would assume that the A2A request do not need persistent session service. So, having InMemory session service only for the A2A endpoint is fine in my opinion
Desktop (please complete the following information):
- Python version(python -V): 3.12.11
- ADK version(pip show google-adk): 1.18.0
Model Information:
- Are you using LiteLLM: No
- Which model is being used(e.g. gemini-2.5-pro): gemini-2.5-flash
Additional context
I would imagine solving the issue here
And I imagine a runner update like this.
async def _get_a2a_runner_async() -> Runner:
original_runner = await adk_web_server.get_runner_async(captured_app_name)
runner = copy.copy(original_runner) # Create a shallow copy
runner.memory_service = InMemoryMemoryService()
runner.session_service = InMemorySessionService()
runner.artifact_service = InMemoryArtifactService()
runner.credential_service = InMemoryCredentialService()
return runner
return _get_a2a_runner_async
What do you think?
Activity
[-]A2A with agent engine session service[/-][+]A2A with agent engine session service in api_server runtime[/+]narmada-nannaka commentedon Nov 28, 2025
Alternative Solution: FirestoreSessionService for A2A Persistence
Hi @guillaumeblaquiere,
I've been exploring the session service + A2A integration challenge and developed a potential solution using Firestore as a custom session backend.
Context
I'm working on a multi-agent system where:
Approach
I implemented a
FirestoreSessionService(BaseSessionService)that:RemoteA2aAgentSimplified Example
Usage with A2A
Proposal
Rather than limiting A2A to
InMemorySessionService, would maintainers be open to a PR contributingFirestoreSessionServiceas an alternative? This would:InMemorySessionService#2754 and aspects of Session State Leakage: Multiple Sessions Showing Accumulated Data #3513 as wellI can prepare:
contributing/samples/firestore_session_service/Would this be a useful addition? Happy to adapt to maintainer preferences or contribute as an example/pattern instead of core library if preferred.
guillaumeblaquiere commentedon Nov 28, 2025
Hello @narmada-nannaka
Thank you for this proposal that forced me to deep dive in the A2A protocol.
As outcome, I have 2 remarks:
If the session is not found in Firestore, you return None, that will lead to the same error as mine.
According to a contextID provided by the client, the agent MAY maintain the context and state. not a SHOULD or a MUST
So, my solution is not perfect, but finally acceptable and compliant with the protocol.
I think the best way to solve this would be to create automatically a session if the A2A protocol is active and the session not found. This solution won't work with AgentEngine session service because you can't define your own sessionID (here will be the ContextID provided by the client, if any, could be missing). But should work with non-managed session persistence services.
Eventually, it's only my opinion, and I'm not a maintainer, only a contributor. Maybe the team will have other remarks and point of view on your proposal!
narmada-nannaka commentedon Dec 1, 2025
Thank you for the detailed analysis, @guillaumeblaquiere!
You're absolutely right - I missed the critical auto-creation requirement for A2A workflows. I see the distinction now:
Two A2A Patterns
1. External A2A (your case): Client sends arbitrary contextId
2. Internal A2A (my case): I control both ends
Solutions for Each Pattern
Your InMemory solution is perfect for Pattern 1 (stateless, external clients).
My Firestore proposal could add value for:
Implementation Consideration
For auto-creating sessions with external clients, I'd suggest adding:
Example:
Would this be useful as an additional option alongside InMemory, or do you think the simplicity of InMemory makes it the better default for external A2A?
Looking forward to maintainer input on this!
guillaumeblaquiere commentedon Dec 10, 2025
I agree with you, my patch is too agressive. I should only set in-memory if it's with AgentEngine. Other solution would have the ability to create session with the contextID.
The problem with AgentEngine session service is that you can't provide sessionID (here the contextID) and you can't make the link between the subsequent calls. it's a lack in the current Google Cloud API. But DB session service, In memory, Firestore (...) does not have this limitation.
surajksharma07 commentedon Dec 14, 2025
The issue occurs because Agent Engine's session service doesn't support user-provided session IDs, but A2A endpoints map the context_id directly to session_id (see vertex_ai_session_service.py:103-107 and a2a/converters/request_converter.py:78-117).
Your proposed solution is correct - conditionally override the session service with InMemorySessionService for A2A endpoints when Agent Engine is configured.
This is compliant with the A2A protocol since agents MAY (not MUST) maintain state based on context_id.
Workaround: Remove the --session_service_uri and --memory_service_uri flags when running adk api_server --a2a, which defaults to InMemorySessionService and works correctly.
surajksharma07 commentedon Dec 14, 2025
@seanzhou1023 Please have a look into it.
surajksharma07 commentedon Feb 5, 2026
The bug still exists in v1.23.0 -
fast_api.py:491-494still uses the configured session service for A2A endpoints, which fails with Agent Engine.PR #3587 was not merged.
As a workaround, remove
--session_service_uriand--memory_service_uriflags when runningadk api_server --a2ato use InMemorySessionService by default.guillaumeblaquiere commentedon Apr 2, 2026
@surajksharma07 It's not a valid workaround if your agent must work with session when used by API, and work also with A2A. I do not want to deploy 2 versions of the same agent only for a session persistence issue.
GWeale commentedon Aug 6, 2026
thanks for flagging this, since v1.29.0 the vertex ai session service forwards a caller-supplied session id, which should let a2a create the session under the incoming context id. closing as stale, open with a fresh traceback if it still fails.
fix: agent engine memory service with A2A endpoint activated
fix: agent engine memory service with A2A endpoint activated