> ## Documentation Index
> Fetch the complete documentation index at: https://phidatainc-redirect-agent-platform-overview.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Loop HITL

> Confirm before starting loops and review output between iterations.

Loops support two HITL modes: start confirmation (pause before the first iteration) and iteration review (pause between iterations for human feedback).

All HITL settings are configured via [`HumanReview`](/workflows/hitl/human-review).

## Start Confirmation

When `requires_confirmation=True`, the loop pauses before executing:

* **Confirm**: Execute the loop iterations
* **Reject**: Skip the entire loop

```python theme={null}
from agno.workflow import Workflow
from agno.workflow.loop import Loop
from agno.workflow.step import Step
from agno.workflow.types import HumanReview, StepInput, StepOutput
from agno.db.sqlite import SqliteDb

def refine_analysis(step_input: StepInput) -> StepOutput:
    return StepOutput(content="Iteration complete: Quality improved")

workflow = Workflow(
    name="refinement_workflow",
    db=SqliteDb(db_file="workflow.db"),
    steps=[
        Step(name="prepare", executor=prepare_data),
        Loop(
            name="refinement_loop",
            steps=[Step(name="refine", executor=refine_analysis)],
            max_iterations=5,
            human_review=HumanReview(
                requires_confirmation=True,
                confirmation_message="Start refinement loop? (up to 5 iterations)",
            ),
        ),
        Step(name="finalize", executor=finalize_results),
    ],
)

run_output = workflow.run("Process data")

if run_output.is_paused:
    for req in run_output.steps_requiring_confirmation:
        print(f"Loop: {req.step_name}")
        print(f"Message: {req.confirmation_message}")
        
        if input("Start loop? (y/n): ").lower() == "y":
            req.confirm()
            print("Starting loop")
        else:
            req.reject()
            print("Skipping loop")
    
    run_output = workflow.continue_run(run_output)

print(run_output.content)
```

### Parameters

| Field                   | Type       | Description                                      |
| ----------------------- | ---------- | ------------------------------------------------ |
| `requires_confirmation` | `bool`     | Pause before first iteration                     |
| `confirmation_message`  | `str`      | Message shown to the user                        |
| `on_reject`             | `OnReject` | Action when rejected: `skip` (default), `cancel` |

### Loop Behavior

The confirmation happens once before the loop starts. Individual iterations do not pause for confirmation. For per-iteration pauses, see [Iteration Review](#iteration-review).

| User Action | Result                                                                                     |
| ----------- | ------------------------------------------------------------------------------------------ |
| Confirm     | Execute all iterations (up to `max_iterations` or until `should_continue` returns `False`) |
| Reject      | Skip the loop entirely                                                                     |

## Iteration Review

Set `requires_iteration_review=True` to pause between loop iterations. After each iteration completes, the workflow pauses for human review. The reviewer can accept the result (stopping the loop) or reject to run another iteration.

```python theme={null}
from agno.workflow import Workflow, OnReject
from agno.workflow.loop import Loop
from agno.workflow.step import Step
from agno.workflow.types import HumanReview
from agno.db.sqlite import SqliteDb

refine_agent = Agent(
    name="Refiner",
    model=OpenAIResponses(id="gpt-5.4"),
    instructions=(
        "You refine and improve text. If the reviewer provides feedback, "
        "incorporate it. Return only the improved text."
    ),
)

workflow = Workflow(
    name="iterative_refinement",
    db=SqliteDb(db_file="workflow.db"),
    steps=[
        Loop(
            name="refinement_loop",
            steps=[Step(name="refine", agent=refine_agent)],
            max_iterations=5,
            forward_iteration_output=True,
            human_review=HumanReview(
                requires_iteration_review=True,
                iteration_review_message="Review this iteration.",
                on_reject=OnReject.retry,
            ),
        ),
    ],
)

run_output = workflow.run("Improve this paragraph...")

while run_output.is_paused:
    for req in run_output.steps_requiring_output_review:
        print(req.step_output.content)

        choice = input("Accept? (yes/no): ").strip().lower()
        if choice in ("yes", "y"):
            req.confirm()
        else:
            feedback = input("Feedback: ").strip()
            if feedback:
                req.reject(feedback=feedback)
            else:
                req.reject()

    run_output = workflow.continue_run(run_output)
```

### Iteration Review Parameters

| Parameter                   | Type       | Default         | Description                                                        |
| --------------------------- | ---------- | --------------- | ------------------------------------------------------------------ |
| `requires_iteration_review` | `bool`     | `False`         | Pause after each iteration for review                              |
| `iteration_review_message`  | `str`      | `None`          | Message shown to the reviewer                                      |
| `on_reject`                 | `OnReject` | `OnReject.skip` | Action on rejection. Use `OnReject.retry` to run another iteration |

### Iteration Review Behavior

| Reviewer Action          | Result                                                  |
| ------------------------ | ------------------------------------------------------- |
| `confirm()`              | Stop the loop. Keep the current iteration's output      |
| `reject()`               | Run another iteration (when `on_reject=OnReject.retry`) |
| `reject(feedback="...")` | Run another iteration with feedback passed to the agent |

Iteration review requirements appear in `run_output.steps_requiring_output_review`, the same property used for step output review.

<Note>
  `requires_iteration_review` is only supported on Loop. Passing it to Step or Router raises a `ValueError`.
</Note>

## With should\_continue

The `should_continue` function controls iteration. Confirmation happens before any iteration:

```python theme={null}
def check_quality(step_input: StepInput, iteration: int) -> bool:
    return iteration < 3

Loop(
    name="quality_loop",
    steps=[Step(name="improve", executor=improve_quality)],
    should_continue=check_quality,
    human_review=HumanReview(
        requires_confirmation=True,
        confirmation_message="Start quality improvement loop?",
    ),
)
```

## Timeout

Set a deadline for user responses during loop HITL pauses. See the dedicated [Timeout](/workflows/hitl/timeout) page for full details.

```python theme={null}
from agno.workflow import OnTimeout

Loop(
    name="review_loop",
    steps=[Step(name="generate", executor=generate_fn)],
    max_iterations=3,
    human_review=HumanReview(
        requires_iteration_review=True,
        iteration_review_message="Review this iteration.",
        on_reject=OnReject.retry,
        timeout=120,  # 2 minutes per pause
        on_timeout=OnTimeout.approve,
    ),
)
```

## Streaming

Handle loop HITL in streaming workflows:

```python theme={null}
from agno.run.workflow import StepPausedEvent

for event in workflow.run("input", stream=True, stream_events=True):
    if isinstance(event, StepPausedEvent):
        print(f"Paused at: {event.step_name}")

session = workflow.get_session()
run_output = session.runs[-1]

while run_output.is_paused:
    for req in run_output.steps_requiring_confirmation:
        req.confirm()
    
    for event in workflow.continue_run(run_output, stream=True, stream_events=True):
        pass
    
    session = workflow.get_session()
    run_output = session.runs[-1]
```

## Developer Resources

* [HumanReview Config](/workflows/hitl/human-review)
* [Output Review](/workflows/hitl/output-review)
* [Workflow HITL overview](/workflows/hitl/overview)
* [Loop reference](/reference/workflows/loop-steps)
* [Iterative workflow pattern](/workflows/workflow-patterns/iterative-workflow)
