Eleven Deep Research Tools That Live Inside Your Coding Agent, and the One I Forked
The first time I ran my research agent on a real topic, it ran for over an hour and I had no idea whether it was working or hung. Nothing between “started” and whatever it was eventually going to print. So I sat there watching a spinner.
It was not almost done, because it had no definition of done.
That agent was a fork of somebody else’s project, and before I spent another weekend modifying it to my needs I wanted to know whether I should just use one of the tools that already existed. So I took a deep look at the other tools. Eleven tools that run inside a coding agent, or that an agent can drive.
I put the breakdown in my own repo as ALTERNATIVES.md.
This post is that page with the story attached.
- One Way to Rank These
- The Eleven
- The One I Forked
- It Would Not Install the Way I Wanted
- The Agent With No Tool Allowlist
- No Budget, No Stop Condition, No Way to Tell Working From Stuck
- The Part I Really Liked: Search Modules
- Building a Module by Discovering Its Sources Instead of Guessing Them
- Installing It Does Not Give You a Tool, It Starts a Research Project
- Everything Else That Got Bolted On
- What It Is Bad At
- Using It
- What I Actually Took Away From This
One Way to Rank These
One instinct with research tools is to rank them by depth. Which one goes deepest. Which one reads the most sources. Which one runs the longest.
Depth is a dial that almost all of them have, so depth is not something to compare here.
The two properties that actually decide which tool you want are shape and persistence.
Answer shape. A run produces one of four things. A narrative document, which is chapters and prose and citations. A matrix, which is N subjects by M attributes, also known as a comparison table. An annotated source list, which is findings with provenance where you do the synthesis. Or a knowledge base, which is a corpus that grows with new research instead of a single deliverable that ships.

Persistence. A run is either ephemeral, where the findings exist once and the next run starts cold, or accumulating, where there is a store that gets consulted before anything gets fetched. An accumulating tool used twenty minutes a week beats an ephemeral one used eight hours once, if the topic is something you keep coming back to. Which, if you’re researching your own industry, it is.
Two smaller axes worth checking before you commit:
Source routing. Does it search the open web generically, or does it know where the answers for a given kind of question actually live? Generic width does badly on any topic where vendor marketing and programmatic SEO own the first hundred results. Try researching LLM pricing with a generic web sweep sometime and count how many of the top results are listicles written by other AI.
Provider lock. Is it welded to one model vendor, or can it run on whatever you have, up to and including a local model?
The Eleven
Everything below runs inside a coding agent or is something an agent can drive. Skills, MCP servers, CLIs, libraries. I deliberately left out the hosted deep research products, the ChatGPT and Gemini and Perplexity tier, because their output lives in somebody else’s UI. The entire reason to run research from an agent is that the findings land in your own files.
Stars and last-push months here were verified against the GitHub API on 2026-10-10. Everything else in this section is taken from each project’s own documentation. I haven’t independently reproduced anybody’s benchmark placement or run time.
| Tool | Form | Answer shape | Persistence | Stars | Last push |
|---|---|---|---|---|---|
| local-deep-research | MCP + lib + CLI | Narrative report | Encrypted SQLite history + your own docs | 9.2k | 2026-10 |
| hyperresearch | Claude Code skill + MCP + CLI | Narrative, chaptered | Markdown vault + SQLite index | 3.8k | 2026-10 |
| gpt-researcher | Python lib (+ MCP) | Narrative report | None | 30k | 2026-10 |
| last30days-skill | Claude Code skill | Ranked brief | SQLite archive of past briefs | 63.9k | 2026-10 |
| paper-qa | Python lib + CLI | Cited answer | Reusable index under ~/.pqa/ | 9.3k | 2026-09 |
| local-deep-researcher | LangGraph app | Summary + sources | None | 9.4k | 2026-09 |
| deep-searcher | Python lib + CLI | Narrative report | Milvus vector DB | 8.3k | 2026-09 |
| DeepGit | MCP + CLI + lib | Ranked matrix | LanceDB vector index | 919 | 2026-08 |
| hoolulu/deep-research | Cross-platform skill | Narrative, chaptered | Folder of dated reports | 598 | 2026-08 |
| reddit-research-mcp | MCP server | Cited findings | Saved feeds | 254 | 2026-09 |
| RivalSearchMCP | MCP server | Structured JSON | None | 132 | 2026-10 |
The Report Writers

local-deep-research is the most complete package in the table. Per-domain engines for arXiv, PubMed, Semantic Scholar, NASA ADS, GitHub, SearXNG and the Wayback Machine. An encrypted SQLCipher history of every run you have ever done. A personal document library that gets indexed and searched right alongside the live results. It runs fully offline on Ollama or llama.cpp if you want it to. Use this one when the corpus is what you want and you’ll be coming back to the same subject for months.
hyperresearch is a sixteen-step pipeline with three tiers, and the top tier, dissertation, is opt-in only. It partitions your topic into four to ten chapters and then loops the research steps once per chapter. That’s how you get 25,000 to 80,000 words out of it. Markdown is the source of truth and SQLite is the cache, so the vault stays portable and greppable. It’s Claude-only and it puts Opus on the synthesis and critique roles, so a long run isn’t cheap. Reach for it when you want one large chaptered document at the end.
gpt-researcher is the mature baseline. Thirty thousand stars and the one most likely to already be supported by whatever you’re building on top of. Its MCP surface, specifically get_research_context and get_research_sources, hand back the raw material separately from the written report. That means your agent can do the writing instead of getting handed prose. One caveat: you need a paid search API to get good results out of it.
hoolulu/deep-research produces the same chaptered shape as hyperresearch but it’s portable across Claude Code, Codex, Cursor, OpenCode, Windsurf and Cline, and it is multilingual.
local-deep-researcher is the smallest readable implementation of the reflect-then-fill-the-gap loop that all of these are variations on.
deep-searcher inverts the whole premise: research over your private corpus, with the web as an optional supplement. That’s the opposite of everything else on this list.
The Ones That Return a Table Instead of Prose

DeepGit does GitHub-only tool discovery and returns a scored comparison table. It preserves your actual query intent, meaning must-haves, nice-to-haves and anti-patterns, instead of flattening everything into keywords. This is ethe right tool for “find me the N projects that do X,” which is the question this entire post is an answer to.
last30days-skill is recency-windowed research across social and forum sources. Reddit, X, Hacker News, YouTube transcripts, Bluesky, Polymarket odds. It ranks by actual engagement, not search position, so it answers “what are people saying about this right now.” Add --store and the briefs accumulate into a local SQLite database you can run scheduled watchlists and digests against.
The Ones That Hand You Sources, Not Conclusions
paper-qa does academic literature with citations traceable down to page ranges, across your own PDFs plus Semantic Scholar, Crossref and Unpaywall. Use it when a claim has to be defensible, not just plausible.
reddit-research-mcp is semantic search across Reddit where every finding cites a real post or comment, upvote count included. This is where you get demand signals and pain points in people’s own words. Generic web search flattens all of that into blog posts about the topic, written by people who also only read blog posts about the topic.
The Audit Layer
RivalSearchMCP has no LLM inside the server at all. Every result carries a tier, freshness, corroboration and citation score out of 100, every multi-result response carries an aggregate confidence signal, and find_conflicts surfaces numeric, date and polarity disagreements between sources instead of averaging them. It is an auditing layer instead of a research tool, and it composes with any of the others.
And STORM, Which Is a Reference Design Now
STORM out of Stanford did not make the table, but it deserves the mention because it’s the only project in this space whose output shape is a wiki article. It gets there by discovering perspectives from existing articles on similar topics, then simulating a conversation between a Wikipedia writer and a topic expert grounded in real sources. Which is a clever way to get an outline that is not just the first five headings an LLM associates with your topic. Last pushed 2025-09. Treat it as a reference design to steal from, not a dependency to take on.
The One I Forked

The pipeline in deep-research-agent is not my design. The skills, the agent and the original strategy modules come from Weizhena/Deep-Research-skills by Lan Zheng, MIT licensed, and all the credit for the structure goes there. Outline, then fields, then one agent per item, then roll the JSON up into a report. I kept that part verbatim.
It Would Not Install the Way I Wanted
APM only accepts a source whose root is a package, meaning a SKILL.md, or an apm.yml plus .apm/, or a plugin.json. Upstream ships its agent as a bare agents/ directory with none of those, so apm install Weizhena/Deep-Research-skills/agents fails validation. Which is a problem, because the skills don’t work without the agent.
So the first thing that happened was repackaging the whole thing into one APM installable bundle:
apm install eristoddle/deep-research-agent --target claude
# or
apm install eristoddle/deep-research-agent --target copilot
The Agent With No Tool Allowlist
Upstream’s agent has no tools: frontmatter at all, which means it inherits every tool the host offers. Under Copilot in VS Code, that includes the embedded browser and the download tooling.
An agent whose instructions say “systematically explore” roughly twenty five source families, handed a browser, opened about a hundred editor tabs in a single run. In the same run it decided to write its own report-generator script rather than use /research-report.
It’s now restricted to WebSearch, WebFetch, Read, Write, Bash with an explicit prohibition on browser automation, downloads, and self-authored research scripts.
No Budget, No Stop Condition, No Way to Tell Working From Stuck
Back to my spinner. Upstream tells the agent to generate “5-10 query variations,” to “read beyond the first few results,” and to cover that merged list of about twenty five source families. There is no cap on searches, no cap on fetches, no cap on link depth, and no definition of done.
There is now a three-level depth setting, defaulting to standard:
| Level | Searches | Fetches | Link depth | Modules |
|---|---|---|---|---|
quick | 3 | 4 | 1 | 1 |
standard (default) | 8 | 12 | 1 | 2 |
deep | 20 | 30 | 2 | 3 |

