Skip to content

HITL Deep Research

Research pipeline with a human-in-the-loop approval gate before research begins

Get Code

The HITL deep-research template runs a three-agent research pipeline with a durable human-approval gate between planning and execution. A scoping agent proposes a research plan, the workflow pauses and waits for you to approve, edit, or reject it in Studio, and only then do the research and writing agents run.

What you’ll build

  • A scoping_agent that turns a topic into a structured research plan with 3–6 subtopics
  • A durable pause with ctx.wait_for_user() that presents the plan and waits for approve / edit / reject
  • A research_agent that gathers findings per subtopic using Wikipedia search and webpage fetching
  • A writing_agent that synthesizes the findings into a cited Markdown report

Requirements

  • Python 3.12+ or Node.js 22+
  • OPENAI_API_KEY
  • The AGNT5 CLI
  • No search API key - research runs against Wikipedia and public webpages directly

Install

curl -LsSf https://agnt5.com/cli.sh | bash

Setup

Scaffold the project

agnt5 create —template python/hitl_deep_research my-deep-research
cd my-deep-research
agnt5 create —template typescript/hitl_deep_research my-deep-research
cd my-deep-research

Set environment variables

cat > .env << EOF
OPENAI_API_KEY=your_openai_api_key_here
EOF

Install dependencies

uv sync
pip install -e .
npm install

Start the AGNT5 dev server

agnt5 dev

When the workflow reaches the approval step, open the Dev Dashboard to review and approve the research plan before research begins.

How it works

The workflow runs four stages. First, a planning step runs the scoping agent to produce a structured plan. Second, the workflow pauses and waits for a human decision - approve, edit, or reject - presenting the plan and the options. This pause suspends the workflow entirely; it is not held in process memory while waiting, and can resume on a different worker host whenever a human responds, even after a restart. A reject ends the run early; an edit collects free text and substitutes it for the plan. Third, once approved, a research step runs the research agent, which uses Wikipedia search and webpage fetching to gather findings per subtopic. Fourth, a writing step runs the writing agent to synthesize everything into a cited Markdown report.

Because the pause is a checkpointed call like any other step, the workflow body can safely re-run top-to-bottom on resume - the recorded answer is returned immediately instead of re-prompting. Log statements before the pause are guarded to fire only on the first pass, but the pause call itself always stays unconditional.

Tip:

This is the pattern to copy for any workflow that needs a checkpoint gate before an expensive or irreversible step - approvals, spend limits, content moderation. The pause is just another durable step, not special infrastructure.

Key files

app.py                          - Worker entry point
src/deep_research/workflows.py  - deep_research_workflow: plan, approve (HITL), research, write
src/deep_research/agents.py     - scoping_agent, research_agent, writing_agent
src/deep_research/tools.py      - wikipedia_search_tool, fetch_webpage_tool
src/deep_research/functions.py  - _plan_research, _conduct_research, _write_report step wrappers
app.ts            - Worker entry point
src/workflows.ts  - deepResearchWorkflow: plan, approve (HITL), research, write
src/agents.ts      - getScopingAgent(), getResearchAgent(), getWritingAgent()
src/tools.ts       - wikipediaSearch, fetchWebpage
src/functions.ts   - planResearch, conductResearch, writeReport step wrappers

Customize

Add a real search API. tools.py only has Wikipedia and raw webpage fetching today - add a web_search_tool backed by Tavily, Exa, or Brave and give it to research_agent alongside the existing tools.

Change the approval UX. The input_type passed to wait_for_user() can be "text", "approval", "select", or "multiselect" - swap "select" for a simpler "approval" gate if you don’t need the edit path.

Change the report format. writing_agent’s instructions in agents.py define the Markdown report structure - point them at a different structure or ask for JSON output for downstream processing.

Next steps