一键导入
deep-research
Autonomous deep-research loop: iterative investigation, externalized state, convergence detection, fresh context per pass.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Autonomous deep-research loop: iterative investigation, externalized state, convergence detection, fresh context per pass.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | deep-research |
| description | Autonomous deep-research loop: iterative investigation, externalized state, convergence detection, fresh context per pass. |
| allowed-tools | ["Read","Write","Edit","Bash","Grep","Glob","Task","WebFetch","memory_context","memory_search"] |
| argument-hint | [topic] [:auto|:confirm] [--max-iterations=N] [--convergence=N] |
| version | 1.13.1.0 |
Note: Task is allowed for the command executor that manages the loop. The @deep-research agent itself is LEAF-only and does not dispatch sub-agents.
Iterative research protocol with fresh context per iteration, externalized state, and convergence detection for deep technical investigation.
Runtime path resolution:
.opencode/agents/*.md.claude/agents/*.md.codex/agents/*.tomlOperator contract precedence for this skill surface:
.opencode/commands/deep/research.mdreferences/convergence/convergence.md and the deep-research YAML workflowDefault: 0.05 on newInfoRatio (fully-new=1.0, partially-new=0.5, +0.10 simplicity bonus, capped 1.0)
Semantic: convergenceThreshold compares newly discovered information against accumulated research knowledge with negative-knowledge emphasis. Lower = more iterations / higher signal threshold.
NOT INTERCHANGEABLE with siblings:
deep-review uses 0.10 default on weighted P0/P1/P2 severity ratiodeep-ai-council uses 0.20 default on adjudicator-verdict stabilityCarrying threshold expectations across siblings will cause unexpected iteration counts. See this skill's changelog and decision records for the cross-sibling threshold research and parity invariants that confirm thresholds do not carry across siblings.
Use this skill when:
Keyword triggers:
autoresearchdeep researchautonomous researchresearch loopiterative researchmulti-round researchdeep investigationcomprehensive researchUse deep-research for multi-round technical investigation, source triangulation, repeated exploration with fresh context, and research sessions where prior findings should shape the next focus.
/speckit:plan)/speckit:plan)/speckit:implement)@context or direct Grep/Glob)Pattern: aligned with the sk-doc smart-router resilience template.
The router discovers markdown resources recursively from references/ and assets/, then applies intent scoring from RESOURCE_MAP. Keep routing domain-focused rather than hardcoding exhaustive inventories.
references/guides/quick_reference.md for the first-touch operator cheat sheet.references/protocol/loop_protocol.md for lifecycle, dispatch, reducer sequencing, and command-owned state flow.references/protocol/spec_check_protocol.md for bounded spec.md anchoring and generated-fence write-back.references/convergence*.md for stop contracts, signals, recovery, graph gates, and reference-only convergence ideas.references/state*.md for packet layout, JSONL records, markdown outputs, reducer ownership, and reconstruction.references/guides/capability_matrix.md for runtime parity.assets/*.md for markdown templates and prompt assets that are safe to route through guarded markdown loading.| Level | When to Load | Resources |
|---|---|---|
| ALWAYS | Every skill invocation | Quick reference baseline |
| CONDITIONAL | If intent signals match | Loop, convergence, state, spec anchoring, runtime parity references |
| ON_DEMAND | Only on explicit request | Full reference set and markdown assets |
| Phase | Signal | Primary Resources |
|---|---|---|
| Init | No JSONL exists or setup context | loop_protocol.md, state_format.md, state_jsonl.md |
| Iteration | Dispatch context includes iteration number | loop_protocol.md, state_outputs.md, convergence_signals.md |
| Stuck | Dispatch context includes recovery language | convergence_recovery.md, state_reducer_registry.md |
| Synthesis | STOP candidate or final report | convergence.md, state_outputs.md, spec_check_protocol.md |
The authoritative routing logic for scoped loading, weighted intent scoring, ambiguity handling, and graceful fallback.
discover_markdown_resources() recursively scans references/ and assets/.load_if_available() guards paths, checks inventory, and suppresses repeats with seen.UNKNOWN_FALLBACK_CHECKLIST requests disambiguation and missing families return a helpful notice.from pathlib import Path
SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references", SKILL_ROOT / "assets")
DEFAULT_RESOURCE = "references/guides/quick_reference.md"
INTENT_SIGNALS = {
"LOOP_SETUP": {"weight": 4, "keywords": ["autoresearch", "deep research", "research loop", "autonomous research", "setup", "init"]},
"ITERATION": {"weight": 4, "keywords": ["iteration", "next round", "continue research", "research cycle", "delta", "focus"]},
"CONVERGENCE": {"weight": 4, "keywords": ["convergence", "stop condition", "diminishing returns", "legal stop", "newInfoRatio"]},
"RECOVERY": {"weight": 4, "keywords": ["stuck", "recovery", "timeout", "reconstruct", "blocked stop", "blocked_stop"]},
"STATE": {"weight": 4, "keywords": ["state file", "jsonl", "strategy", "dashboard", "registry", "lineage"]},
"SPEC_ANCHORING": {"weight": 3, "keywords": ["spec.md", "generated fence", "folder_state", "lock", "spec anchoring"]},
"RUNTIME_PARITY": {"weight": 3, "keywords": ["runtime", "capability", "parity", "codex", "claude"]},
"RESOURCE_MAP": {"weight": 3, "keywords": ["resource map", "resource-map", "inventory", "coverage gate"]},
}
RESOURCE_MAP = {
"LOOP_SETUP": ["references/protocol/loop_protocol.md", "references/state/state_format.md", "references/state/state_jsonl.md", "references/protocol/spec_check_protocol.md"],
"ITERATION": ["references/protocol/loop_protocol.md", "references/state/state_outputs.md", "references/convergence/convergence_signals.md"],
"CONVERGENCE": ["references/convergence/convergence.md", "references/convergence/convergence_signals.md", "references/convergence/convergence_graph.md"],
"RECOVERY": ["references/convergence/convergence_recovery.md", "references/state/state_reducer_registry.md"],
"STATE": ["references/state/state_format.md", "references/state/state_jsonl.md", "references/state/state_outputs.md", "references/state/state_reducer_registry.md"],
"SPEC_ANCHORING": ["references/protocol/spec_check_protocol.md", "references/state/state_outputs.md"],
"RUNTIME_PARITY": ["references/guides/capability_matrix.md"],
"RESOURCE_MAP": ["references/protocol/loop_protocol.md", "references/state/state_outputs.md"],
}
LOADING_LEVELS = {
"ALWAYS": [DEFAULT_RESOURCE],
"ON_DEMAND_KEYWORDS": ["full protocol", "all references", "complete reference", "resume deep research", "state log", "research/iterations", "deltas", "overnight research", "active lineage", "reference-only", "optimizer"],
"ON_DEMAND": [
"references/protocol/loop_protocol.md",
"references/protocol/spec_check_protocol.md",
"references/convergence/convergence.md",
"references/convergence/convergence_signals.md",
"references/convergence/convergence_recovery.md",
"references/convergence/convergence_graph.md",
"references/convergence/convergence_reference_only.md",
"references/state/state_format.md",
"references/state/state_jsonl.md",
"references/state/state_outputs.md",
"references/state/state_reducer_registry.md",
"references/guides/capability_matrix.md",
],
}
UNKNOWN_FALLBACK_CHECKLIST = [
"Confirm setup vs iteration vs convergence vs state recovery",
"Confirm the target spec folder and research packet",
"Provide the current phase, latest iteration, or failing state file",
"Confirm whether full references or quick routing guidance are needed",
]
def _task_text(task) -> str:
return " ".join([
str(getattr(task, "text", "")),
str(getattr(task, "query", "")),
" ".join(getattr(task, "keywords", []) or []),
]).lower()
def _guard_in_skill(relative_path: str) -> str:
resolved = (SKILL_ROOT / relative_path).resolve()
resolved.relative_to(SKILL_ROOT)
if resolved.suffix.lower() != ".md":
raise ValueError(f"Only markdown resources are routable: {relative_path}")
return resolved.relative_to(SKILL_ROOT).as_posix()
def _guard_resource_map(resource_map: dict[str, list[str]]) -> None:
for intent, resources in resource_map.items():
for relative_path in resources:
guarded = _guard_in_skill(relative_path)
if guarded.startswith("references/"):
tail = guarded.removeprefix("references/")
if "/" not in tail and "-" in Path(tail).stem:
raise ValueError(f"RESOURCE_MAP must target canonical references, not compatibility stubs: {intent} -> {guarded}")
def discover_markdown_resources() -> set[str]:
docs = []
for base in RESOURCE_BASES:
if base.exists():
docs.extend(path for path in base.rglob("*.md") if path.is_file())
return {doc.relative_to(SKILL_ROOT).as_posix() for doc in docs}
def score_intents(task) -> dict[str, float]:
text = _task_text(task)
scores = {intent: 0.0 for intent in INTENT_SIGNALS}
for intent, cfg in INTENT_SIGNALS.items():
for keyword in cfg["keywords"]:
if keyword in text:
scores[intent] += cfg["weight"]
return scores
def select_intents(scores: dict[str, float], ambiguity_delta: float = 1.0, max_intents: int = 2) -> list[str]:
ranked = sorted(scores.items(), key=lambda item: item[1], reverse=True)
if not ranked or ranked[0][1] <= 0:
return ["LOOP_SETUP"]
selected = [ranked[0][0]]
if len(ranked) > 1 and ranked[1][1] > 0 and (ranked[0][1] - ranked[1][1]) <= ambiguity_delta:
selected.append(ranked[1][0])
return selected[:max_intents]
def route_deep_research_resources(task):
_guard_resource_map(RESOURCE_MAP)
_guard_resource_map({"ALWAYS": LOADING_LEVELS["ALWAYS"], "ON_DEMAND": LOADING_LEVELS["ON_DEMAND"]})
inventory = discover_markdown_resources()
scores = score_intents(task)
intents = select_intents(scores)
loaded = []
seen = set()
def load_if_available(relative_path: str) -> None:
guarded = _guard_in_skill(relative_path)
if guarded in inventory and guarded not in seen:
load(guarded)
loaded.append(guarded)
seen.add(guarded)
for relative_path in LOADING_LEVELS["ALWAYS"]:
load_if_available(relative_path)
if max(scores.values() or [0]) < 0.5:
return {
"intents": intents,
"intent_scores": scores,
"load_level": "UNKNOWN_FALLBACK",
"needs_disambiguation": True,
"disambiguation_checklist": UNKNOWN_FALLBACK_CHECKLIST,
"resources": loaded,
}
matched_intents = []
for intent in intents:
before_count = len(loaded)
for relative_path in RESOURCE_MAP.get(intent, []):
load_if_available(relative_path)
if len(loaded) > before_count:
matched_intents.append(intent)
text = _task_text(task)
if any(keyword in text for keyword in LOADING_LEVELS["ON_DEMAND_KEYWORDS"]):
for relative_path in LOADING_LEVELS["ON_DEMAND"]:
load_if_available(relative_path)
result = {"intents": intents, "intent_scores": scores, "resources": loaded}
if not matched_intents:
result["notice"] = f"No knowledge base found for intent(s): {', '.join(intents)}"
return result
This skill is invoked exclusively through /deep:research:auto or /deep:research:confirm. The command YAML owns state, dispatch, convergence, and synthesis.
Never simulate the loop with ad hoc shell dispatch, nested CLI loops, direct @deep-research Task dispatch, /tmp prompt files, or state outside the resolved local research packet.
The YAML workflow owns executor selection. Native @deep-research is the default path; CLI executors are routed through the workflow, not through ad hoc shell loops.
Cross-CLI delegation is possible inside each executor sandbox but discouraged. Do not invoke the same CLI from within itself, and do not assume auth from a parent executor propagates to child CLIs.
Executor invariants:
{state_paths.iteration_pattern}.{state_paths.state_log} with required fields: type, iteration, newInfoRatio, status, and focus.Failure modes include iteration_file_missing, iteration_file_empty, jsonl_not_appended, jsonl_missing_fields, and jsonl_parse_error. Three consecutive failures route to stuck recovery.
Runtime-supported lifecycle modes:
| Mode | Meaning |
|---|---|
new | First run against the spec folder |
resume | Continue the active lineage and append a typed resumed JSONL event |
restart | Archive the existing research tree, mint a fresh sessionId, increment generation, and append a typed restarted event |
Deferred modes are fork and completed-continue. They are reserved but not runtime-supported.
The live code-graph readiness contract reaches four TrustState values: live, stale, absent, and unavailable.
cached, imported, rebuilt, and rehomed remain declared in the shared TrustState type for compatibility, but the readiness helpers used here do not emit them today.
When {spec_folder}/resource-map.md exists at init, deep research promotes it from ad hoc context to canonical packet state.
resource_map_present: true in deep-research-config.json.deep-research-strategy.md Known Context.READMEs, Documents, Commands, Agents, Skills, Specs, Scripts, Tests, Config, and Meta.resource-map.md as the exclusion set for previously inventoried files.{spec_folder}/resource-map.md in research.md References when the map was present at init.{artifact_dir}/resource-map.md from research delta evidence unless the operator passes --no-resource-map.When {spec_folder}/resource-map.md is absent at init:
resource_map_present: false.resource-map.md not present; skipping coverage gate into Known Context./deep:research owns the YAML workflow, which initializes state, dispatches one LEAF iteration at a time, evaluates convergence, synthesizes research/research.md, and saves continuity. The @deep-research agent executes only one research cycle per dispatch.
The research state packet always lives under the target spec's local research/ folder. Root-spec targets use {spec_folder}/research/ directly. Child-phase and sub-phase targets use flat-first: a first run with an empty research/ directory writes flat at {spec_folder}/research/. A pt-NN subfolder ({basename(spec_folder)}-pt-{NN}) is allocated only when prior content already exists in research/ for a non-matching target (continuation runs reuse the existing flat artifact or matching pt-NN packet). This avoids the unnecessary pt-01 wrapper on first runs.
Example (first run on a child phase): .../026-graph.../019-system-hardening/001-initial-research/004-desc-regen/ writes to 004-desc-regen/research/ directly.
Example (subsequent run with prior content for a different target): 004-desc-regen/research/004-desc-regen-pt-02/ (pt-NN allocated as a sibling to the prior content).
State files include deep-research-config.json, deep-research-state.jsonl, deep-research-strategy.md, deep-research-findings-registry.json, deep-research-dashboard.md, .deep-research-pause, .deep-research.lock, resource-map.md, research.md, and iterations/iteration-NNN.md.
v(next): deep-research-findings-registry.json is the canonical registry name for sibling-skill consistency.
Each agent dispatch gets a fresh context window. State continuity comes from files, not memory. This solves context degradation in long research sessions.
Adapted from: karpathy/autoresearch (loop concept), AGR (fresh context "Ralph Loop"), pi-autoresearch (JSONL state), autoresearch-opencode (context injection).
Init creates config, strategy, and state logs. Each loop reads state, checks convergence, dispatches @deep-research, writes iteration markdown and JSONL deltas, refreshes reducer-owned state, and either continues or synthesizes and saves continuity.
Late-INIT can also anchor the research run to spec.md: the workflow acquires the advisory lock, classifies folder_state, seeds or appends bounded context before LOOP, and then syncs one generated findings block back into spec.md during SYNTHESIS while keeping research/research.md canonical.
That contract is exact:
folder_state is always one of no-spec, spec-present, spec-just-created-by-this-run, or conflict-detectedresearch/.deep-research.lock from late INIT through save, skip-save, or cancel cleanup<!-- BEGIN GENERATED: deep-research/spec-findings --> ... <!-- END GENERATED: deep-research/spec-findings --> fence under the chosen host anchorResearch continuity is externalized to files, each iteration starts fresh, convergence uses newInfoRatio/stuck/question signals, strategy and registry are reducer-owned, JSONL remains append-only, and final synthesis consolidates research/research.md.
deep-research-strategy.md, Step 5a): appends empty placeholders if missing, presents the charter for review in confirm mode.[SOURCE: url] or [SOURCE: file:line]research/research.mddeep-research-* artifacts and research/.deep-research-pause; legacy names are read-only migration aliases/deep:research:auto or /deep:research:confirm, and let the YAML workflow own dispatch/tmp prompt dispatchers, or direct Task loops for @deep-research. Command-driven fan-out via step_fanout_spawn in the YAML is SUPPORTED — use --executor/--executors/--concurrency flags on the command; ad-hoc shell fan-out and intra-lineage wave orchestration remain forbidden.complete | timeout | error | stuck | insight | thought
insight: Low newInfoRatio but important conceptual breakthroughthought: Analytical-only iteration, no evidence gatheringThese concepts remain documented for future design work, but they are not part of the live executable contract for /deep:research:
--executor/--executors flags on the command (see §8 EXAMPLES). Each lineage is an independent full loop in {artifact_dir}/lineages/{label}/, converging independently. This is not "wave orchestration"; it is N independent loops.claude -p or similar dispatch modes are used internally by fanout-run.cjs; do not write them ad-hoc from within a research sessionCore documentation: references/guides/quick_reference.md, references/protocol/loop_protocol.md, references/protocol/spec_check_protocol.md, references/convergence/convergence.md, and references/state/state_format.md.
Focused convergence references: references/convergence/convergence_signals.md, references/convergence/convergence_recovery.md, references/convergence/convergence_graph.md, and references/convergence/convergence_reference_only.md.
Focused state references: references/state/state_jsonl.md, references/state/state_outputs.md, and references/state/state_reducer_registry.md.
Templates: assets/deep_research_config.json, assets/deep_research_strategy.md, assets/deep_research_dashboard.md, assets/prompt_pack_iteration.md.tmpl, and assets/runtime_capabilities.json.
Cross-skill alignment: deep-research owns iterative investigation. Its shared resource family mirrors deep-review and deep-ai-council, but its vocabulary remains novelty, sources, negative knowledge, question coverage, and research synthesis rather than severity findings or council agreement.
config.resource_map.emit == false (operator flag: --no-resource-map)Blocking gates: valid config/strategy/state before loop, iteration markdown plus JSONL plus reducer refresh per iteration, final research/research.md and convergence report after loop, and quality guards for source diversity/focus/no weak single source. Continuity save is expected but non-blocking.
Every completed loop produces a convergence report:
This skill operates within the behavioral framework defined in the active runtime's root doc (CLAUDE.md, AGENTS.md, or CODEX.md).
Key integrations:
skill_advisor.py (keywords: autoresearch, deep research)/speckit:resume is the operator-facing recovery surface; canonical packet continuity is written via generate-context.jsBefore research, recover context with /speckit:resume using handover.md -> _memory.continuity -> spec docs. During each iteration, write iterations/iteration-NNN.md, append JSONL, and let the reducer refresh strategy/registry/dashboard. After research, save continuity through generate-context.js.
| Command | Relationship |
|---|---|
/deep:research | Primary invocation point |
/speckit:resume | Canonical recovery surface before resuming or extending an active packet |
/speckit:plan | Next step after deep research completes |
/memory:save | Manual memory save (deep research auto-saves) |
The router discovers reference and markdown asset docs dynamically. Start with references/guides/quick_reference.md, then route to loop protocol, spec anchoring, convergence, state, runtime parity, or recovery references based on intent.
Scripts: scripts/reduce-state.cjs, scripts/runtime-capabilities.cjs.
Related skills: deep-review for iterative audit loops, deep-loop-runtime for shared executor/state/coverage-graph runtime, and system-spec-kit for command-owned state, packet anchoring, and continuity saves.
Routes non-trivial requests to matching skills through standalone MCP metadata and stable advisor tool ids.
Unified spec-folder workflow + context preservation: Levels 1-3+, validation, Spec Kit Memory. Required for file modifications.
OpenCode CLI orchestrator: external dispatch, in-OpenCode parallel sessions, cross-AI handback with full runtime context.
Shared deep-loop runtime: executor + prompt-pack + validation + atomic state + coverage-graph + Bayesian scoring + fallback routing.
Iterative codebase-context-gathering deep loop. Runs a configurable pool over a shared scope in parallel (native-only by default; optional heterogeneous CLI seats) and synthesizes a reuse-first Context Report for planning/implementation. Use before /speckit:plan or /speckit:implement to map existing code, integration points, and conventions.
Unified deep-loop workflow skill: routes a request to one of five modes (context, research, review, ai-council, improvement) over the shared deep-loop-runtime backend. Holds no per-mode logic — it dispatches by workflowMode through mode-registry.json. Use for codebase-context gathering, autonomous research, iterative code review, multi-seat AI Council planning, and evaluator-first agent/model/skill/non-dev-system improvement.