The Problem
Teams that need deep, multi‑turn analysis of a single question often build ad‑hoc scripts that spawn many LLM calls, track intermediate results, and then synthesize a final answer. Maintaining that logic, handling parallelism, and preventing runaway costs quickly becomes a maintenance burden.
What This Does
deep-research implements a recursive “research tree” where a top‑level question is decomposed into sub‑questions, each handled by its own LLM agent. The process repeats until leaf questions are atomic, after which a synthesis step produces a single answer. Core logic lives in src/deep_research/cli.py (the user‑facing CLI) and the orchestration classes under src/deep_research/core/ – notably operation.py, chef.py, graph.py, and the operations/ package (e.g., answer.py, decompose.py). Provider adapters for Claude, Gemini, OpenAI‑Azure, OpenRouter, and Kimi are in src/deep_research/providers/.
How It Is Wired
Execution starts at the research command defined in src/deep_research/cli.py (line 122). This parses CLI flags, builds a Chef instance, and calls Chef.run(). Chef.run() invokes Operation.execute() (via src/deep_research/core/operation.py line 106) which routes to the appropriate operation class (Decompose, Detect, Answer, etc.) based on the current phase.
The most‑used internal functions are:
parse– called from 31 locations, builds question objects.validate_question– called from 17 locations, raisesQuestionValidationError.generate– called from 12 locations, triggers the provider’s LLM call.
A typical run follows this path:
research (cli) → Chef.run → Operation.execute → parse → generate
→ ProviderFactory.get_provider_for_model → Provider.generate (e.g., providers/claude.py)
→ filesystem writes (self.output_dir.mkdir, _write_output_file)
→ recursion back up via OperationResult handling
The call graph shows 558 internal edges; the hub modules are src/deep_research/core/operations/base.py (7 inbound, 9 outbound, part of a circular import) and src/deep_research/cli.py (8 outbound, no inbound). Circular imports involve base.py, answer.py, and decompose.py, increasing the risk of import‑time side effects.
External effects are limited to:
- Filesystem I/O (creation of output directories, checkpoint files, cache files).
- One LLM invocation per leaf node (
self.client.chat.completions.create). - A single external subprocess when the default Claude provider shells out to the
claudebinary.
No database or network services beyond the LLM endpoints are touched.
How To Use It
# Clone the upstream repository
git clone https://github.com/moses-y/deep-research
cd deep-research
# Install in editable mode with dev extras (includes pytest)
pip install -e ".[dev]"
# Set up a provider (example for Claude CLI, already on PATH)
# No env vars needed for the default haiku model
# For Gemini or OpenAI‑Azure, create a .env as described in README
# Run a shallow test to avoid cost explosion
deep-research research -d 1 -m haiku "Why do smart people make bad decisions?"
The CLI also offers validate (question validation) and cache (cache management) sub‑commands, each mapped to functions in src/deep_research/cli.py.
Real‑World Use
A product team could embed deep-research in a nightly analysis pipeline: feed each new market hypothesis to deep-research research -d 2, store the generated synthesis in a markdown report, and commit the file to the repository. The pipeline would only need to configure the appropriate provider API key and run the CLI as a subprocess.
Code Health & Issues
- High – Import cycles across
src/deep_research/core/operations/base.py,answer.py,decompose.py. Break cycles by extracting shared types or using lazy imports. - High – Missing lockfile (
pyproject.tomlonly). Runpip install -r requirements.txt(oruv pip compile) and commit the generated lockfile. - Medium – No least‑privilege
GITHUB_TOKENpermissions in.github/workflows/ci.yml. Addpermissions: contents: read. - Medium – No automated dependency updates. Add a
dependabot.ymlcoveringpythonandgithub-actions. - Medium – No vulnerability‑scan step in CI. Insert
dependabotordependency-review-actionon PRs. - Medium – Checkout step keeps credentials (
persist-credentials: falsemissing). Update the checkout action accordingly. - Medium – No job timeout defined; add
timeout-minutesto avoid overlapping runs. - Low – Three stray
TODO/FIXMEmarkers insrc/deep_research/core/chef.py. Resolve or file issues.
The Bottom Line
deep-research delivers a functional recursive‑agent framework with a clear CLI and provider abstraction, but its codebase suffers from import cycles, duplicated scripts, and missing production safeguards (lockfile, CI hardening). It is suitable for experimentation or internal tooling where the team can address the highlighted health issues; production deployments should first resolve the high‑severity import cycles and add reproducible dependency management.