Guides / Research fleet with Claude Code subagents, URLs verified
Running a research fleet with Claude Code subagents and verifying every URL
2026-10-11 · 722 words · Pack: Research Fleet
Ask an agent to "research whether SQLite is sane for a multi-tenant SaaS" and you get a fluent answer in thirty seconds. Ask where a specific claim came from and the fluency drops. Single-pass research has two structural problems: one search returns one source's framing, and a language model summarising thin evidence sounds exactly as confident as one summarising strong evidence. Then there are the links — some fraction of which, in any long research answer, do not resolve or do not say what they are cited for.
A research fleet fixes all three by treating research like a build: decompose, run in parallel, merge, test.
1. Decompose into independent sub-questions
Write the question as one sentence, then split it into three to five sub-questions that are independent (answerable without each other), concrete (a subagent knows when it is finished), and jointly sufficient (answering all of them answers the question). For a contested topic, add an adversarial one:
1. What write-concurrency limits does SQLite have today (WAL, BEGIN CONCURRENT)?
2. Which production SaaS products run SQLite per-tenant, and at what scale?
3. What do Litestream / LiteFS / rqlite / Turso actually guarantee?
4. Adversarial: strongest documented evidence of teams that moved OFF SQLite, and why.
Question 4 is the one a single search never asks. Popular narratives are self-reinforcing in search results; you have to go looking for the counter-evidence on purpose.
2. Dispatch in parallel, with a prompt that forbids memory
Claude Code's subagents run concurrently when launched in a single message. Each gets the same prompt template with its sub-question filled in. The template's rules are what make the output mergeable:
1. Every claim you return MUST cite the URL you read it from. No URL, no claim.
Do not answer from memory.
2. Prefer primary sources: official docs, changelogs, papers, filings.
3. Record the publication or last-updated date when visible; write "undated" otherwise.
4. Look for disagreement. If two sources conflict, return both with their dates.
5. If you cannot find something, say "NOT FOUND: <what>" instead of guessing.
6. Return 3–8 claims.
And a strict return format — claim / url / date / quote / source_type per item, then NOT FOUND and NOTES sections. Structured output from each explorer is what lets the next step be mechanical rather than another round of summarising.
3. Merge into a claim table and cross-check
Collect every claim from every explorer into one table and deduplicate near-identical ones. Then tag each:
- [HIGH] — two or more independent sources agree, at least one primary. Independent means different publishers, not three blogs quoting the same conference talk.
- [MED] — one credible source, or several that plausibly share an origin.
- [LOW] — a single weak source, or an inference you drew from the data.
- [CONFLICT] — credible sources disagree. Show both with dates; do not pick silently.
The tags do real work downstream. A reader can skim the HIGH rows and trust them, read the CONFLICT rows with care, and discount the LOW ones. If a whole sub-question comes back LOW, that is a signal to dispatch one more explorer at it before writing anything.
4. Verify every URL like you would test code
This is the step most research workflows skip, and it is cheap. The pack ships verify-urls.ts: it extracts every URL from the draft, fetches each with redirects followed and a timeout, and reports status, final URL, page title, and — optionally — whether the page contains a keyword the claim depends on.
const res = await f(url, { redirect: "follow", signal: controller.signal, headers: { "user-agent": "research-fleet-verify/1.0" } });
const body = await res.text();
const keyword = opts.expect?.[url];
const keywordFound = keyword ? body.toLowerCase().includes(keyword.toLowerCase()) : undefined;
const ok = (res.ok || allowed) && keywordFound !== false;
return { url, ok, status: res.status, finalUrl: res.url || url, title: titleOf(body), keyword, keywordFound, ms };
Run it on the draft before writing the final report:
bun .claude/skills/research-fleet/scripts/verify-urls.ts draft.md \
--expect "BEGIN CONCURRENT=https://sqlite.org/cgi/src/doc/begin-concurrent/doc/begin_concurrent.md"
| ok | status | url | title/keyword |
| PASS | 200 | https://sqlite.org/wal.html | Write-Ahead Logging |
| PASS | 200 | https://sqlite.org/cgi/src/doc/... | BEGIN CONCURRENT: found |
| FAIL | 404 | https://example-blog.dev/sqlite-2023 | Not Found |
13/14 passed, 1 FAILED — remove or replace before publishing.
The rules are strict on purpose. Any URL that is not 2xx after redirects is removed, and the claim it supported drops one confidence level — or disappears if it had no other source. A URL whose page does not mention the expected keyword is flagged for a re-read. The script exits non-zero when anything fails, so it can gate a publish step the same way a test suite gates a merge. A hallucinated link is a worse failure than no link; this makes it a detected failure.
5. Write the report from the table
The report template leads with the answer in a few sentences, each referencing a claim number, followed by the evidence table, the conflicts, and — importantly — what was not found and where you looked. The verifier's output is attached at the bottom in a collapsed block. Dates are explicit everywhere; "recently" is banned.
Where this is worth the time
A fleet run takes a few minutes and some tokens. Use it when the answer drives a decision, a document other people will read, or a purchase. Do not use it for one documented fact or an API signature — that is a single search. The threshold is roughly: would I be embarrassed if a claim in this turned out to be wrong? If yes, run the fleet and verify the links.
Install
The Research Fleet pack is the orchestration skill, the explorer prompt template, the report template and verify-urls.ts, tested against a local server for 200s, 404s, redirects and missing keywords.
curl -fsSL https://hookcrate.com/install | bash # Windows: irm https://hookcrate.com/install.ps1 | iex
hookcrate login hc_YOUR_KEY
hookcrate install research-fleet
$9/month or $99 lifetime; one license covers every pack in the catalog. (bunx hookcrate is coming soon on npm.)
The pack
Decomposes a research question into sub-questions, runs parallel subagents, cross-checks claims and verifies every URL before reporting.
$9 / month or $99 lifetime — one license covers every pack. Get access.