This repository contains a simplified implementation of a deep research agent built via LangGraph. It is able to take in user queries, clarify scope, and search the web for information to synthesize into a comprehensive report.
The Simple Deep Research agent is built on the core principles of deep agents like Claude Code, Codex, and Cursor while integrating the user experience of popular deep research implementations like ChatGPT's. The system is composed of three LangGraph graphs arranged in a nested architecture:
Main Graph - Top-level entry point handling the clarification loop:
- Clarify - Asks the user clarifying questions via
interrupt, resumes when answered - Orchestrate - Once clarification is complete, hands off to the orchestrator subgraph
Orchestrator Graph - ReACT-style subgraph for delegating research agents and writing the final report:
- Plan - Uses a todo list tool to outline research steps
- Delegate - Kicks off research sub-agents in parallel via tool calls
- Synthesize - Combines sub-agent findings into a final cited report
Research Graph - ReAct-style sub-graph for web research:
- Decides what to search, calls Tavily web search
- Filters results by relevance, iterates until sufficient
- Returns a cited intermediate report to the orchestrator
These work together to create a well cited and structured report in markdown format, an example output can be viewed here
- Clone the repository:
git clone https://github.com/ALucek/simple-deep-research
cd simple-deep-research- Install dependencies:
uv sync- Create a .env file with the following variables:
OPENAI_API_KEY=
TAVILY_API_KEY=
LANGSMITH_API_KEY=
LANGSMITH_TRACING=true
LANGSMITH_ENDPOINT=https://api.smith.langchain.com
LANGSMITH_PROJECT="simple-deep-research"The Simple Deep Research agent connects to the web via Tavily. Tavily generously provides 1,000 free API credits per month, usage and API keys can be created in the overview page.
LangSmith is used for tracing and the Studio IDE. This implementation integrates directly with LangSmith, it is recommended to interact and view the agent graphs via LangSmith Studio.
The Simple Deep Research graphs can be used directly for custom integrations. When using directly, it is important to respect checkpointing and thread handling as we rely on interrupts for human-in-the-loop clarification of research scope.
A simplified example of how this can be implemented is provided in examples/run_agent.py. Run via
uv run examples/run_agent.py
The orchestrator and researcher subgraph can also be used independently. For example with the orchestrator:
import asyncio
import uuid
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
from src.graphs.orchestrator_graph import builder as orchestrator_builder
graph = orchestrator_builder.compile(checkpointer=InMemorySaver()).with_config(
recursion_limit=1000
)
config = {"configurable": {"thread_id": str(uuid.uuid4())}}
result = asyncio.run(
graph.ainvoke(
{
"messages": [
HumanMessage(
content=(
"Research current trends in edge AI for industrial robotics."
)
)
]
},
config,
)
)
print(result["messages"][-1].content)And with the research sub-agent:
import asyncio
import uuid
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
from src.graphs.research_graph import builder as research_builder
graph = research_builder.compile(checkpointer=InMemorySaver()).with_config(
recursion_limit=1000
)
config = {"configurable": {"thread_id": str(uuid.uuid4())}}
result = asyncio.run(
graph.ainvoke(
{
"messages": [
HumanMessage(
content="Research top trends in edge AI."
)
]
},
config,
)
)
print(result["messages"][-1].content)Model and search settings are passed through LangGraph's configurable dict. Each role (orchestrator, clarifier, researcher) inherits from a shared default and can be overridden individually. Any valid ChatOpenAI parameter can be passed.
{
"configurable": {
"thread_id": "...",
"default": {
"model": "gpt-5.2-2025-12-11",
"temperature": 1
},
"orchestrator": {},
"clarifier": {},
"researcher": {},
"max_searches": 30
}
}default— Base settings applied to all roles. Must include at least amodel. Accepts any valid ChatOpenAI parameter (model,temperature,max_tokens,top_p,base_url, etc.).orchestrator— Overrides for the orchestration agent that plans and synthesizes the report.clarifier— Overrides for the clarification agent that scopes the research query.researcher— Overrides for the research sub-agents that perform web searches.max_searches— Hard limit on web searches per research sub-agent run.
Per-role configs are optional and accept the same kwargs as default. Only set fields override the default; omitted fields inherit from default.
config = {
"configurable": {
"thread_id": str(uuid.uuid4()),
"default": {
"model": "gpt-5.2-2025-12-11",
"temperature": 1,
},
"orchestrator": {
"model": "gpt-5.2-pro-2025-12-11",
},
"researcher": {
"model": "gpt-4.1-mini",
"temperature": 0.7,
"max_tokens": 1000,
},
"max_searches": 50,
}
}To initiate the Simple Deep Research agent in LangSmith Studio, launch the local langgraph server via the command:
uv run langgraph dev
This will automatically open a window in your browser to the studio IDE. Within the IDE there are three graphs viewable:
The top-level graph handling clarification and delegating to the orchestrator subgraph
The orchestrator loop (plan, delegate, synthesize) mounted as a node in the main graph
The research sub-agent responsible for searching the web
The graphs can then be interacted with directly in the interface!



