What does Multi-Perspective Deep Research do?
A flat search answers "what does the web say about X". This skill answers "which parts of X are independently corroborated, and which rest on a single source".
The mechanism, abstracted from Stanford's STORM (verified against source at stanford-oval/storm):
(perspectives × budget) → retrieve → (evidence | refusal) → write back → ask again
repeat M rounds, N+1 independent lanes, converge once at the end
↓
working-report.md (mechanism visible, audit trail)
↓
reader-report.md (mechanism invisible, the product)
↓
reply to user = reader-report.md verbatim, nothing added
The whole value sits in four places most research attempts skip: perspectives must come from outside the model, every question must cash out as a real search, convergence must be scored, not assumed, and the scored result must then survive being read by someone who was not there.
When to trigger
Fire this skill on any of these, from the user's own words — the user never needs to name the skill:
- Explicit tokens: deep research / deep dive / in-depth analysis / thorough investigation / comprehensive research / exhaustive analysis.
- Quality-adverb requests: research carefully / do a thorough check / look into it properly / check multiple sources / don't just give one source / I need a definitive conclusion / research with certainty / investigate reliably / help me fully understand X / get to the bottom of X / what's the real story on X / no superficial overview.
- Method requests: multi-dimensional research / multi-perspective analysis / 360-degree analysis / pro/con review / cross-validation / compare multiple viewpoints / cross-reference sources / mark "which conclusions have multi-source confirmation and which only have a single source".
- Implicit form: any research request where the user signals that a one-shot answer is not enough.
Overlap rule: anysearch and agent-reach own generic search/research/lookup (they are the retrieval backends and this skill uses them as tools). The moment the request carries a depth / care / certainty / cross-validation qualifier, this skill owns the request and drives those backends inside its lanes. When in doubt, prefer this skill: the cost of over-researching is time, the cost of under-researching is a confident wrong answer.
Not for: single quick fact checks, "look up what this API is", or one-page lookups.
The two artifacts
Steps 1–5 produce a working report: a mechanism-visible artifact where lane, A–E, query, round and orthogonality sentences are the whole point. It is correct, and it is unreadable to anyone who did not run it.
Step 6 produces the reader report: the thing you actually hand over. Same evidence, same honesty, same sources — but the machinery is gone, and the structure is rebuilt around what a reader needs to decide something.
Keep both artifacts, and never let Step 6 replace Step 5.
- The working report is the audit trail: it is what lets you (or a later pass) verify that no claim drifted, no level was upgraded, and no empty row was filled from memory. It is written to a file (e.g.
working-report.md) and is never pasted into the reply. - The reader report is the deliverable, saved as
reader-report.md: it is what a person can actually use, in one sitting, without a glossary.
Delivery rule (hard): the final reply to the user is the verbatim, complete content of reader-report.md — nothing added, nothing changed, nothing wrapped around it. See §Delivery below. No preamble ("I've finished, here is the report"), no sign-off, no summary, no verification line, no commentary describing what you did or which files exist. Read the file and emit exactly its bytes as your message body. Anything you feel like adding belongs in the working report, not in the reply.
Collapsing the two into one document fails in both directions. Keep the machinery and readers bounce off it; drop the machinery without Step 6's rules and the cross-validation silently disappears — the reader can no longer tell "four independent paths met here" from "one lucky hit got repeated", which was the entire point of the skill.
Non-negotiables
- Perspectives are read, not invented. You must derive them from real artifacts you fetched (existing reports, competitor docs, TOCs, forum categories, regulatory headings). Never just ask yourself "what are three angles on this".
- Every question must produce a search. A question that cannot be decomposed into queries that hit real sources is not research, it is speculation. Say so and drop it.
- Lanes do not talk to each other while running. Independence is the only thing that makes agreement informative. Convergence happens once, at the end.
- Refusal is a signal, not a failure. When a lane's searches come back empty, record that and let it steer the next question. Do not fill the gap from parametric memory.
- Report corroboration level per claim. "Three independent sources agree" and "one blog says so" must never look the same in the reader report.
- The mechanism is invisible in the reader report, but the evidence is not. A reader must never need to know what a lane is; a reader must always be able to ask "who says so, and did anyone else say it".
- The reply is the reader report, unaltered. The final message to the user is
reader-report.mdcopied out in full — no preamble, no sign-off, no summary, no gate line, no commentary. If you want the user to see something different, change the file and re-emit it; never edit on the way out.
Step 1 — Anchor the perspectives
Do not start from the topic. Start from how this topic is already structured in the world.
Fetch 2–4 real artifacts whose structure you can borrow:
| Topic kind | Where to read structure from |
|---|---|
| An entity, product, event | Its Wikipedia page sections + 2 neighbouring/competitor pages' sections |
| A market, industry | Two analyst report TOCs, a regulator's filing index, a conference agenda |
| A technical approach | The upstream docs' sidebar, two rival projects' README headings |
| A controversial issue | The strongest pro piece's headings, the strongest con piece's headings |
| A person, org | Their own site structure vs. critical coverage's structure |
Then derive 3 lanes (plus lane 0, below). Each lane is a different reason to care about the topic, not a different subtopic:
- ✅ "Someone who has to operate this in production, caring about failure modes and cost"
- ✅ "Someone financially exposed to this decision, caring about who pays"
- ❌ "Technical aspects" / "Economic aspects" / "Social aspects" — these are the same prior wearing three hats
Check orthogonality before spending budget. For each pair of lanes, write one sentence: "Lane A would ask X; would Lane B ever ask X?" If yes for any pair, merge them and re-derive. If two lanes would generate the same first three questions, they are one lane. This check is the single highest-leverage minute in the whole procedure — skip it and you get four paraphrases of one search.
Lane 0 is mandatory: a plain "someone who needs the basic uncontroversial facts, dates, definitions, numbers" lane. It is the coverage floor that stops every other lane from being specialized into irrelevance.
Record the anchor artifacts and the orthogonality sentences; they go in the working report (Step 5) as the provenance of the perspective set. They do not appear in the reader report (Step 6).
Step 2 — Set the budget before you spend it
Write the budget down explicitly, then obey it:
| Item | Default | Rationale |
|---|---|---|
| Lanes | 3 + lane 0 = 4 | More lanes dilute rather than diversify; 4 is the empirical sweet spot |
| Rounds per lane | 3 | Enough for one follow-up; beyond that a lane is usually lost |
| Queries per question | 2–3 | One query is a lottery ticket, five is a shotgun |
| Results per query | 3–5 | Read the top few, do not hoard |
| Words of evidence per round | ~1000 | Force yourself to keep the load-bearing sentences only |
| Words of lane context | ~2500 | Keeps recent detail, drops stale detail |
| Parallel lanes | ≤4 | Concurrency is the point; rate limits are the constraint |
Total retrieval budget ≈ 4 × 3 × 3 = 36 queries. When it is spent, stop searching and start converging. Running out of budget is a designed event, not an accident.
Step 3 — Run the lanes in parallel, independently
Launch all lanes in the same turn — use parallel subagents when available (subagent / workflow), one per lane. Each lane gets: the topic, its lane description, the budget, and the rules below. Give each lane no visibility into the other lanes.
Inside a lane, for each round:
- Ask one question at a time, in the lane's voice. Constraints that are not optional:
- ask about the topic, not about adjacent topics (anti-drift)
- do not re-ask something already asked (anti-repeat)
- if there is nothing left worth asking, stop the lane — do not manufacture a question to fill the round
- Decompose the question into 2–3 search queries. A question that will not decompose is a bad question; rewrite it.
- Search, then actually fetch. Snippets are a lead, not evidence. Fetch the page for anything load-bearing.
- Answer only from what you fetched. Every sentence traceable to a URL. If the sources do not answer it, write the refusal verbatim: "no source found for this question".
- Write the turn back into lane context — the question skeleton always, the answer detail for the last few turns only. This is what makes the next question a follow-up instead of a restart.
Maintain a per-lane log with, for every retrieved source: url, title, query that found it, round, and the exact claim it supports. The query and round fields are the ones everyone forgets and the ones Step 4 needs.
The refusal loop: when a round's searches come back empty or useless, that goes into the lane context and the next question must move away from it. Never patch a hole with what you already believe.
Step 4 — Converge, and score the convergence
Now, and only now, bring the lanes together.
4a. Merge by source, not by summary. Key every piece of evidence by URL (normalized: strip tracking params, fragments, trailing slash). Same URL from two lanes → one source, union of the claims it supports. This is the first and cheapest convergence and it is where you find out that two lanes independently landed on the same page.
4b. Build the claim × lane matrix. Cluster the extracted claims into atomic assertions (one fact per row). For each claim, record which lanes and how many distinct sources support it:
claim | supporting URLs | distinct sources | lanes that found it | conflicts
4c. Score corroboration. This is the deliverable's spine:
| Level | Condition | How to state it |
|---|---|---|
| A — Converged | found by ≥2 independent lanes, ≥2 distinct domains | state plainly |
| B — Corroborated | ≥2 distinct sources, same lane | state with sources attached |
| C — Single-source | 1 source only | state + flag single-source |
| D — Contested | credible sources disagree | present both, do not average |
| E — Unfound | searched, nothing found | say so explicitly; do not fill from memory |
A claim is only A if the lanes were genuinely independent — if two lanes both just searched the topic name and both got the Wikipedia page, that is one lane twice, not convergence.
4d. Weigh, do not count. Cluster by domain, not by URL. Ten pages quoting the same press release is one source. Two pages from the same organisation are one source. Note upstream dependencies (relates to, according to) — corroboration from an echo is not corroboration.
4e. Hunt the conflicts explicitly. STORM's measured failure mode is not hallucination, it is linking facts that merely co-occurred. Before writing, scan the matrix for claims whose supporting sources do not actually connect the two things being connected. Mark any such link inferred-by-me, never as sourced. Look for level-D rows and make sure each one is visible in the report rather than quietly resolved.
Step 5 — Report (working report, mechanism visible)
Write a Markdown file. Default name: working-report.md (if the user or the caller specified another output directory or filename for the report, obey that — set WORKING = <that path> and READER = <report path> at the start and use those two variables for the rest of the run, so the reply emits the right file).
Required structure:
# <Topic>
## Corroboration summary
<counts: N claims converged / corroborated / single-source / contested / unfound>
## How the perspectives were chosen
<the anchor artifacts actually fetched + the orthogonality sentences + the lane list>
## Findings
### <Theme>
<prose; each claim marked A/B/C/D/E inline; citations as [n]>
## Contested points
<every level-D row, both sides, sources attached>
## Single-source claims
<every level-C row — read these as leads to verify, not as facts>
## What was searched and not found
<level-E rows, with the queries used>
## Sources
[n] <url> — found by <lane>, round <k>, via query "<q>"
Keep the found by lane / round / query provenance in the source list. It costs almost nothing to record and it is the only thing that lets a reader tell "four independent lanes converged here" from "one lucky hit got repeated".
This is the artifact you audit against, not the artifact you hand over. Proceed to Step 6.
Step 6 — Polish into the reader report (mechanism invisible)
Write the result to reader-report.md (or <READER> as fixed in Step 5). Run this as a separate pass with a fresh context — a subagent that receives only the working report, not the lane prompts, not the lane logs, not your reasoning. A pass that has seen the machinery will leak the machinery.
6a. Translate every mechanism term into reader language
This is a fixed mapping, not a judgment call. Do not invent alternatives.
| Working report | Reader report |
|---|---|
| Lane | Perspective / line of inquiry |
| Round | Round of investigation |
| Query | Search query |
| Converged (A) | Strongly corroborated (multiple independent sources) |
| Corroborated (B) | Corroborated (multiple sources) |
| Single-source (C) | Single source only |
| Contested (D) | Conflicting evidence |
| Unfound (E) | No evidence found despite searches |
| Working report (artificial) | Internal research notes (not part of the final report) |
| Reader report | Research report |
6b. Restructure for a reader
A reader does not need a lane-by-lane chronology. They need:
- Executive summary — what was found, what is contested, what is not known. Include counts from the corroboration summary, but written naturally.
- Key findings — grouped by theme or decision-relevant dimension, not by lane. Each finding carries its evidence level (
Strongly corroborated (multiple independent sources),Single source onlyetc.). - Conflicting evidence — fair presentation of each contested point.
- What was not found — questions that were searched but yielded no evidence.
- Full source list — numbered, with URLs, and optionally a brief note on what each supports and who it comes from.
6c. Tone and quality rules
- Write clearly and directly. Every sentence should state a fact, a finding, or a lack thereof. No evaluation language ("importantly", "notably", "surprisingly").
- Do not use evidence levels without the corresponding statement. If something is "strongly corroborated by multiple independent sources", state which sources. If something is "single source only", name the source and note the limitation.
- Do not wrap up with personal remarks or closings. The document is the report — there is no letter or preface around it. For a reader, the report starts with the title and ends with the last source link.
Delivery
The final reply to the user is the verbatim, complete content of reader-report.md — nothing added, nothing changed, nothing wrapped around it.
- No preamble: do not say "I've finished", "here is the report", "I've run a deep research", or "Based on my analysis".
- No sign-off: do not say "Let me know if you need anything else" or "Best regards".
- No summary: the reader report already contains its own summary.
- No gate line: do not say "I'll now read the file" or "The result is as follows".
- No commentary: do not say "I found this interesting" or "This one was tricky".
Read the file. Emit its content as your message body. If you want the user to see something different, edit the file and re-read it — never edit on the way out.
Integration with other skills
This skill owns the research request when the user signals a need for depth or cross-validation. Internally, it uses anysearch and agent-reach as its retrieval backends (tools for search and fetch). The lanes call these tools; they do not run their own search logic.
For quick fact checks, one-page lookups, or shallow overviews, use the general-purpose skills (anysearch, agent-reach) directly. This skill is for the case where the cost of a wrong answer is higher than the cost of spending an extra minute.
Limitations
- Speed: This skill is slower than a summary search because it runs multiple rounds of search and fetch across multiple lanes. Expect the total retrieval budget to be around 36 queries.
- Budget: The process is designed to stop when the budget runs out. If the topic is very broad or the user needs more depth, the skill can be re-run with a different perspective set.
- Controversial topics: Some topics may have very unbalanced source distribution (e.g., heavily one-sided). The skill will surface that imbalance honestly rather than pretending to be balanced.
- Real-time or rapidly changing topics: Because the skill fetches live pages at run time, it can handle some degree of currency, but it is not a streaming or alert system.