Skip to content

Python: [Bug]: An answered request_info is asked again under a new auto:: id when a sibling @step was running while it paused #9517

Open

Description

Observed Behavior

In a functional workflow, asyncio.gather runs a @step beside a step that calls ctx.request_info without a request_id. The request pauses the run as auto::0 while the sibling step is still in flight. Since 1.22.0 (#9291), the sibling step then completes and its result is cached.

When the run is resumed with responses={"auto::0": ...}, the sibling step is served from the cache, and the request is issued again as auto::1. The answer to auto::0 is never delivered, and the run pauses a second time for input it has already received. Only a second answer, to auto::1, completes the run.

A client that answers each request once therefore sees the workflow ask the same question twice, under different ids.

Expected Behavior

The resumed run delivers the response to auto::0 and completes, as it does when the sibling step finishes before the request is made, or when the request has an explicit request_id.

Steps to Reproduce

  1. Define a functional workflow that asyncio.gathers a @step that awaits (here asyncio.sleep(0.01)) and a @step that calls ctx.request_info(...) without a request_id.
  2. Run it. The run pauses with the pending request auto::0.
  3. Resume with responses={"auto::0": 10}. The run pauses again, now with the pending request auto::1, and produces no output.

Minimal Reproduction

import asyncio

from agent_framework import RunContext, step, workflow


@step
async def work(x: int) -> int:
    await asyncio.sleep(0.01)  # Still running when its sibling asks for input.
    return x + 1


@step
async def ask(x: int, ctx: RunContext) -> int:
    return await ctx.request_info("a number?", int)  # No request_id: an automatic auto::<index> id.


@workflow
async def flow(x: int) -> int:
    done, answer = await asyncio.gather(work(x), ask(x))
    return done + answer


app = flow.build()


async def main():
    result = await app.run(1)
    asked = [event.request_id for event in result.get_request_info_events()]
    print("first run asks:", asked)
    result = await app.run(responses={asked[0]: 10})
    again = [event.request_id for event in result.get_request_info_events()]
    print("after answering it, the run asks:", again, "outputs:", result.get_outputs())
    assert not again and result.get_outputs() == [12], "an answered request was asked again under a new id"


asyncio.run(main())

Error Messages and Stack Traces

first run asks: ['auto::0']
after answering it, the run asks: ['auto::1'] outputs: []
AssertionError: an answered request was asked again under a new id


On 1.20.0 and 1.21.0 the same script prints:


first run asks: ['auto::0']
after answering it, the run asks: [] outputs: [12]

Package Versions

agent-framework-core: 1.22.0 (also main at ebcf4db)

Python Version

Python 3.13.9

Operating System

macOS

Regression

Yes

Additional Context

Acknowledgements

  • I searched existing issues and did not find a duplicate.
  • I personally verified this behavior and the reproduction details are authentic.
  • I will wait for explicit maintainer agreement before starting implementation of a non-trivial change.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 18, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 18, 2026
  3. github-actions commented on Oct 18, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    The bug reproduces in python/packages/core/agent_framework/_workflows/_functional.py::StepWrapper.__call__ around lines 1572-1594 and _return_cached_result around lines 1467-1472 when a cached step overlaps a sibling’s automatic request_info call. Minimal repro: gather a sleeping @step with a @step calling ctx.request_info without an explicit ID, then resume auto::0; the run requests auto::1 and returns no output.

    • Failing test: python/packages/core/tests/workflow/test_functional_workflow.py::TestDeterministicAutoRequestId::test_cached_concurrent_sibling_does_not_advance_auto_request_id_counter
    • Files examined: python/packages/core/agent_framework/_workflows/_functional.py, python/packages/core/tests/workflow/test_functional_workflow.py, python/packages/core/pyproject.toml
    • Tests run: TestDeterministicAutoRequestId::test_auto_request_id_roundtrips_on_resume, TestDeterministicAutoRequestId::test_cached_step_advances_auto_request_id_counter, TestDeterministicAutoRequestId::test_cached_concurrent_sibling_does_not_advance_auto_request_id_counter
    • Reported version: 1.22.0
    • Current version: 1.22.0
  4. added
    workflowsUsage: [Issues, PRs], Target: Workflows
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowworkflowsUsage: [Issues, PRs], Target: Workflows

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions