Skip to content

fix(a2a): respect auto_create_session flag in A2A executor session preparation#5351

Open
nickchecan wants to merge 5 commits intogoogle:mainfrom
nickchecan:fix/a2a-auto-create-session
Open

fix(a2a): respect auto_create_session flag in A2A executor session preparation#5351
nickchecan wants to merge 5 commits intogoogle:mainfrom
nickchecan:fix/a2a-auto-create-session

Conversation

@nickchecan
Copy link
Copy Markdown

Problem:
When a Runner is configured with auto_create_session=False, the A2A executor
layer completely bypasses this flag. Both A2aAgentExecutor._prepare_session
(legacy executor) and _A2aAgentExecutor._resolve_session (new executor impl)
call runner.session_service.get_session() and runner.session_service.create_session()
directly, instead of going through runner._get_or_create_session() (the method
that actually checks the auto_create_session flag). As a result, sessions are
always silently auto-created regardless of the flag value, making it impossible
to enforce explicit session management in A2A workflows.

Additionally, to_a2a()'s internally created Runner did not set
auto_create_session=True, which would cause every incoming A2A request to fail
with SessionNotFoundError since A2A clients never pre-create sessions.

Solution:

  • Replace direct session_service calls in _prepare_session and
    _resolve_session with runner._get_or_create_session(). This single method
    already encapsulates the auto_create_session logic and raises
    SessionNotFoundError when the flag is False and the session is missing.
  • Set auto_create_session=True in to_a2a()'s internal create_runner, to
    preserve backward-compatible behavior for users who rely on to_a2a() to handle
    session lifecycle automatically.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Updated tests in test_a2a_agent_executor.py and test_a2a_agent_executor_impl.py
to mock runner._get_or_create_session instead of runner.session_service.get_session
/ create_session. Rewrote test_resolve_session_creates_new_session to verify
the correct method and arguments are used.

Fixed tests/unittests/a2a/integration/server.py to pass auto_create_session=True
to FakeRunner, restoring the pre-fix behavior for integration tests where sessions
are always created on-the-fly.

pytest tests/unittests/a2a/ -v
...
56 passed, 139 warnings

pytest tests/unittests/ -v
...
5456 passed, 1 skipped, 2240 warnings in 130.24s

Manual End-to-End (E2E) Tests:

Created a minimal A2A server using to_a2a() with a LiteLLM-backed agent and
tested three scenarios:

Scenario 1 — auto_create_session=True (default via to_a2a):

curl -s -X POST http://localhost:8000/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "message/send",
    "params": {
      "message": {
        "messageId": "msg-1",
        "role": "user",
        "parts": [{"kind": "text", "text": "What time is it?"}]
      }
    }
  }' | python3 -m json.tool
{
    "result": {
        "status": { "state": "completed" },
        "artifacts": [
            { "parts": [{ "kind": "text", "text": "It's currently 2026-04-15 22:51:30 UTC." }] }
        ]
    }
}
Test 1 - Auto Create

Scenario 2 — auto_create_session=False with missing session:

{
    "result": {
        "status": {
            "state": "failed",
            "message": {
                "parts": [{ "kind": "text", "text": "Session not found: <session_id>" }]
            }
        }
    }
}
Test 2 - Session Not Found

Scenario 3 — auto_create_session=False with pre-created session:
Session pre-created via lifespan hook → request succeeds with state: completed.

curl -s -X POST http://localhost:8000/ \   
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "message/send",
    "params": {
      "message": {
        "messageId": "msg-1",
        "role": "user",
        "contextId": "my-test-session",
        "parts": [{"kind": "text", "text": "What time is it?"}]
      }
    }
  }' | python3 -m json.tool
Test 3 - It works when there's a session

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

The runner._get_or_create_session() method already existed and was used
correctly by all other runner entry points (run_async, run_live,
rewind_async). The A2A executor was the only layer that bypassed it, making
auto_create_session unreliable in A2A-based deployment.

@adk-bot adk-bot added the services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc label Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants