Skip to content

fix(server): run follow-up messages in the sender's contextvars - #1317

Merged
mykytanetipa merged 2 commits into
a2aproject:mainfrom
tejaskash:fix/active-task-sender-contextvars
Oct 6, 2026
Merged

mykytanetipa merged 2 commits into
a2aproject:mainfrom
tejaskash:fix/active-task-sender-contextvars

Conversation

@tejaskash

Copy link
Copy Markdown
Contributor

Description

ActiveTask creates its producer once, during the first request for a task. Later messages on the same task are queued to that producer, so AgentExecutor.execute() ran with the first request's contextvars. Per-request values set by ASGI middleware or a ServerCallContextBuilder (auth tokens, tenant identity, tracing) were stale on every follow-up turn, for example a reply after input-required.

This change captures contextvars.copy_context() in enqueue_request(), which runs in the sender's request, and runs execute() in that context as a child task. Awaiting the child keeps cancellation working, because cancelling the producer cancels the child. Context.run(asyncio.create_task, ...) works on Python 3.10.

Only execute() changes context. Task-store writes and push notifications still run in the producer's context, as before.

Tested:

  • New test_follow_up_message_runs_in_sender_contextvars, for both on_message_send and on_message_send_stream. It fails on main and passes with this change.

  • The reproduction in [Bug]: DefaultRequestHandler runs follow-up messages on a task with the first request's contextvars #1316 prints request-2 for the follow-up.

  • ./scripts/lint.sh passes. uv run pytest --cov=src gives 2223 passed, 93% coverage. tests/integration/cross_version/client_server/test_client_server.py was deselected because its server fails to start in my local environment on main too.

  • Follow the CONTRIBUTING Guide.

  • Make your Pull Request title in the https://www.conventionalcommits.org/ specification.

  • Ensure the tests and linter pass (Run bash scripts/format.sh from the repository root to format)

  • Appropriate docs were updated (if necessary)

Fixes #1316 🦕

ActiveTask creates its producer once, during the first request for a task,
so every later message on the task ran AgentExecutor.execute() with the
first request's contextvars. Capture the caller's context in
enqueue_request() and run execute() in it.

Fixes a2aproject#1316
@tejaskash
tejaskash requested a review from a team as a code owner October 5, 2026 19:27
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

🧪 Code Coverage (vs main)

⬇️ Download Full Report

No coverage changes.

Generated by coverage-comment.yml

@mykytanetipa mykytanetipa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mykytanetipa
mykytanetipa merged commit a016002 into a2aproject:main Oct 6, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: DefaultRequestHandler runs follow-up messages on a task with the first request's contextvars

2 participants