你正在和 AI 讨论一个功能怎么设计,聊到一个关键问题:「这个库的 API
在并发调用时到底什么行为?」答案不在仓库里,在官方文档和源码里。
谁去读?如果你让当前会话停下来读四十分钟文档,讨论的思路就断了。
research 就是为这一刻准备的:把「查清楚一件事」这单跑腿活
(legwork,指查资料、读文档这类花时间但不需要你做判断的工作)
派给一个后台代理(background agent:在你当前会话之外独立干活的 agent),
你继续讨论,它读完把一篇带来源引用的 Markdown 报告放进仓库。
这个 skill 的全部正文只有三条指令,但每一条都值得拆开讲。
学完这节课,你能说清楚它什么时候自动触发、报告写到哪里、写完该带去哪一步,
以及行为不对时这三条指令里该拧哪一条。
0001 把 22 个 skill 分成三层:配置层(跑一次性的初始设置)、编排层(你手动启动的完整流程)、
纪律层(被反复调用的基本功)。按调用方式这根轴,research 被归进纪律层:
它是 model-invoked 的(人和 AI 都能启动),frontmatter 里没有
disable-model-invocation,agents/openai.yaml 里也没有
policy.allow_implicit_invocation: false——按
.agents/invocation.md 的契约,两个条件都不设就是 model-invoked 的默认形态。
它的 description 是写给 AI 看的,带着触发短语
「Use when the user wants a topic researched, docs or API facts gathered, or reading legwork
delegated to a background agent」,所以 AI 能在任务变质成阅读跑腿时自己把它捡起来。
但按流程位置这根轴,ask-matt 把它放在 Standalone(主流程之外的独立工具)一节,
和 prototype、grill-me、teach 站一排。
两种归类不矛盾,它们说的是两件事:
| 看它的角度 | 归类 | 意思 |
|---|---|---|
| 调用方式(0001 的分层) | 纪律层 · model-invoked | AI 可以自己伸手用它,不需要你逐字打出 /research;别的 skill 也能用一句自然语言把它拉进来(0001 讲过,这叫 prose 调用) |
| 流程位置(ask-matt 的地图) | Standalone,随时可伸手 | 它不在「想法 → 交付」的主流水线上,不拆票、不写代码;它产出的报告是思考的材料,要带回主流程的 grill-with-docs 才发生作用 |
上一课的 handoff(0006)和本课是一对好对照,两者都解决「上下文装不下」,
但方向相反:handoff 把当前对话压缩成一个文件,换一个新会话接着干
(跨会话的桥);research 是同一个会话内分出一个后台代理去平行干活,
主线程一步不停。一个是串联的接力,一个是并联的外包。
罗盘:MISSION.md · 地图:0001 · 路由规则:ask-matt/SKILL.md 的 Standalone 一节 · 调用契约:.agents/invocation.md · 上一课:0006 handoff
SKILL.md 的 description 原文:对一个 question 做调查,依据
high-trust primary sources(高可信度的一手资料,第 5 节细讲),
把发现写成仓库里的一个 Markdown 文件。docs 页补了一句它的价值主张:
报告里保存的东西可以追溯到权威来源,「而不是一份转述的转述」
(a summary of a summary)。
research 回答的是「世界上已经存在的事实」:某个 API 怎么行为、
某份规格实际写了什么、某个说法站不站得住。它不替你做决定、不替你写代码、
也不替你想清楚你想要什么——它只把带出处的事实放到你桌上。
docs 页的原话是:它是「你派出去的跑腿,不是你外包出去的思考」
(legwork you delegate, not thinking you outsource)。
| 谁启动 | 怎么发生 | 典型场景 |
|---|---|---|
| User 你手动 | 直接输入 /research,后面跟要查的问题 |
你明确知道下一步是「查清楚一件事」,而且不想让这个会话停下来读 |
| Model AI 自动 | description 里的触发短语命中:任务变成了 reading legwork(读文档、收集 API 事实之类的阅读跑腿) | 讨论中冒出一个事实问题,AI 判断「这要读不少资料」,自己把 research 拉进来,继续陪你聊 |
| Model 被 wayfinder 调用 | wayfinder 的研究票(research ticket)由 /research 子代理来解决(第 8 节) |
大型模糊工程画决策地图时,「去查某个事实」的那类票 |
docs 页给的判断标准很朴素:当下一步是 finding something out(把某件事查出来),
而不是把某件事想出来或试出来的时候,用它。想靠对话把计划磨清楚 → 那是
grilling;想用一次性代码把设计问题试出答案 → 那是 prototype。
下一节把这条岔路讲透。
权威原文: skills/engineering/research/SKILL.md · 给人看的叙事版: docs/engineering/research.md (aihero.dev/skills-research)
讨论中冒出一个悬而未决的问题,先别急着喊「让 AI 去查一下」。这套技能库把 「回答问题」拆成三条路,选错了会浪费一整轮:答案的来源不同,用的工具就不同。
| 问题的性质 | 答案在哪 | 走哪条路 | 产物 |
|---|---|---|---|
| 「这个 API 到底怎么行为?」「规格里怎么写的?」「这个说法成立吗?」——事实已经存在,只是没人读过 | 在外部世界的资料里(官方文档、源码、规格) | research | 仓库里一篇带来源引用的 Markdown 报告 |
| 「我们到底想要什么?」「这个需求边界在哪?」——答案在你脑子里,还没被问出来 | 在你的判断里,需要被追问才能浮现 | grilling / grill-with-docs | 聊清楚的计划;有代码库时写进 CONTEXT.md 和 ADR |
| 「这个状态机手感对吗?」「这个界面该长什么样?」——纸上谈兵定不下来,得看见真东西 | 要造出一次性代码跑一跑、看一看才知道 | prototype | 明确标记为一次性的临时代码 + 一个答案;代码本身不进交付 |
research——后台代理读遍全网也读不出你的意图,
那是面试(grilling)的活。反过来,拿一个纯事实问题去 grill 用户——用户又不是文档,
问他「这个库的并发语义是什么」只会得到猜测。docs 页把这条分叉写得很直白:
用面试磨计划选 grilling,用一次性代码探索要造什么选 prototype,阅读跑腿选 research。
岔路依据:docs/engineering/research.md 的 「When to reach for it」一节 · 面试课:0003 grilling · 原型课:0008 prototype
research 是整套技能库里最薄的 skill 之一:SKILL.md 连 frontmatter
一共 12 行,正文只有三条指令,外加一个 agents/openai.yaml(里面只有
Codex 选择器的显示名和一行简介,没有策略配置)。薄是设计出来的:它是一条
原语(primitive:被更大流程拼装使用的基本动作),作者故意不规定
「用哪个搜索工具、读几个页面、报告分几节」,把这些留给执行它的 agent 和仓库习惯。
但三条指令每条都钉死了一个不容让渡的要求,逐条看。
| # | 原文指令(压缩) | 钉死了什么 | 故意没规定什么 |
|---|---|---|---|
| 0 | Spin up a background agent to do the research, so you keep working while it reads. | 阅读必须发生在后台代理里,主会话不停——这是整个 skill 的定义性动作(第 6 节) | 派几个代理、代理内部怎么分工 |
| 1 | Investigate against primary sources… Follow every claim back to the source that owns it. | 证据等级:只用一手资料;每个论断都要追到「拥有这个答案的来源」(第 5 节) | 具体读哪些站点、用什么检索手段 |
| 2 | Write the findings to a single Markdown file, citing each claim's source. | 产物形态:一个文件、Markdown、逐条论断带出处 | 文件名、章节结构、篇幅 |
| 3 | Save it where the repo already keeps such notes; match the existing convention; if none, somewhere sensible and say where. | 落盘位置服从仓库已有的笔记习惯;没有习惯时选个合理位置并明确说出来(第 7 节) | 没有统一指定的目录——各仓库自己定 |
把这三条连起来就是它的完整行为模型:后台去读 → 只信一手 → 单文件带回出处 → 按仓库习惯落盘。记这一句,整个 skill 就记住了。
逐条原文:skills/engineering/research/SKILL.md (全文 12 行,值得直接读一遍)· 显示元数据:agents/openai.yaml
primary source(一手资料)是「拥有这个答案的来源」本身:
官方文档、源代码、规格文本、第一方 API。secondary write-up
(二手转述)是别人读过一手资料之后写下的解读:博客、教程、论坛回答、周刊摘要。
SKILL.md 的要求是:调查只用一手资料,并且
每个论断都要沿着引用链追回到拥有它的那个来源。
| 来源 | 算一手还是二手 | 为什么 |
|---|---|---|
| 库的官方文档、官方 API 参考 | 一手 | 行为定义就在这儿,写文档的人拥有这段行为 |
| 库的源代码、测试、commit 历史 | 一手 | 文档可能过时,代码是行为最终的拥有者 |
| RFC、W3C/ECMA 规格文本、协议草案 | 一手 | 规格是规则的原文,不是对规则的报道 |
| 服务方自己的 API 响应(第一方 API) | 一手 | 直接问系统本人,答案没有经过转述 |
| 解读文档的博客、教程、视频 | 二手 | 是「转述的转述」链条上的一环,可能过时、可能读错 |
| 论坛/问答网站的回答 | 二手 | 回答者自己也常常没读过一手资料;可以当线索,不能当证据 |
这条纪律解决的是一个真实病变:AI 生成的答案经常引用「看起来像那么回事」的二手页面, 二手页面又引用别的二手页面,三层之后没人知道最初的论断出自哪里。docs 页说, research 存下的东西要能追溯到权威来源,而不是「一份转述的转述」。 二手材料不是不能看——它能当路标,告诉你一手资料在哪;但报告里每个论断的引用, 必须落在一手来源上。
纪律原文:research/SKILL.md 指令 1、2 · 「转述的转述」:docs/engineering/research.md 的 「What it does」一节
正文第一句不是「去读一手资料」,而是「派一个后台代理去读,这样你可以继续干活」。 指令顺序不是随便排的:docs 页把后台代理称为这个 skill 的 defining move(定义性动作)——没有这个动作,剩下两条不过是普通的「认真查资料」。
为什么是定义性动作?三个理由:
定义性动作:docs/engineering/research.md 的 「Delegated legwork」一节 · 指令原文:research/SKILL.md 指令 0
指令 3 是三条里最容易被忽视、却最影响日常体验的一条: 「存在仓库已经用来放这类笔记的地方;配合已有习惯;如果没有习惯, 放在一个合理的位置,并说明放在哪了。」
| 仓库情况 | 指令要求的行为 | 反例(行为跑偏时) |
|---|---|---|
仓库已有放笔记的目录(比如 docs/research/、notes/ 之类的既有习惯) |
顺着既有习惯放进去,命名风格也向既有文件看齐 | 无视已有目录,新发明一个 research-output/ 顶在仓库根上 |
| 仓库没有这类习惯 | 选一个合理的位置,并且在交付时明确告诉你文件放在哪 | 悄悄丢在某个目录,会话结束后没人找得到 |
注意这条指令和 handoff 的落盘规则正好相反:handoff 的文件写进
操作系统的临时目录(它不是仓库资产,只是过桥的船票,0006 讲过);
research 的报告写进仓库——它是要被反复引用、被 grill、
被设计讨论踩在上面的资产。0001 的全表里,research 的「跑完主要留下什么」一栏写的就是
「仓库里一篇带引用的 Markdown 研究报告」。
和 setup-matt-pocock-skills(0002)的关系也在这里:setup 负责把
「工单系统在哪、文档放哪」这类仓库约定写成 docs/agents/ 下的配置文件。
research 自己不读那些配置来决定落点——它的规则更简单:看仓库现状里笔记已经放哪。
如果你的仓库跑过 setup、文档有了统一住处,research 的报告自然会顺着那个住处走。
落盘规则:research/SKILL.md 指令 3 · 全表对照:0001 · 配置层:0002 setup-matt-pocock-skills
research 自己不调用任何别的 skill(正文三条指令里没有一句
「Run the /xxx skill」,它是片叶子),但有一个 skill 会成体系地调用它:
wayfinder(0016,大型模糊工程的决策地图流程)。
wayfinder 把大工程拆成一张张 Decision ticket(决策票:
挂着问题、解决后产出「决定」而不是「交付物」的 issue,全套词见 CONTEXT.md 和 0001)。
每张票带一个类型标签,其中 wayfinder:research 这一型,原文定义是:
读文档、第三方 API 或本地知识库,把某个决定等在上面的那个事实挖出来;
属于 AFK(agent 自己就能干完,不需要人在场);「当需要的知识在当前工作目录之外时用」;
解决方式就是派一个 /research 子代理。
| wayfinder 给 research 加了什么 | 原文依据 |
|---|---|
| 画地图阶段一次性并行派多个研究子代理,每张研究票一个 | 「Fire the research subagents」——chart 流程第 5 步 |
研究发现放在一次性的 research/<name> 分支上,票里留一个指过去的上下文指针 |
同一第 5 步:「capturing its findings on a throwaway research/<name> branch with a context pointer from the ticket」 |
| 「一个会话最多解决一张票」的铁律,对研究票开例外 | 「never resolve more than one ticket per session — with the exception of research tickets」 |
这个例外和第 6 节是同一个逻辑:研究票天生适合并联——它们彼此独立、都在等外部事实, 串行做纯属浪费。wayfinder 是 research 在编排层的最大用户; 反过来,research 对 wayfinder 一无所知,它只是被叫来「把这个问题查清楚」。 这正是原语该有的样子:被用的一方不需要知道用它的流程长什么样。
wayfinder(编排层,人启动)
│ chart 第 5 步:对每张 wayfinder:research 票
▼
派 /research 子代理(可并行,一会话一票的例外)
│ 读一手资料 → 单篇带引用 Markdown
▼
发现落在 research/<name> 分支 + 票上留指针
│
▼
票被解决 → 决策地图上的雾散一格
研究票定义与例外:skills/engineering/wayfinder/SKILL.md 的 Ticket Types 与 Invocation 两节 · wayfinder 一课:0016 wayfinder
| 动作 | 会写什么 | 不会写什么 |
|---|---|---|
单独跑 /research |
仓库里一篇 Markdown 研究报告,论断逐条挂出处,位置服从仓库笔记习惯 | 不写 CONTEXT.md / ADR,不碰工单系统,不改代码,不写临时 HTML |
| 在 wayfinder 里被当研究票解决 | 报告在一次性 research/<name> 分支上;票上留上下文指针;票的状态随解决推进 |
报告不直接进主分支;分支是一次性的(和 prototype 的「答案留下、代码丢弃」同一思路) |
横向对比几个邻居,副作用的边界就更清楚了:codebase-design(0005)默认
什么都不写,只在对话里对齐词汇;handoff(0006)写文件但写到
系统临时目录;research 写文件且写进仓库——
它是这三个「轻」skill 里唯一常态产出仓库资产的。
/grill-with-docs。ask-matt 的原话:
报告是「可以带进主流程 grill-with-docs 的东西——research 喂饱思考,它不代替思考」。
拿着挂好出处的事实去被面试,比凭印象被面试质量高得多。
(docs 页把下游写成 to-prd;本仓库发布集里没有这个 skill,
对应位置是 to-spec,见 0009。)
| 方向 | skill | 关系 |
|---|---|---|
| 它依赖 | (无) | 正文不调用任何别的 skill,是叶子原语 |
| 被谁依赖 | wayfinder | 研究票的解决手段;chart 阶段并行派发;享一会话一票的例外 |
| 被谁指路 | ask-matt | Standalone 一节告诉用户它的存在和下游 |
| 流程邻居(分工不依赖) | grilling · prototype | 第 3 节的三条岔路:按「答案在哪」选路 |
这个 skill 一共就两个文件:SKILL.md(frontmatter + 三条指令)和
agents/openai.yaml(显示名和简介)。可调的地方少,但每一处对应一类症状:
| 症状 | 先查 / 改哪里 | 不要误改 |
|---|---|---|
| AI 从不主动用它,明明任务已经是读文档的跑腿 | SKILL.md frontmatter 里 description 的「Use when…」触发短语——model-invoked 的自动触发全靠这段措辞(契约见 .agents/invocation.md) |
plugin.json(它本来就在发布集里);ask-matt 的路由句 |
| 它把主会话占住读资料,讨论被晾着 | 指令 0「Spin up a background agent」一句——后台化是定义性动作,被绕开就是这条没被执行 | 一手资料那段(那是证据纪律,不管谁去读) |
| 报告里引的全是博客和论坛,出处经不起抽查 | 指令 1 的 primary sources 一段 + 指令 2 的「citing each claim's source」 | docs/engineering/research.md(那是给人看的叙事,改它不改行为) |
| 报告到处乱丢,每次目录都不一样 | 先想仓库有没有笔记习惯——没有就先立一个;再查指令 3 的表述是否被遵守 | setup-matt-pocock-skills 的配置文件(research 的落盘规则不读它) |
| 它开始替你做决定、顺手把代码改了 | 越界不是文本问题而是角色问题:决定归 grill-with-docs 及主流程,改代码归 implement/tdd——检查是不是用错了 skill(回第 3 节岔路) | 给 SKILL.md 加「不要改代码」的长篇禁令(保持它薄) |
| Codex 选择器里显示名不对 | agents/openai.yaml 的 interface.display_name / short_description——它只管展示,不管行为 |
SKILL.md 正文(那里没有展示元数据) |
先别往回翻表,凭记忆答。选项的长度刻意对齐,不会从版式泄题。行为细节以本课和 SKILL.md 原文为准。
本课主一手材料(请打开原文读,不要只背本页摘要):
skills/engineering/research/SKILL.md
—— 全文 12 行:frontmatter 的触发描述 + 三条指令,是本课所有论断的源头。
docs/engineering/research.md
—— 给人看的叙事版:什么时候伸手、什么是「派跑腿不是外包思考」、它在地图上的位置
(aihero.dev/skills-research)。
skills/engineering/research/agents/openai.yaml
—— Codex 侧的显示元数据;没有 policy 块,是它 model-invoked 身份的旁证。
速查页(本课同步): reference/research.html
导航: 上一课 0006 handoff (跨会话的桥:把对话压缩带走;本课是同会话内的并联外包,正好一对)。 总览仍回 0001 系统地图; 岔路的另外两端见 0003 grilling 和下一课。
建议下一课(0008): 0008 prototype。 三条岔路的另一端:当问题纸上说不清、需要可运行的答案时,用一次性代码去换。 和本课的交接点很直接——先问「答案在哪」:在外部资料里走 research, 在要造的东西里走 prototype,在你自己脑子里走 grilling。
SKILL.md / docs/engineering/research.md /
wayfinder/SKILL.md 的原文,不会临场编造。
做完检索练习后,回复「练习结果 / 哪里卡住 / 开 0008 或先补 0006」,我们安排下一课。