Perplexity Agent Skills:设计、打磨与维护

导读自 Perplexity Agents 团队公开文:Designing, Refining, and Maintaining Agent Skills at Perplexity。只保留可复用原则,不 dump 原文。

Perplexity 的前沿 agent 产品,地基是模块化的 Agent Skills:通用能力、垂直领域(金融 / 法律 / 健康)、以及长尾专用模块。有些 Skill 很少被调用,但一旦调用就必须对。他们把 Skill 质量与代码质量同等对待。

Agent Harness 地图里,Skills 属于「可按需注入的领域上下文与流程模块」:不替代编排循环,但决定模型在特定意图下看到什么、先读什么、避开什么坑。

关键洞察:写好 Skill 的直觉,和写好传统软件差很多。 很多优秀工程师的 Skill PR,会收到大量「代码里正确、Skill 里反模式」的评论。

Python 之禅 vs Skills 之禅

| Zen of Python | Zen of Skills | | --- | --- | | Simple is better than complex | Skill 是文件夹,不是单文件;复杂度可以是特性 | | Explicit is better than implicit | 激活靠隐式模式匹配 + 渐进披露 | | Sparse is better than dense | 上下文很贵;每 token 最大信号 | | Special cases aren't special enough | Gotchas 才是最高价值内容 | | Easy to explain may be good | 好解释的模型已经会了——删 |

Skill 至少是四样东西

1. 一个目录

不只是 SKILL.md,常见还有:

  • scripts/ —— 给 agent 跑的代码,别让它每次重发明
  • references/ —— 重文档,条件加载
  • assets/ —— 模板、schema、数据
  • config.json —— 首次用户配置

Hub-and-spoke:SKILL.md 是枢纽,分支内容按需加载。税务这类超级复杂域,甚至需要多级主题嵌套;把 1945 个 IRC 条款一股脑塞进单目录,表现可能比不加载 Skill 还差。层级要配检索与速查,否则只是增加间接层。

2. 一种格式

SKILL.md 必须有 namedescription,且 name 与目录名一致:小写、无空格、可用连字符。

description 是路由触发器,不是内部文档。 常见写法是 “Load when…”,不是 “This Skill does…”。还可有 depends:metadata:,或把 runtime 配置放进旁路 JSON/YAML,避免污染模型上下文。

3. 可调用

默认不整包塞进上下文,而是运行时 load_skill(name=...),拷进沙箱,递归加载依赖,再剥离 frontmatter,只给 body 与附加文件。对 Coding Agent 来说,这比把所有 runbook 塞进 AGENTS.md 更可扩展:全局指令保持短,领域知识按意图拉起。

4. 渐进的

以 Perplexity Computer 的三档成本为例:

| Tier | 加载什么 | 预算感 | 何时付费 | | --- | --- | --- | --- | | Index | 每个 Skill 的 name: description | ~100 tokens/Skill | 每个会话、每个用户,永远付 | | Load | 完整 SKILL.md body | 目标 ≤ ~5k tokens | 加载后整段对话都背着 | | Runtime | scripts / references / assets / 子 skill | 无界 | 仅当 agent 去读时 |

Index 门槛极高:必须有用,描述必须极密。Body 一旦加载,废话会拖累其它 Skill 与整体能力。

什么时候需要 Skill

需要: agent 没有这段特殊上下文就会做错;要跨 run 极度一致;知识耐用但不在训练数据里(企业流程、品味、截止后规范)。例如设计 Skill 里「用哪些字体、感觉如何」——模型从通用训练学不来。

不需要: 一串模型本就会的 git 命令;复述系统提示;变化比维护更快的远程 MCP 工具清单(会漂移)。

每一句都是税。 测试句:没有这句话,agent 会做错吗? 不会就不该占 token。难写短,才像好 Skill。用 LLM 五分钟 one-shot 出 PR,多半很差;研究甚至显示 self-generated Skills 平均无收益

怎么建(五步)

Step 0:先写 Evals

来源:真实用户查询、已知失败、邻域混淆(应路由到别的 Skill 的负例)。至少测「该加载时加载」。负例往往比正例更有力。

Step 1:Description(最难的一行)

  • 以 “Load when…” 开头
  • 目标 ≤ 50 词
  • 写用户意图与真实说法(如 “babysit CI”“watch this PR”)
  • 不要总结工作流

加 Skill 可能让其它 Skill 变差——最小化回归是第一义务。

Step 2:Body

跳过模型已知常识。别写:

1
git log; git checkout main; git checkout -b ...; git cherry-pick ...

而写:

1
Cherry-pick the commit onto a clean branch. Resolve conflicts preserving intent. If it can't land cleanly, explain why.

少 railroading,多目标与边界;gotchas / 负例是高信号。条件重内容踢到 spoke 文件。

Step 3:用层级

| 目录 | 用途 | | --- | --- | | scripts/ | 每轮会重发明的确定性逻辑 | | references/ | 条件才读的重文档 | | assets/ | 输出模板 / schema | | config.json | 首次配置后复用 |

复杂域要想清楚:单体 vs 多个 Skill + depends:

Step 4–5:迭代再发

在分支上多轮 hero query + eval;description 的小词变化可有巨大路由副作用。尽量一次完整 changeset(含 eval),少堆无 eval 的增量 PR。

怎么维护

Gotchas 飞轮(append-mostly):

  • 失败 → 加 gotcha
  • 误加载 → 收紧 description + 负例 eval
  • 该加载未加载 → 加关键词 + 正例 eval
  • 系统提示变更 → 查争用 / 重复

合并后改 description 却无 eval,通常说明偏轨了。

Eval 套件: 加载精度 / 召回 / 禁止加载;渐进读取是否发生;端到端任务 + LLM judge;跨模型族(如 GPT / Claude Opus / Sonnet)行为是否一致。

带走清单

  1. 先 eval(含负例与邻 Skill 禁止加载)。
  2. description 是路由,不是文档。
  3. Gotchas 最值钱:先薄,随失败生长。
  4. 少即是多;每个 Skill 是全局税。
  5. 新 Skill 可能远距离破坏旧 Skill。

这就是 Agent Skills:不是文档库,而是 给模型环境的可路由上下文模块。写 Skill 像在做上下文工程,不像在写 README。

和工具、护栏怎么拼

  • Skills:回答「这类任务该怎么想、注意什么」。
  • Tools / tool use:回答「能调用什么能力」。
  • 状态机护栏:回答「当前阶段允许什么」。

三者正交。只堆 Skills 而工具面过大,模型仍会乱用;只硬拦工具而没有 gotchas,模型在允许集合里仍会犯领域错误。生产系统通常是:薄 harness 循环 + 精路由 Skills + 最小工具集(必要时再加 phase 限制)。

给本地仓库的可操作清单

  1. 盘点「每周重复、且模型常做错」的流程,而不是盘点「我能想到的全部命令」。
  2. 每个候选 Skill 先写 5–10 条正负 eval(含邻域禁止加载)。
  3. description 用真实用户说法;body 只留模型会错的部分。
  4. 把 scripts / 模板放进目录,而不是让模型每轮重写。
  5. 合并后只允许「append gotcha」类小改无大评测;动 description 必须重跑路由套件。

Liked this note? Share it on Twitter / X, or browse more writing from the home page. Feedback and pointers welcome via @qianyuhe.

Thanks for reading.

– 千羽鹤