HITL Deep Research
Research pipeline with a human-in-the-loop approval gate before research begins
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_agentthat 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_agentthat gathers findings per subtopic using Wikipedia search and webpage fetching - A
writing_agentthat 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 | bashSetup
Scaffold the project
agnt5 create —template python/hitl_deep_research my-deep-research
cd my-deep-researchagnt5 create —template typescript/hitl_deep_research my-deep-research
cd my-deep-researchSet environment variables
cat > .env << EOF
OPENAI_API_KEY=your_openai_api_key_here
EOFInstall dependencies
uv syncpip install -e .npm installStart the AGNT5 dev server
agnt5 devWhen 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.
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 wrappersapp.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 wrappersCustomize
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
- Read /docs/build/human-in-the-loop for
wait_for_user()semantics and input types - See code_reviewer for another multi-agent, multi-step workflow
- Browse /docs/build/workflows for durable step and replay semantics