Set it per run with /research-deep deep, per project with execution.depth in outline.yaml, or ad hoc by naming explicit numbers in the task prompt. Explicit numbers win, then the named level, then the outline, then the default.
The agent now reports budget state as it goes, like [deep: 3/20 searches, 5/30 fetches], and it stops at the ceiling. The budget also propagates down to every per-item agent, along with the tool prohibitions, so the constraints survive the handoff. And the fetch budget counts every retrieval attempt.
Instructions in the prompt that contradicted the budget got rewritten, not left in there to fight it. That sounds obvious. It’s also the step everyone skips when they bolt a limit onto an existing prompt, and then they wonder why the model ignores the limit.
The Part I Really Liked: Search Modules
Search modules are what make this repo worth having instead of just a patched fork.
Most research tools search the open web generically and then scale by adding more sources. This one tries to search fewer, better places, and it decides where to look before it searches anything. That’s what a search module is: a per-domain routing file with a source list, an access method per source, an ordering rule for which sources outrank which, and documented workarounds for the ones that block agent fetching.
There are twelve of them now. Five are upstream’s, and those five assume you are debugging code or reading papers: general-web, github-debug, stackoverflow, academic-papers, chinese-tech.
Now there is also an AI ecosystem and market family:
benchmarksputs independent evaluators first, makes the configuration and observation date mandatory, and labels self-reported scores as self-reported.model-releasesranks docs and deprecation pages above announcement posts, and wants model IDs, not marketing names.pricingwill not quote a price from anything but the provider’s own page, and records unit, host and date with it.vendor-landscapebuilds the competitive set from vendors’ own comparison pages, and keeps claim separate from evidence.
Plus agent-tooling, which is its own family and covers the things you install and run, not call over an API. Agent CLIs and IDEs, MCP servers, skills, plugins. The questions you actually have about those are the config format, the permission model and the version history.

Then two more that are not about technology at all. competitor-content samples what has already been published on a topic, reading three to five top pages for outline, not prose, plus People Also Ask and forum questions, and reports the union of subtopics and the gap. It’s also explicit about its limits: WebSearch returns a result list, not a SERP, so ranking position, search volume and keyword difficulty are unavailable. I would rather a module tell the agent “you can’t know this” than let it produce a confident number out of nothing.
demand-signals answers “what do people keep complaining about, in their own words, across places that do not talk to each other.” That needs raw user language, not a ranked page or a spec sheet.
Building a Module by Discovering Its Sources Instead of Guessing Them
/research-add-module makes you do the source discovery for real. Draft the questions the module has to answer. Run them as plain general-web queries. Tally which domains actually held the answers. Then work out and test how to query each one, whether that’s a site: query, the site’s own search URL, a stable index page you can fetch directly, or a note recording that it blocks fetching entirely. It registers the result, then checks whether the new module actually beats general-web on the original questions, and offers to throw it away if it doesn’t.
demand-signals got built that way, by running the discovery pass across seven unrelated probe topics instead of writing a source list that looked right. What came out of it was more specific than anything I’d have guessed. Discourse’s search.json works and I confirmed it on two unrelated instances. Other forum software falls back to a site: query, because XenForo’s own community confirms its search is POST-only with no fetchable route. People Also Ask earns its own dedicated query pass. Amazon product Q&A went in as unreachable, 503 on every product I tested, recorded rather than silently dropped.
Installing It Does Not Give You a Tool, It Starts a Research Project

