Skip to content

Python: [Bug]: Functional workflow response-only HITL resume loses user state #8299

Closed

Description

@CoralGarden52

Summary

A functional workflow loses user state when it resumes a human-in-the-loop run with responses={...} and no checkpoint_id.

Reproduction

from agent_framework import RunContext, step, workflow


@step
async def seed_state(ctx: RunContext) -> str:
    ctx.set_state("marker", "ok")
    return "seeded"


@workflow
async def stateful_review(data: str, ctx: RunContext) -> str:
    value = await seed_state()
    answer = await ctx.request_info("question", response_type=str, request_id="r1")
    return f"{ctx.get_state('marker', 'MISSING')}:{value}:{answer}"


caller = stateful_review.build()
first = await caller.run("input")
resumed = await caller.run(responses={"r1": "ok"})

On current main, the resumed output is:

MISSING:seeded:ok

The seed_state step is replayed from its cache, so its body is not executed during the response-only resume. The new RunContext therefore has an empty _state.

Expected behavior

The response-only resume should restore the user state captured when the workflow suspended and return:

ok:seeded:ok

The same workflow already preserves the state when resumed with a checkpoint_id, which demonstrates that state persistence is intended for HITL resumes.

Impact

This can silently change workflow decisions and outputs in normal multi-turn HITL flows whenever a completed cached step initialized or updated workflow state before requesting input. The workflow appears to resume successfully, but state-dependent logic observes missing values.

Related context

The review discussion on the original functional workflow implementation in #4238 identified that response-only resumes restore cached step outputs but not workflow state. This issue tracks the unresolved follow-up. It is distinct from #8292, which concerns cached-result swaps between concurrent calls to the same @step.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Sep 11, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Sep 11, 2026
  3. github-actions commented on Sep 11, 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::FunctionalWorkflow._run_core around lines 980-1017 when a response-only HITL resume replays a cached step that previously mutated user state. Minimal repro: set state inside an @step, suspend later with request_info, then resume using only responses={"r1": "ok"} and observe that the cached step is bypassed while ctx.get_state returns the default.

    • Failing test: python/packages/core/tests/workflow/test_functional_workflow.py
    • 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: TestStateManagement, TestHITLInStepWithCaching::test_preceding_step_bypassed_on_hitl_resume, TestHITLInStepWithCaching::test_response_only_resume_preserves_state_set_by_cached_step
    • Current version: 1.18.0
  4. added
    workflowsUsage: [Issues, PRs], Target: Workflows
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Sep 11, 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