mcpField
R
research

research

github.com/athola生产力34380 次安装3 天前更新
代码仓库

关于 research

用于组织完整研究会话的技能,可分类主题、并行派发研究 Agent,并将结果整合为报告。它还会验证搜索覆盖情况并记录未解决的缺口,让未完成或失败的搜索清晰可见。

主要功能

  1. 01主题领域分类
  2. 02按权重规划研究渠道
  3. 03并行派发研究 Agent
  4. 04合并发现并按相关性排序
  5. 05验证搜索并按需重试
  6. 06生成格式化报告并保存会话

适用场景

  1. 01对主题开展多来源调查
  2. 02识别搜索渠道未覆盖的缺口
  3. 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 类型提示词包含内容
codetome:code-searcher主题
discoursetome:discourse-scanner主题、领域、subreddit
academictome:literature-reviewer主题、领域
webtome:web-searcher主题、领域
triztome:triz-analyst主题、领域、triz_depth

规则:

  • 分派 research_plan.channels 中的所有通道,规划器根据每张卡片的 min_depth 推导出这些通道:code 和 discourse 在所有深度级别都要分派, academic 和 web 从 medium 深度开始分派,triz 从 deep 深度开始分派
  • 在一条消息中分派所有符合条件的 Agent (并行,而非串行)

每个 Agent 的提示词必须包含:

  1. 主题字符串
  2. 领域分类结果
  3. 任何通道专属的上下文信息(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 参数传入
  4. 该通道的卡片,来自 tome.channels.cards 中的 render_card(get_card(channel))。 卡片说明了该通道的限制,并指引 Agent 查看其自身文件中 记录的封套格式。不要在提示词中规定返回格式:Agent 会优先遵循提示词, 而不是其文件;曾有一次会话因为提示词自创的格式而丢失了 canary 记录。

上表是对卡片内容的重述。规划器会依据卡片进行门控, 漂移测试会确保两者保持一致。

命名实体。 列出问题中提及的,或比较时将进行排名的每个产品、项目、 标准或方法,并将列表作为工作流的 entities 参数传入。工作流会搜索每个未被任何通道覆盖的实体, 并将其余实体作为 coverage.unsearched 返回。若直接分派 Agent,则须在综合结果前自行执行相同的检查:对每个没有研究结果提及的实体, 分派 tome:web-searcher。没有搜索依据时,绝不要将某个选项判定为纳入或排除。2026-10-05 的一份报告仅凭描述就排除了 Beartooth, 因为没有通道恰好覆盖它。仍未搜索的实体必须按名称列入报告的 覆盖缺口。

第 5 步:收集并综合

所有 Agent 返回后:

  1. 将每个 Agent 的发现解析为 Finding 对象

  2. 在合并任何内容之前,记录每个 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。

  3. 使用 tome.synthesis.merger.merge_findings() 合并

  4. 使用 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 都失败,则报告错误并建议手动替代方案;绝不生成空报告

评论

支持 Markdown