Deep Research (also known as Agentic Deep Research) refers to an intelligent research agent where large language models (LLMs) collaborate with tools (such as search, browser, code execution, memory storage, etc.) to complete complex tasks through a closed-loop process of "multi-turn reasoning → retrieval → verification → integration."
Unlike single retrieval RAG (Retrieval-Augmented Generation), Deep Research resembles the thought process of a human expert — first making a plan, then continuously exploring, adjusting direction, verifying information, and finally producing a well-structured report with sources.
In this development example, we will build a demonstration based on the UltraRAG framework. Considering that most users may not have access to powerful servers, we implement the entire process on a MacBook Air (M2), ensuring a lightweight and easy-to-reproduce environment.
# Create and activate Conda environment
conda create -n ultrarag python=3.11
conda activate ultrarag
# Clone the project and enter the directory
git clone https://github.com/OpenBMB/UltraRAG.git
cd UltraRAG
# Install dependencies using uv
pip install uv
uv pip install -e .- Retrieval API: We use Tavily Web Search, which provides 1000 free calls upon initial registration.
- LLM API: You can choose any large model service according to your preference. In this tutorial, we use gpt-5-nano as an example.
We offer two ways to pass API Keys: environment variables and explicit parameters. It is recommended to use environment variables for better security and to avoid API Key leakage in logs.
export LLM_API_KEY="your llm key"
export TAVILY_API_KEY="your retriever key"In this example, we will implement a lightweight Deep Research Pipeline with the following core functionalities:
- Plan formulation: The model first creates a solution plan based on the user's question;
- Sub-question generation and retrieval: The main question is broken down into retrievable sub-questions, and web search tools are used to gather related information;
- Report organization and filling: The research report content is progressively refined;
- Reasoning and final generation: After the report is completed, the model outputs the final answer.
The flowchart is shown below:
This pipeline mainly consists of two stages:
-
Initialization stage: The model generates a plan based on the user's question and constructs an initial report page accordingly.
-
Iterative filling stage:
- The system checks whether the current report page is complete.
- The criterion is whether the page still contains the string "to be filled."
- If the report is not yet complete, the model generates a new sub-question by combining the user's question, the plan, and the current page, and triggers a web search.
- Retrieved documents are used to update the page, then the next check is performed.
- This process iterates until the page is fully filled.
Finally, the model generates a complete answer based on the user's question and the final report page.
The code implementation of this example is very concise, mainly relying on custom extensions of the router and prompt tools. Interested users can directly check the source code.
UltraRAG development techniques involved include:
- Prompt Tool Development
- Branch Decision Tool Development
- Loop Structure Pipeline
- Branch Structure Pipeline
- Parameter Renaming Mechanism
Below is the complete pipeline definition (see examples/light_deepresearch.yaml):
# light deepresearch demo
# MCP Server
servers:
benchmark: servers/benchmark
generation: servers/generation
retriever: servers/retriever
prompt: servers/prompt
router: servers/router
# MCP Client Pipeline
pipeline:
- benchmark.get_data
# generate plan
- prompt.webnote_gen_plan
- generation.generate:
output:
ans_ls: plan_ls
# Initialize page
- prompt.webnote_init_page
- generation.generate:
output:
ans_ls: page_ls
# Iteratively generate sub-questions, retrieve information, and progressively fill the page
- loop:
times: 10
steps:
# Trigger Check: determine whether the page is complete
- branch:
router:
- router.webnote_check_page
branches:
# If the page is not complete, continue.
incomplete:
# generate sub question
- prompt.webnote_gen_subq
- generation.generate:
output:
ans_ls: subq_ls
# retrieve answer
- retriever.retriever_tavily_search:
input:
query_list: subq_ls
output:
ret_psg: psg_ls
# fill page
- prompt.webnote_fill_page
- generation.generate:
output:
ans_ls: page_ls
# If the page has been completed, stop.
complete: []
# generate answer
- prompt.webnote_gen_answer
- generation.generateFirst, create a file named sample_light_ds.jsonl in the data folder and write the question you want to research. For example:
{
"id": 0,
"question": "Introduce the continent of Teyvat",
"golden_answers": [],
"meta_data": {}
}Run the following command to generate the parameter file corresponding to the pipeline:
ultrarag build examples/light_deepresearch.yamlThis will generate light_deepresearch_parameter.yaml under examples/parameter/. Open this file and modify it according to your actual situation, for example:
benchmark:
benchmark:
key_map:
gt_ls: golden_answers
q_ls: question
limit: -1
name: ds
path: data/sample_light_ds.jsonl
seed: 42
shuffle: false
generation:
api_key: ''
base_url: your api url
model_name: gpt-5-nano
sampling_params:
max_tokens: 4096
temperature: 0.7
prompt:
webnote_fill_page_template: prompt/webnote_fill_page.jinja
webnote_gen_answer_template: prompt/webnote_gen_answer.jinja
webnote_gen_plan_template: prompt/webnote_gen_plan.jinja
webnote_gen_subq_template: prompt/webnote_gen_subq.jinja
webnote_init_page_template: prompt/webnote_init_page.jinja
retriever:
top_k: 5Before running, be sure to set your API Key. Although it can also be passed via parameters, it is recommended to use environment variables to avoid leaking keys into log files:
export LLM_API_KEY="your llm key"
export TAVILY_API_KEY="your retriever key"ultrarag run examples/light_deepresearch.yamlAfter running, you can visualize the generated content through the Case Study Viewer:
python ./script/case_study.py \
--data output/memory_ds_light_deepresearch_20250909_152727.json \
--host 127.0.0.1 \
--port 8070 \
--title "Case Study Viewer"This will open the result page in your browser, allowing you to intuitively analyze the pipeline execution process and generated content.

