关于 research
用于组织完整研究会话的技能,可分类主题、并行派发研究 Agent,并将结果整合为报告。它还会验证搜索覆盖情况并记录未解决的缺口,让未完成或失败的搜索清晰可见。
主要功能
- 01主题领域分类
- 02按权重规划研究渠道
- 03并行派发研究 Agent
- 04合并发现并按相关性排序
- 05验证搜索并按需重试
- 06生成格式化报告并保存会话
适用场景
- 01对主题开展多来源调查
- 02识别搜索渠道未覆盖的缺口
- 03汇总渠道结果并生成研究报告
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ athola/ claude-night-market --skill research安装后在 Claude Code 中输入/research确认已加载。
附带文件modules/stop-verifier.md
详细介绍
研究会话编排器
运行完整的多来源研究会话:分类领域、 分派并行 Agent、综合研究结果, 并输出格式化报告。
不适用场景
- 深入研究活跃会话中的某个子主题(使用
tome:dig) - 合并已收集的研究结果(使用
tome:synthesize)
工作流
步骤 1:分类领域
对主题运行领域分类器:
from tome.scripts.domain_classifier import classify
result = classify(topic)
# result.domain, result.triz_depth, result.channel_weights
如果置信度 < 0.6,分类器会放弃判断并细化
计划,而不是拒绝:result.candidates 列出有关键词支持的
领域,triz_depth 变为这些候选领域中最深的级别,
channel_weights 则是按支持度加权的
混合值。面对歧义时,覆盖范围会扩大而不是缩小,
因为跨领域通道正是为涉及多种词汇的主题准备的。
向用户说明分类器放弃判断,并提供候选列表, 让用户覆盖领域。不要将细化后的计划视为失败; 应将其视为分类器拒绝猜测。
如果 candidates 为空,说明该主题完全没有匹配到关键词。
此时仍采用成本较低的双通道计划,因为没有可供细化的方向,
升级会浪费预算。如果该主题确实值得研究,
说明 _DOMAIN_KEYWORDS 中缺少相应词汇,而不要
强行归入某个领域。
步骤 2:规划研究
from tome.scripts.research_planner import plan
research_plan = plan(result)
# research_plan.channels, research_plan.weights, research_plan.triz_depth
步骤 3:创建会话
from tome.session import SessionManager
mgr = SessionManager(Path.cwd())
session = mgr.create(topic, result.domain, result.triz_depth, research_plan.channels)
步骤 4:分派 Agent
使用 Agent 工具并行启动研究 Agent。 使用以下映射:
| 通道 | Agent 类型 | 提示词包含内容 |
|---|---|---|
| code | tome:code-searcher | 主题 |
| discourse | tome:discourse-scanner | 主题、领域、subreddit |
| academic | tome:literature-reviewer | 主题、领域 |
| web | tome:web-searcher | 主题、领域 |
| triz | tome:triz-analyst | 主题、领域、triz_depth |
规则:
- 分派
research_plan.channels中的所有通道,规划器根据每张卡片的min_depth推导出这些通道:code 和 discourse 在所有深度级别都要分派, academic 和 web 从 medium 深度开始分派,triz 从 deep 深度开始分派 - 在一条消息中分派所有符合条件的 Agent (并行,而非串行)
每个 Agent 的提示词必须包含:
- 主题字符串
- 领域分类结果
- 任何通道专属的上下文信息(discourse 的 subreddit、
triz 的 triz_depth)。对于 triz,还要运行
PYTHONPATH="${CLAUDE_PLUGIN_ROOT}/src" python3 -m tome.channels.triz analyze --topic "<topic>" --domain <domain>并包含其 JSON:该 Agent 没有 shell。工作流运行这些通道时,将该 JSON 作为trizAnalysis参数传入 - 该通道的卡片,来自
tome.channels.cards中的render_card(get_card(channel))。 卡片说明了该通道的限制,并指引 Agent 查看其自身文件中 记录的封套格式。不要在提示词中规定返回格式:Agent 会优先遵循提示词, 而不是其文件;曾有一次会话因为提示词自创的格式而丢失了 canary 记录。
上表是对卡片内容的重述。规划器会依据卡片进行门控, 漂移测试会确保两者保持一致。
命名实体。 列出问题中提及的,或比较时将进行排名的每个产品、项目、
标准或方法,并将列表作为工作流的 entities 参数传入。工作流会搜索每个未被任何通道覆盖的实体,
并将其余实体作为
coverage.unsearched 返回。若直接分派 Agent,则须在综合结果前自行执行相同的检查:对每个没有研究结果提及的实体,
分派 tome:web-searcher。没有搜索依据时,绝不要将某个选项判定为纳入或排除。2026-10-05 的一份报告仅凭描述就排除了 Beartooth,
因为没有通道恰好覆盖它。仍未搜索的实体必须按名称列入报告的
覆盖缺口。
第 5 步:收集并综合
所有 Agent 返回后:
-
将每个 Agent 的发现解析为 Finding 对象
-
在合并任何内容之前,记录每个 Agent 实际搜索的内容:
from tome.synthesis.quality import parse_envelope for envelope in agent_envelopes: # one per dispatched agent session.query_log.extend(parse_envelope(envelope))这一步让空白渠道变得可读。发现记录找到的内容;查询日志记录搜索的内容。如果没有查询日志,出错的渠道和搜索了狭窄主题的渠道就会被视为同一回事:没有发现。跳过这一步,报告中的每个渠道都会显示为
unknown。 -
使用
tome.synthesis.merger.merge_findings()合并 -
使用
tome.synthesis.ranker.rank_findings()排序
第 5b 步:验证,然后循环或停止
from tome.synthesis.verifier import verify_context
check = verify_context(session, passes_run=n) # max_passes default 2
CONTINUE 会说明要做什么以及原因:
rerun:渠道失败、表现降级、没有留下记录,或无法证明自己能够进行搜索。原样再次调度该渠道。reformulate:搜索场所不匹配。使用有效渠道的发现中采用的词汇,再次调度该渠道。add:一个检索渠道从未查看过的薄弱领域候选项。调度该渠道进行搜索。
只调度这些 Agent,将其信封追加到同一会话中,再次合并和排序,然后将 passes_run 增加 1 后再次验证。STOP 则进入第 6 步。达到轮次上限(max_passes,默认值为 2)时执行 STOP,仍需列出未完成的工作:将其报告为缺口,绝不能说成已完成搜索。每项检查的 detail 都会说明读取了什么。有关为何决策依据记录而非判断,请参阅 modules/stop-verifier.md。
第 6 步:生成输出
from tome.output.report import format_report, format_brief, format_transcript
# Default to report format
output = format_report(session)
# Save to docs/research/
output_path = f"docs/research/{session.id}-{slug}.md"
保存会话状态:
mgr.save(session)
第 7 步:展示结果
向用户显示简要摘要:
- 根据
tome.synthesis.frontier.frontier_verdict(session)给出前沿结论及其理由。这是报告对“发现少是因为相关内容本来就少,还是因为搜索执行不佳?”这一问题的回答。 - 根据
tome.synthesis.quality.channel_outcomes(session),显示各渠道的发现数量及其结果状态:ok、empty、error、rate_limited、degraded或unknown - 按相关性列出排名前三的发现
- 已保存报告的路径
- 根据
tome.synthesis.frontier.frontier_stories(session)列出任何研究事项。每个事项都是带有证据的缺口,初始状态均为undecided。请用户将其标记为act、defer或decline。不要替用户做决定,也不要为用户尚未标记的事项创建 issue:搜索记录中没有任何信息能说明什么值得投入该项目的时间。若标记为defer,则使用minister:create-issue创建 issue,使其在会话结束后仍能保留。若标记为act,则立即开始工作,无需创建 issue。若标记为decline,则不记录任何内容。
三个检索渠道会先运行正向控制,再搜索主题查询,因此现在 INCONCLUSIVE 指的是特定情况,而不再是“控制项尚不存在”。应将其理解为以下两种情况之一:渠道未通过其金丝雀测试,因此无法有效搜索;或者渠道进行了搜索,但没有运行控制。结论中的证据会明确说明是哪种情况,并且这两种情况都会生成一项 Research Stories。
triz 不运行控制,并且不纳入结论。它生成类比,而不是检索已有工作,因此其输出不能作为已发表内容的证据,其发现也不计入覆盖范围。
明确说明哪些渠道未能正常完成。只报告“发现了 3 条”,却不说明有两个渠道受到速率限制,会让读者误以为只运行了一半的搜索也足以说明该主题的情况。
然后提供交互式细化选项:
“使用 /tome:dig "subtopic" 探索特定领域。”
错误处理
- 如果某个 Agent 失败,继续使用其余 Agent
- 如果所有 Agent 都失败,报告错误并建议手动研究方法
- 如果综合结果为 0 条发现,应明确说明,而不是生成空报告
- 即使部分失败,也要保存会话状态
输出格式选择
| 标志 | 格式 | 函数 |
|---|---|---|
| (默认) | 报告 | format_report() |
--format brief | 简报 | format_brief() |
--format transcript | 转录文本 | format_transcript() |
退出条件
- 在调度 Agent 之前完成领域分类;如果置信度 < 0.6,则在继续之前请求用户确认
-
research_plan.channels中的每个频道都已调度,没有 调度该列表之外的频道,且全部包含在一条并行消息中 - 每条调度提示词都嵌入了对应频道的
render_card输出,且没有规定 自己的返回格式 - 每轮之后都运行了
verify_context;只有它返回STOP后才撰写报告,且运行轮数不超过max_passes - 如果预算触发
STOP,并要求rerun、reformulate或add,则将非空名称 列为摘要中的待补缺口 - 综合完成后,将会话保存到
docs/research/{session.id}-{slug}.md,无论所有 Agent 是否都成功 - 向用户展示按相关性评分排序的前 3 条发现,以及已保存报告的路径
- 如果所有 Agent 都失败,则报告错误并建议手动替代方案;绝不生成空报告