Files
google--adk-python/contributing/workflow_samples/request_input_rerun
Wei (Jack) Sun 1c64a41b53 feat: ADK 2.0 alpha
Introduces two major capabilities:
- Workflow runtime: graph-based execution engine for composing
  deterministic execution flows for agentic apps, with support for
  routing, fan-out/fan-in, loops, retry, state management, dynamic
  nodes, human-in-the-loop, and nested workflows
- Task API: structured agent-to-agent delegation with multi-turn
  task mode, single-turn controlled output, mixed delegation
  patterns, human-in-the-loop, and task agents as workflow nodes

Co-Authored-By: Bo Yang <ybo@google.com>
Co-Authored-By: George Weale <gweale@google.com>
Co-Authored-By: Sean Zhou <seanzhougoogle@google.com>
Co-Authored-By: Shangjie Chen <deanchen@google.com>
Co-Authored-By: Swapnil Agarwal <swapnilag@google.com>
Co-Authored-By: Wei Sun <weisun@google.com>
Co-Authored-By: Xuan Yang <xygoogle@google.com>
Co-Authored-By: Yifan Wang <wanyif@google.com>
Change-Id: I35932c50cfe29ff68559e3781713dbb5eb7b3382
2026-03-17 23:24:58 -07:00
..
2026-03-17 23:24:58 -07:00
2026-03-17 23:24:58 -07:00

ADK Workflow Request Input Rerun Sample

Overview

This sample demonstrates an alternative way to handle a Human-in-the-Loop workflow in ADK Workflows using the RequestInput event combined with the @node(rerun_on_resume=True) decorator.

Like the standard request_input sample, this workflow simulates a customer support scenario where an AI drafts an email and a human reviews it. The key difference lies in how the human input is processed when the workflow resumes.

request_input vs request_input_rerun

  • Standard (request_input): The workflow pauses after a node yields RequestInput. When the user provides input and execution resumes, the input is automatically passed as the argument to the next node in the edge definition. This requires two separate nodes: one to request the input and one to handle it.
  • Rerun (request_input_rerun): The node yielding RequestInput is decorated with @node(rerun_on_resume=True). When execution resumes, the workflow re-runs the exact same node that asked for the input. The node can then access the provided input via the execution Context.

This allows you to combine the requesting and handling of human input into a single, cohesive node.

Sample Inputs

  • The delivery was a week late
  • I received the wrong item
  • My account was charged twice

Graph

       [ START ]
           |
           v
    [draft_email] <------------------+
           |                         |
           v                         |
    [human_review] -- (revise) ------+
    (reruns on resume)
        /    \
       /      \
      v        v
[send_email]  [END (rejected)]

How To

  1. Decorate the node that needs human input with @node(rerun_on_resume=True). Ensure the function signature includes the workflow Context.

    from google.adk.workflow import node
    from google.adk import Context
    
    @node(rerun_on_resume=True)
    def human_review(draft: str, ctx: Context):
        # ...
    
  2. Inside the node, check if you are being resumed by looking for the interrupt_id in ctx.resume_inputs.

    resume_input = ctx.resume_inputs.get('human_review')
    
  3. If resume_input is missing (i.e., this is the first time the node is executing), yield the RequestInput event to pause the workflow. Include an explicit interrupt_id.

    if not resume_input:
        yield RequestInput(
            interrupt_id="human_review",
            message="Please review the draft...",
        )
        return # Important: Stop execution of this node for now
    
  4. If resume_input is present (i.e., the workflow was resumed with user input), process the input and yield the appropriate routing events.

    if resume_input == "reject":
        yield Event(route="rejected")
    elif resume_input == "approve":
        yield Event(route="approved")
    else:
        yield Event(state={"feedback": resume_input}, route="revise")
    
  5. The edge definition is much simpler because the single human_review node handles everything:

    Workflow(
        name="request_input",
        edges=[
            ("START", process_input, draft_email, human_review),
            (human_review, {"revise": draft_email, "approved": send_email}),
        ],
    )