Model or dataset
dzhng/deep-research avatar
dzhng/deep-research

dzhng/deep-research: A Recursive Research Agent Kept Under 500 Lines

An AI-powered research assistant that performs iterative, deep research on any topic by combining search engines, web scraping, and large language models. The goal of this repo is to provide the simplest implementation of a deep research agent - e.g. an agent that can refine its research direction overtime and deep dive into a topic.

19,677 stars1,999 forksTypeScriptMIT

At a glance

What is it?
A TypeScript deep research agent that loops search queries, scrapes pages, and asks a model to extract learnings and new directions. The README states the goal is the simplest implementation of this pattern, and the design choices follow from that constraint.
Who is it for?
Adopt dzhng/deep-research if you want a readable reference for the recursive search loop and you already hold Firecrawl and OpenAI keys, or if you plan to point it at a local OpenAI-compatible endpoint. Do not adopt it if you need a hosted service, a stable CLI contract, or a system that runs without a scraping vendor.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 157 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap this fills: a research loop you can read in one sitting

Search APIs return links. A model summarizing those links returns a single pass. Neither refines its own question. dzhng/deep-research targets the loop between those two: generate queries, scrape results, ask a model what was learned and what to ask next, then repeat. The README frames the audience directly by stating the goal is to keep the repository under 500 lines of code so it is easy to understand and build on top of. That is the design brief, and it explains why the project has no plugin system, no queue, no database, and no server component. The intended user is an engineer who wants to see the whole agent, modify the prompts, and swap providers without reading a framework. If you want a product, this is the wrong shape. If you want a working skeleton of iterative research, the size constraint is the feature.

The recursion: SERP queries, learnings, directions, depth counter

The flowchart in the README shows the data flow plainly. A user query plus a breadth parameter and a depth parameter enter the Deep Research step. That step produces SERP queries, which are executed and then processed. Processing yields two separate outputs: learnings and directions. A decision node checks whether depth is greater than zero. If yes, the next direction is assembled from prior goals, new questions and accumulated learnings, and that bundle is fed back into Deep Research as new context. If no, the loop exits and the system emits a markdown report. Two details matter here. First, learnings and directions are distinct artifacts, so the model is asked both to compress what it read and to propose where to look next. Second, breadth and depth are separate knobs: breadth controls how many queries go out per round, depth controls how many rounds happen. The README recommends breadth 3 to 10 with a default of 4, and depth 1 to 5 with a default of 2. Those defaults are modest, which suggests the author expects cost and latency to bite before quality does.

Setup: two keys, a .env.local file, and the Fireworks switch

The README gives a Node.js path and a Docker path. For Node: clone the repository, run npm install, then create a .env.local file containing FIRECRAWL_KEY and OPENAI_KEY. Firecrawl handles both search and content extraction, so there is no separate search provider to configure. For a self-hosted Firecrawl instance, the README shows an optional FIRECRAWL_BASE_URL pointing at http://localhost:3002. To run against a local model instead of OpenAI, you comment out OPENAI_KEY and uncomment OPENAI_ENDPOINT (for example http://localhost:1234/v1) and OPENAI_MODEL. Two further optional variables exist for OpenAI-compatible providers: OPENAI_ENDPOINT and CUSTOM_MODEL. There is also a provider switch that is easy to miss: setting FIREWORKS_KEY makes the system automatically use DeepSeek R1 instead of o3-mini. The Docker route renames .env.example to .env.local, builds with docker build -f Dockerfile, starts with docker compose up -d, and runs the agent inside the container with docker exec -it deep-research npm run docker. The interactive run itself is npm start, which prompts for the query, breadth, depth, and follow-up questions, and writes report.md or answer.md into the working directory depending on the mode selected.

Concurrency is the first thing that will break

The README is explicit that CONCURRENCY_LIMIT controls how many searches and result-processing jobs run at once, and that raising it is only sensible on a paid Firecrawl plan or a self-hosted instance. On the free tier it warns that rate limit errors appear, and the documented remedy is to drop the limit to 1, which the README itself describes as running a lot slower. This is the honest failure mode of the project. The agent's value comes from fanning out across many queries per round, so the moment the scraping vendor throttles you, the recursion either stalls or degrades into serial requests. There is no built-in retry policy described, no backoff configuration, and no partial-result handling mentioned. A second constraint follows from the architecture: every round passes prior goals, new questions and learnings back into the model as context, so token usage grows with depth even when breadth stays fixed. The README gives no cost estimate and no token accounting, so the only way to know what a depth-5 run costs is to run it.

What it is not: no releases, no CLI contract, no library surface

The repository has no published releases and no homepage, and the README documents a single interactive entry point rather than a programmatic API. Nothing in the material describes importing the agent as a module, exposing a function, or returning structured output to a caller. The output is a markdown file on disk. That makes it a poor fit for pipelines that need typed results, and a poor fit for anyone who wants to pin a version: with no tags, you track the main branch. The licence is MIT, which is permissive and imposes no obligations beyond retaining the notice, but the README does not discuss the terms of the services it depends on. Firecrawl and OpenAI each carry their own terms and billing, and self-hosting Firecrawl moves that cost onto your own infrastructure. None of this is a defect in a reference implementation. It is a defect if you were hoping to drop it into production unchanged.

Where it sits next to a general-purpose agent framework

The obvious comparison is to a general agent framework such as LangChain or LangGraph, where you would assemble a research loop from a retriever, a tool-calling agent and a state graph. The difference is not capability but where the structure lives. In a framework, the loop is something you configure and the framework supplies the abstractions, tracing and integrations. In dzhng/deep-research, the loop is the codebase: the flowchart in the README is close to a description of the program, and the sub-500-line target means there is no abstraction layer between you and the prompts. That is a real advantage when the loop itself is what you are trying to understand or modify, and a real disadvantage when you need retries, observability or multi-tenant isolation, because you will write those yourself. The README also links a Python port, deep-research-python, for teams whose stack is not Node, which is worth noting since the two implementations are not described as sharing a test suite or a compatibility guarantee.

Editorial conclusion

Adopt dzhng/deep-research if you want a readable reference for the recursive search loop and you already hold Firecrawl and OpenAI keys, or if you plan to point it at a local OpenAI-compatible endpoint. Do not adopt it if you need a hosted service, a stable CLI contract, or a system that runs without a scraping vendor. Before you commit, verify the current Firecrawl rate limits against your plan, confirm which model the run will actually use after the FIREWORKS_KEY switch, and check whether the CONCURRENCY_LIMIT default survives your first run.

Official sources

  1. dzhng/deep-research on GitHub
  2. Issues
  3. License: MIT
  4. README
Community notes

Community notes