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, raises QuestionValidationError.
  • 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 claude binary.

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.toml only). Run pip install -r requirements.txt (or uv pip compile) and commit the generated lockfile.
  • Medium – No least‑privilege GITHUB_TOKEN permissions in .github/workflows/ci.yml. Add permissions: contents: read.
  • Medium – No automated dependency updates. Add a dependabot.yml covering python and github-actions.
  • Medium – No vulnerability‑scan step in CI. Insert dependabot or dependency-review-action on PRs.
  • Medium – Checkout step keeps credentials (persist-credentials: false missing). Update the checkout action accordingly.
  • Medium – No job timeout defined; add timeout-minutes to avoid overlapping runs.
  • Low – Three stray TODO/FIXME markers in src/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.