Note before submitting: this is a direct reproduction and expansion of
Discussion #6464.
Prefer commenting there or asking a maintainer to convert it into an Issue,
rather than creating a duplicate Issue. If a new Issue is requested, use the
following content.
Describe the Bug
google-adk==2.5.0 regresses Workflow replay for an interruptible workflow
that contains an LlmAgent.
If an ADK session first completes an independent invocation and then starts a
second invocation that pauses on RequestInput, resuming the second invocation
can fail with:
RuntimeError: Replay divergence detected: Timed out waiting for sequence key
'prepare_intent_text@1' to be unblocked.
The failing key belongs to the already completed earlier invocation, not to
the currently resumed HITL invocation.
This makes normal same-session HITL usage unreliable. A session must support
multiple independent user requests, including a later request that requires
human input; requiring a new session for every HITL request is not a viable
application-level workaround.
Steps to Reproduce
- Install
google-adk==2.5.0 with its database/A2A dependencies and configure
a working LiteLLM OpenAI-compatible endpoint.
- Use
DatabaseSessionService backed by PostgreSQL and create one session.
- Run the minimal reproduction below with
"who are you"; let that first
invocation complete.
- Run the same Workflow again in the same session with
"weather please".
It emits a RequestInput event.
- Resume that exact pending function call with
"sample-location".
- Observe the following error after approximately 15 seconds:
RuntimeError: Replay divergence detected: Timed out waiting for sequence key
'prepare_intent_text@1' to be unblocked.
Expected Behavior
The second invocation should resume the pending clarify node and emit:
Previous completed invocations in the same session must not prevent a later
HITL invocation from resuming.
Observed Behavior
The resumed invocation fails rather than executing the pending HITL node. The
failure points to prepare_intent_text@1, which belongs to the earlier,
already-completed invocation, not the current HITL invocation.
RuntimeError: Replay divergence detected: Timed out waiting for sequence key
'prepare_intent_text@1' to be unblocked.
The exception originates from
google.adk.workflow.utils._replay_sequence_barrier.
Environment Details
ADK Library Version: 2.5.0
Desktop OS: macOS
Python Version: 3.12
Session storage: DatabaseSessionService (PostgreSQL / asyncpg)
Model Information
Using LiteLLM: Yes
Model: glm-5.2 through an OpenAI-compatible LiteLLM gateway
The issue is independent of the model response itself. The failure is raised
from google.adk.workflow.utils._replay_sequence_barrier after its 15-second
wait timeout.
Regression
google-adk==2.4.0: PASS
google-adk==2.5.0: FAIL
google-adk==2.5.0 with a fresh session that directly enters HITL: PASS
Minimal Reproduction Code
This graph deliberately has no graph cycle. clarify is
rerun_on_resume=True, and its interrupt ID includes ctx.run_id so it is
unique for the node execution.
from google.adk import Context, Event, Workflow
from google.adk.agents import LlmAgent
from google.adk.events import RequestInput
from google.adk.workflow import START, node
@node
async def prepare_intent_text(node_input: str, ctx: Context) -> Event:
return Event(output=node_input)
classifier = LlmAgent(
name="classifier",
model=model, # any working LiteLlm/OpenAI-compatible model
instruction="Output META for 'who are you'; otherwise output WEATHER.",
output_key="classification",
)
@node
async def route(node_input: str, ctx: Context) -> Event:
route_name = "META" if ctx.state.get("classification", "").strip() == "META" else "NEED_INPUT"
return Event(output=node_input, route=route_name)
@node
async def finish(node_input: str, ctx: Context) -> Event:
return Event(output="done", message="done")
@node(rerun_on_resume=True)
async def clarify(node_input: str, ctx: Context):
interrupt_id = f"clarify:{ctx.run_id}"
response = ctx.resume_inputs.get(interrupt_id)
if response is None:
yield RequestInput(interrupt_id=interrupt_id, message="Enter a city")
return
yield Event(output=f"resumed:{response}", message=f"resumed:{response}")
workflow = Workflow(
name="replay_llm_probe",
edges=[
(START, prepare_intent_text),
(prepare_intent_text, classifier),
(classifier, route),
(route, {"META": finish, "NEED_INPUT": clarify}),
],
)
Against one persistent session, execute:
- Send
"who are you"; allow the invocation to complete.
- Send
"weather please"; the workflow emits RequestInput.
- Resume the exact pending function call with
"sample-location".
Additional Context
The same result occurs after all of the following application-level changes:
Control experiments
| Test |
Result |
Same minimal graph, no LlmAgent (FunctionNodes only) |
PASS |
Add one real LlmAgent, then perform completed invocation -> HITL -> resume |
FAIL on 2.5.0 |
Same LlmAgent test with a fresh session that immediately enters HITL |
PASS |
Same LlmAgent test on google-adk==2.4.0 |
PASS |
This isolates the regression from the application's original loop topology,
the interrupt ID, and model-provider failure.
Suspected cause
The behavior matches cross-invocation contamination of Workflow replay state.
Node path keys such as prepare_intent_text@1 are reused in separate
invocations. If the replay sequence barrier scans terminal events from the
whole session instead of only the current invocation_id, it can wait for an
old key that is never advanced during the current resume.
This is consistent with the rehydration-index optimization introduced around
commit 64a7448fc6e05f37e6dedadd6c0e65bc19264057.
Requested fix
Please ensure all replay sequence construction and event indexing are scoped by
the current invocation ID (or key replay state by both invocation ID and node
path). Please add a regression test that:
- runs an
LlmAgent-containing Workflow to completion;
- starts another invocation of the same Workflow in the same persistent
session;
- pauses with
RequestInput and resumes it successfully.
Related reports
How often has this issue occurred?
Always (100%) for the minimal reproduction above.
Describe the Bug
google-adk==2.5.0regresses Workflow replay for an interruptible workflowthat contains an
LlmAgent.If an ADK session first completes an independent invocation and then starts a
second invocation that pauses on
RequestInput, resuming the second invocationcan fail with:
The failing key belongs to the already completed earlier invocation, not to
the currently resumed HITL invocation.
This makes normal same-session HITL usage unreliable. A session must support
multiple independent user requests, including a later request that requires
human input; requiring a new session for every HITL request is not a viable
application-level workaround.
Steps to Reproduce
google-adk==2.5.0with its database/A2A dependencies and configurea working LiteLLM OpenAI-compatible endpoint.
DatabaseSessionServicebacked by PostgreSQL and create one session."who are you"; let that firstinvocation complete.
"weather please".It emits a
RequestInputevent."sample-location".Expected Behavior
The second invocation should resume the pending
clarifynode and emit:Previous completed invocations in the same session must not prevent a later
HITL invocation from resuming.
Observed Behavior
The resumed invocation fails rather than executing the pending HITL node. The
failure points to
prepare_intent_text@1, which belongs to the earlier,already-completed invocation, not the current HITL invocation.
The exception originates from
google.adk.workflow.utils._replay_sequence_barrier.Environment Details
Model Information
The issue is independent of the model response itself. The failure is raised
from
google.adk.workflow.utils._replay_sequence_barrierafter its 15-secondwait timeout.
Regression
Minimal Reproduction Code
This graph deliberately has no graph cycle.
clarifyisrerun_on_resume=True, and its interrupt ID includesctx.run_idso it isunique for the node execution.
Against one persistent session, execute:
"who are you"; allow the invocation to complete."weather please"; the workflow emitsRequestInput."sample-location".Additional Context
The same result occurs after all of the following application-level changes:
clarify -> prepare_intent_textgraph back-edge;clarifytorerun_on_resume=True;ctx.run_id(the workaround discussed in RequestInput with constant interrupt_id breaks dev-ui input prompt on @node(rerun_on_resume=True) loops #5617);Control experiments
LlmAgent(FunctionNodes only)LlmAgent, then perform completed invocation -> HITL -> resumeLlmAgenttest with a fresh session that immediately enters HITLLlmAgenttest ongoogle-adk==2.4.0This isolates the regression from the application's original loop topology,
the interrupt ID, and model-provider failure.
Suspected cause
The behavior matches cross-invocation contamination of Workflow replay state.
Node path keys such as
prepare_intent_text@1are reused in separateinvocations. If the replay sequence barrier scans terminal events from the
whole session instead of only the current
invocation_id, it can wait for anold key that is never advanced during the current resume.
This is consistent with the rehydration-index optimization introduced around
commit
64a7448fc6e05f37e6dedadd6c0e65bc19264057.Requested fix
Please ensure all replay sequence construction and event indexing are scoped by
the current invocation ID (or key replay state by both invocation ID and node
path). Please add a regression test that:
LlmAgent-containing Workflow to completion;session;
RequestInputand resumes it successfully.Related reports
this reproduction uses a unique ID and still fails.
How often has this issue occurred?