You do not install this and end up with a research agent. You install it into a project, and from that point the copy inside that project starts drifting toward the kind of research that project does. Three mechanisms do it.
Runs accumulate into a tree, not a pile. Every run lives under one root, research/ by default, and research/INDEX.md records a tree, not a list. Research does not happen once. One run’s findings point at the next one, so the index keeps a map of which run spawned which, plus a **Leads** checklist per run of the directions that run opened and I haven’t chased yet.
Sources that keep earning their place get promoted. /research-harvest scans every run under the root and tallies which source URLs keep showing up. A URL becomes a promotion candidate once it has appeared in at least three runs and actually supported a field in at least two of them. It never writes into a module itself. It writes a candidate list for a human to choose from.
The modules it feeds live in the project and survive reinstalls. Local modules go in .agents/web-search-modules-local/, which APM doesn’t own. The router checks that directory before its own table and the local module wins a name conflict.
Put those three together and you have a loop. Run research, find out which sources actually answered something, promote the repeat domains into a module that lives in this project, and the next run here routes better than the last one did. A client repo ends up knowing that client’s competitive set. The repo where I research AI tooling ends up knowing where the real leaderboards and deprecation pages are and ignoring everything else.

Everything Else That Got Bolted On
- Routing lives in a file, not in the prompt. Upstream hardcodes five trigger-to-file lines into the agent’s system prompt. That works at five modules and falls over as the library grows, because overlapping triggers get resolved by dropping one, and every module costs system-prompt context on every task whether or not it’s relevant. Routing now lives in
skills/web-search-modules/ROUTING.md, which the agent reads before any search. Adding a module is one file plus one row and the prompt never changes. - A bounded fetch escalation ladder.
WebFetchreturns 403s and bot challenges and JS-only shells often enough to lose real sources. The agent can escalate one URL throughcrwl(crawl4ai) if it is installed, then Firecrawl if both the CLI is onPATHandFIRECRAWL_API_KEYis set. Every rung is stdout-only and bounded, no install attempts, and the whole ladder doesn’t buy an extra fetch slot because it’s one logical fetch of the same page. I wrote about that whole mess separately in What to Do When Your AI Coding Agent Can’t Read a Web Page. unreachable[]is its own output channel. A page nothing could fetch is provenance about a source. It’s not a reason to mark a field uncertain when that field got answered through a documented substitute. The report renders an## Unreachable sourcessection by default./research-enumerateis for when the hard part is finding the items at all. The pipeline only had one shape of work, which was “here are the items, go deep on each.” That doesn’t answer “what exists in this space” when each item needs three shallow facts and the difficulty is enumeration. It sweeps aggregators first, the directories and registries and awesome-lists that list the leaves, before going after the leaves themselves. Its real discipline is the coverage declaration: a category the sweep never reached gets its own subsection saying so and naming the exhausted budget as the reason, never silently omitted, because an unreached category that goes unmentioned reads as a negative result to every later reader.
What It Is Bad At
This repo produces a matrix. You define items and fields, it researches every field for every item with one agent per item, and the report rolls the values up. It is a good fit for “these twelve models across these fifteen attributes.” It is a bad fit for “write me a long document about this topic,” and there’s no reason to force it into that job when six tools listed in this post do it better.

It’s also human-in-the-loop on purpose. The outline gets reviewed and amended before any research runs. That costs you a step. What it buys is the ability to fix a bad research plan before you spend an hour executing it.
And field counts matter a lot. A 42-item outline with 96 fields is roughly four thousand researched values and it will not finish. Keep field lists to fifteen or twenty and prefer items_per_agent: 1, so each finished agent yields a complete file instead of an all-or-nothing batch. Ask me how I learned that one.
Using It
/research <topic> # interactive: builds outline.yaml + fields.yaml
/research-enumerate # breadth-first: catalog what exists into catalog.md + outline.yaml
/research-add-items # amend the item list
/research-add-fields # amend the field list
/research-add-module # build a search module for a domain the existing ones miss
/research-deep # one agent per item -> one JSON per item in results/
/research-report # roll the JSON files up into report.md
/research-harvest # hand-invoked: tally recurring sources across runs
/research and /research-deep pick the host-native entry point. Claude launches web-search-agent, Copilot launches Web Research Writer. The skills do not work without the packaged agents, which is the entire reason the bundle exists.
What I Actually Took Away From This
Most of the work in that fork was not features. Count them up and the majority of the commits are guardrails: a tool allowlist, a search budget, a stop condition, a rule about what counts as a fetch, a prohibition on writing your own scripts, and a routing file so the prompt stops growing. The pipeline design was already good. It’s the reason I forked it.
I will do the ALTERNATIVES page again. Writing “here are eleven tools, nine of them beat mine at something, here is the one job mine is actually for” clarified the repo more than any feature I added.
Also, the part I worked on the most is a part I never planned. I built a matrix generator. Then an index, because run folders were cluttering up repos where I was also writing code. Then a harvest command, because I kept hand-copying the same three URLs into modules. The loop those three turned out to make showed up on its own and became the reason to keep using the thing.
