每一杯手冲咖啡,都是一次 Skill 的执行。
研磨度、水温、注水手法、断水时机——这些看似随意的参数,在专业咖啡师手里是一套精确的、可重复的、经过成百上千次迭代的程序。AI Agent 的 Skill 也一样:把「凭感觉做事」变成「按配方执行」,把个人经验沉淀为组织能力。
这篇文章本身就是一份 Skill。它的格式遵循 SKILL.md 规范,它的内容是手冲咖啡与 AI Skill 设计之间的深层同构。
Overview
没有配方的咖啡师,每次冲煮都是开盲盒。
没有 Skill 的 AI Agent,每次执行都在重新发明轮子。
两者的困境完全一样:输入不确定、参数不透明、输出不稳定。解决路径也一样: 把隐性知识显性化,把显性知识程序化。
手冲咖啡世界里,SCA(精品咖啡协会)用杯测表(Cupping Form)把「好喝」拆解为 10 个可量化维度。AI Agent 的 Skill 框架用 SKILL.md 把「好用的回答」拆解为触发条件、执行步骤、验证清单和常见翻车点。
本质上,它们都是同一个工程范式的产物:
┌─────────────────────────────────────────────────┐
│ Knowledge Codification Loop │
│ │
│ 隐性经验 ──→ 显性配方 ──→ 程序化执行 ──→ 数据反馈 │
│ ↑ │ │
│ └────────── 迭代优化 ←────────────┘ │
└─────────────────────────────────────────────────┘
When to Use
什么时候该写一份 Skill?用咖啡做判断标准:
- 你反复做同一件事——每天早晨冲一杯,还是偶尔来一杯?高频 = 值得写
- 结果不稳定——同样的豆子,今天好喝明天翻车?说明关键参数没有被锁定
- 要教别人——带新人上手,口头说「差不多」是最差的教学方式
- 翻过车——被坑过的地方,是最该写进 Common Pitfalls 的
不该写的场景:一次性任务、纯探索性工作、结果无法验证的操作。一杯喝完就扔的速溶,不需要杯测记录。
核心映射
这是整篇文章的脊柱。手冲咖啡的每一个元素,都对应 Skill 设计中的一个核心概念。
| 手冲咖啡 | Agent Skill | 说明 |
|---|---|---|
| 咖啡豆(产地、处理法) | 原始知识与数据源 | 一切的基础。耶加雪菲和曼特宁需要完全不同的冲法,就像代码审查和数据分析需要完全不同的 Skill |
| 磨豆机(研磨度) | 信息粒度控制 | 太粗萃取不足(信息不够),太细过萃发苦(信息过载)。研磨度就是 Skill 对上下文的裁剪策略 |
| 水温 92-96°C | 执行参数与上下文温度 | 同一个豆子,88°C 和 96°C 出来的风味截然不同。Agent 的「温度」是它的推理自由度——保守任务低温,创意任务高温 |
| 闷蒸(30s 释放 CO₂) | Overview 建立上下文 | 不闷蒸直接注水,咖啡粉会翻滚不均匀。不写 Overview 直接执行,Agent 会缺少全局视角 |
| 分段注水(3-4 段) | 分阶段执行步骤 | 一段水冲到底是最粗暴的方式。分阶段注水让每一段都有明确的萃取目标,Skill 的每一步也应该有明确的子目标 |
| 滤纸 | 输出过滤与质量把关 | 滤纸挡住细粉和油脂,只让干净的咖啡液通过。Skill 的输出格式约束就是那层滤纸 |
| 电子秤(精度 0.1g) | 可观测性与度量 | 不称量就没有一致性。Skill 的验证清单就是你的电子秤 |
| 通道效应(局部穿透) | 执行偏差、漏步骤 | 水流只走阻力最小的路径,其他区域被绕过。Agent 跳过关键步骤时,就是在发生「通道效应」 |
| 杯测记录 | Verification Checklist | 喝完记下来,下次对比。没有记录,进步就是幻觉 |
| 烘焙师笔记(标注瑕疵) | Common Pitfalls | 「这支豆子浅烘容易夹生」「二爆后降温要快」——每一条都是一次翻车的学费 |
| 新豆 Dial-in | Skill 调优与迭代 | 每换一支新豆子都要重新找参数。新场景下的 Skill 也需要 Dial-in,不可能开箱即用 |
冲煮步骤:一杯咖啡的执行生命周期
下面用冲一杯耶加雪菲的完整流程,映射 Skill 从触发到验证的完整生命周期。
第一步:称重——触发条件匹配
咖啡师拿起豆子,看一眼标签:
- 产地:埃塞俄比亚 耶加雪菲
- 处理法:水洗
- 烘焙度:浅中烘
- 烘焙日期:7 天前
→ 匹配到配方:浅烘水洗耶加,标准参数
Agent 收到一个请求,首先做的是 意图识别与 Skill 匹配:
# generated by hugo AI
@dataclass
class SkillTrigger:
"""Skill 的触发条件声明"""
keywords: list[str] # 关键词匹配
context_patterns: list[str] # 上下文模式匹配
negative_signals: list[str] # 排除条件
def matches(self, request: str, context: dict) -> bool:
# 类似咖啡师看豆子标签——
# 不是所有豆子都适合手冲,不是所有请求都适合这个 Skill
if any(neg in request for neg in self.negative_signals):
return False
return any(kw in request for kw in self.keywords)
关键洞察:称重不是形式主义。用错了配方,后面每一步都是浪费。Skill 的 When to Use 和 description 字段就是你的豆子标签——写不清楚,就会被错误匹配。
第二步:研磨——信息预处理
研磨度决定了咖啡粉颗粒的大小分布,直接影响萃取速率。
太粗(French Press 级) → 萃取不足 → 酸涩、单薄
太细(Espresso 级) → 过度萃取 → 苦涩、焦味
刚好(中细,如白砂糖) → 均衡萃取 → 风味清晰
Skill 对信息的处理完全一样:
- 太粗:只给 Agent 一个模糊的指令「帮我写个方案」,没有背景、没有约束、没有示例。Agent 只能凭默认参数硬猜
- 太细:塞进去 50 页文档、20 个链接、100 条规则。Agent 上下文溢出,重要信息被淹没
- 刚好:结构化的上下文,关键约束明确,有 1-2 个示例做锚点
信息粒度光谱:
模糊指令 ←──────────────────────────→ 信息过载
"写个方案" 结构化上下文 50页文档+20个链接
↑
最佳萃取点
(白砂糖级研磨)
第三步:闷蒸——Overview 注入
闷蒸是手冲咖啡中最容易被新手忽略,却对最终风味影响最大的步骤。
30 秒的少量注水,让咖啡粉充分吸水膨胀,释放 CO₂。不闷蒸的后果:
- 咖啡粉中的气体会阻碍水与粉的接触
- 水流会寻找阻力最小的路径(通道效应)
- 萃取不均匀,风味模糊
Skill 的 Overview 就是闷蒸。它的职责是:
- 建立全局上下文——这个 Skill 解决什么问题?在什么场景下用?
- 释放「认知气体」——让 Agent 理解整体目标,避免后续步骤中迷失方向
- 防止通道效应——没有 Overview,Agent 会直接跳到看起来最像答案的路径,绕过真正重要的步骤
一份好的 Overview 不超过 3 句话,但能让后续所有步骤的「萃取效率」提升一个量级。
第四步:第一段注水——主流程启动
闷蒸结束后,第一段注水开始。这段水通常占总水量的 40-50%,目标是建立基础萃取。
映射到 Skill:这是 核心执行步骤。
注水手法:从中心开始,缓慢画圈向外扩展
↓
映射到 Skill:从最确定的步骤开始,逐步扩展到边界情况
为什么要从中心开始?因为中心区域的咖啡粉最密集,萃取效率最高。同样,Skill 的核心步骤应该从最有把握的路径开始——先解决 80% 的场景,再处理 20% 的边缘。
第五步:分段注水——条件分支
第二段、第三段注水,每一段都有明确的目的:
| 注水段 | 咖啡目标 | Skill 映射 |
|---|---|---|
| 第一段 | 建立基础萃取 | 核心流程(happy path) |
| 第二段 | 提升甜感与醇厚度 | 补充细节、增加深度 |
| 第三段 | 调整平衡、控制尾韵 | 边界处理、异常兜底 |
| 断水 | 避免过度萃取 | 终止条件、防止 over-engineering |
分段注水的精髓是 节奏控制。每段之间有间隔,让水有时间渗透。Skill 的步骤之间也需要「呼吸」——给 Agent 留出推理空间,而不是塞满指令。
第六步:断水——终止条件
总水量到了就停,不要「再加一点点」。
过度萃取的咖啡又苦又涩,所有好风味都被坏风味覆盖了。过度执行的 Skill 也一样——做了太多不必要的事情,反而把正确的结果搞砸了。
断水信号(咖啡) 断水信号(Skill)
───────────── ─────────────
目标水量已达到 验证清单全部通过
萃取时间到达上限 执行时间/步骤数到达上限
咖啡液颜色变浅 输出已经满足要求
Agent 开始「发挥创造力」 ← 危险信号
第七步:杯测——验证
冲完之后,喝一口。
这不是客套,这是工程验证。杯测表上的每一个维度都是一项检查:
| 杯测维度 | 验证问题 | Skill 验证清单 |
|---|---|---|
| 香气 | 闻起来像这支豆子该有的味道吗? | 输出格式正确吗? |
| 酸质 | 酸是明亮的还是尖锐的? | 核心功能实现了吗? |
| 醇厚度 | Body 是否足够? | 内容深度够吗? |
| 余韵 | 喝完之后嘴里舒服吗? | 用户拿到这个结果能直接用吗? |
| 平衡感 | 酸甜苦是否协调? | 有没有过度执行或遗漏? |
| 干净度 | 有没有杂味? | 有没有幻觉或多余信息? |
没有 Verification Checklist 的 Skill,就像没有杯测记录的咖啡师——冲了一千杯,不知道哪杯好喝。
Common Pitfalls
翻车案例对照。每一条都是学费。
1. 参数写死,不考虑豆子差异
咖啡:用曼特宁的参数(96°C、中粗研磨)冲耶加雪菲。结果:浅烘豆萃取不足,又酸又寡淡。
Skill:把特定项目的路径、命令硬编码到 Skill 里。换个项目就全盘失效。
修正:Skill 应该声明参数范围,而不是固定值。就像好的咖啡配方会说「浅烘 92-94°C,深烘 88-90°C」,而不是「一律 92°C」。
2. 没有闷蒸,直接闷头冲
咖啡:跳过闷蒸,大水直接浇下去。咖啡粉翻滚、通道效应、萃取不均。
Skill:不写 Overview,直接列步骤。Agent 缺少全局视角,只机械执行每一步,不知道为什么要这么做,遇到异常情况无法判断。
修正:Overview 是闷蒸,不是废话。用 2-3 句话告诉 Agent 这个 Skill 的目标、适用场景和核心逻辑。
3. 研磨度不对,信息粒度失控
咖啡:用 Espresso 的极细粉做手冲。滤杯堵塞,水漫过粉层,苦涩到无法入口。
Skill:在 Skill 里塞进太多细节——完整的 API 文档、所有历史决策、每种边缘情况的处理方式。Agent 的上下文窗口被撑满,重要信息反而被淹没。
修正:核心信息放 SKILL.md,详细参考放 references/。就像磨豆机有不同档位,信息也应该按需取用。
4. 通道效应——步骤被跳过
咖啡:注水时只冲中心,边缘的咖啡粉完全没被浸润。水从中心「通道」直接流下去,只萃取了一小部分。
Skill:步骤之间的依赖关系没有明确标注。Agent 觉得某一步「不需要」就跳过了,结果后续步骤因为缺少前置条件而失败。
修正:用编号步骤 + 显式依赖声明。如果 Step 3 依赖 Step 2 的输出,就写清楚「使用 Step 2 的结果作为输入」。
5. 不断水,过度萃取
咖啡:明明目标水量已经到了,觉得「再冲一点更浓」,结果尾段全是苦味和涩味。
Skill:验证清单都通过了,还继续执行「优化」「美化」「增强」。画蛇添足,把好的结果搞砸了。
修正:验证清单全部通过 = 立即停止。Skill 的终止条件和启动条件一样重要。
6. 不记录,不迭代
咖啡:冲完就喝,喝完就忘。下次换一支豆子,又从开盲盒开始。
Skill:写完第一版就再也不看。场景变了、工具更新了、发现新的坑了——Skill 还是老样子,越来越不准。
修正:每次使用 Skill 后,如果发现新坑或更好的做法,立刻 patch。Skill 的生命力在于持续迭代,和咖啡师不断调整配方一样。
Verification Checklist
一份合格的 Skill(一杯合格的咖啡),应该满足:
- 触发条件明确——不是所有豆子都该用这个配方
- Overview 清晰——2-3 句话建立全局视角(闷蒸充分)
- 信息粒度合适——不粗不细,白砂糖级研磨
- 步骤有序、依赖明确——没有通道效应
- 有终止条件——到了就停,不过度萃取
- 验证清单完整——每个维度都有对应的检查项
- Pitfalls 来自真实翻车——不是想象的,是喝过苦头写下来的
- 可迭代——留了 patch 的接口,不是一次性配方
One-Shot Recipe:一份完整的手冲 Skill
把上面的所有映射,收束成一份可以直接使用的 Skill。它既是冲一杯耶加雪菲的配方,也是设计任何 Skill 的模板。
---
name: pour-over-yirgacheffe
description: >
Use when brewing light-roast washed Ethiopian coffee.
Produces a clean, bright cup with floral and citrus notes.
version: 1.0.0
---
# 手冲耶加雪菲(浅烘水洗)
## Parameters
- 豆量:15g
- 水量:225g(粉水比 1:15)
- 水温:93°C(浅烘偏低,保留花香)
- 研磨度:中细(EK43 刻度 7.5)
- 总时间:2:30 - 3:00
## Steps
1. 称重 & 研磨
→ 确认豆子信息,匹配研磨度
2. 闷蒸(0:00 - 0:30)
→ 注入 30g 水,等待 30s
→ 观察:粉层是否均匀膨胀?有没有干点?
3. 第一段注水(0:30 - 1:00)
→ 中心画圈注水至 120g
→ 目标:建立基础萃取
4. 第二段注水(1:10 - 1:30)
→ 注水至 180g
→ 目标:提升甜感
5. 第三段注水(1:40 - 2:00)
→ 注水至 225g
→ 目标:调整平衡
6. 断水 & 等待滴完
→ 总时间不超过 3:00
## Verification
- [ ] 香气:有明显花香或柑橘调
- [ ] 酸质:明亮、活泼,不尖锐
- [ ] 醇厚度:中等偏轻,干净
- [ ] 余韵:甜感持续,无涩味
- [ ] 总时间:2:30 - 3:00 范围内
## Pitfalls
1. 水温超过 95°C → 花香被烫死,苦味出来
2. 研磨太细 → 流速过慢,过萃
3. 不闷蒸 → 通道效应,萃取不均
4. 第三段注水太猛 → 搅动细粉到滤杯底部,尾段浑浊
这份配方本身就是一份合格的 Skill:有参数声明、有分步骤、有条件判断、有验证清单、有翻车记录。
写在最后
手冲咖啡和 AI Skill 设计,看似风马牛不相及,底层是同一套工程思维:
把不确定性变成可控参数,把个人直觉变成可复制流程,把一次性成功变成持续稳定输出。
咖啡师不会永远用同一个配方——每支新豆子都需要 Dial-in。Skill 也不会永远有效——场景变了就要 patch。真正的专业能力,不是记住一个配方,而是掌握「从零开始调出一杯好咖啡」的方法论。
下次写 Skill 的时候,想象自己在冲一杯咖啡。先看看手里的「豆子」是什么,选对「研磨度」,别忘了「闷蒸」,控制好「注水节奏」,该「断水」就断水,最后认真「杯测」一次。
你的 Agent 会感谢你。就像你的味蕾会感谢一杯认真冲煮的耶加雪菲。
你写 Skill 的时候,有没有遇到过「通道效应」?欢迎在评论区分享你的翻车记录。