AI 工程师多少都经历过这样的绝望时刻——第一天,看完各种酷炫的 Demo,满怀信心地开始写一个 Agent,你觉得 AGI 就在眼前;到了第三天,你给它加了十几个工具,想让它接管代码库,它却突然变成了一个「智障」——死循环、幻觉、明明有工具却死活不用…

导致 Agent 变蠢的,往往是我们这些喜欢面向接口设计、喜欢二分断点调试 bug,不懂儿童心理学的「程序员」。

01. 主动探索 > 被动接受

传统提示词工程师直觉是:写一个事无巨细的 System Prompt,把项目背景、API 文档、代码规范一股脑全塞进去。

Claude 团队最早期也是这么干的——RAG。结果索引检索 bug 多,反倒让 Agent 失去了 Agency。

后来,他们做了一个改变:给一个 Grep 的搜索工具,与其外设 RAG 注入上下文,不如让 Agent 自己去代码库里翻。

渐进式披露(Progressive Disclosure):不一次性塞满上下文,而是让 Agent 通过工具和文件系统,按需、递归地发现它需要的信息。

结果模型不仅精准找到了需要的信息,还在搜索的过程中自动建立起了整个项目关于某任务的认知上下文。

这种渐进式披露模式后来成为了 Skills 的设计原则和整个 Harness 工程的基石。

02. 趁手工具,实验迭代

设计 Tool Set,是构建 Agent 最微妙最艺术的环节,这确定了 Agent 可供使用的工具范围。

例如,Claude Code 团队曾想给增加一个「向用户提问对齐」的能力。

  • 第 1 次尝试:复用现有ExitPlanTool计划工具,加了一个参数,让模型计划完顺便把问题带上。结果 Agent 不知道该先写计划,还是该先提问。两个复杂意图纠缠在一起,导致幻觉失控。

  • 第 2 次尝试:增加系统提示词,让模型在输出中用特定语法(比如 [?])提问。结果命中极其不稳定,经常漏符号,或自己发明新语法。

  • 第 3 次尝试:单独写一个干净的 AskUserQuestion 工具。Agent 可随时自主调用,调用时前端弹窗阻塞直到用户回答。结果还不错。

最好的工具设计,不是让模型**「被迫」按照你的格式输出;而是顺应它的直觉,让它在遇到困难时「本能」**地想要拿起这个工具。

但另一方面,随着基模变强,工具设计可能过时,需要实验迭代。

例如,在 Claude Code 早期,模型易在长任务中迷失,忘记要做什么。在这样的背景下,团队为 Agent 设计了一个 TodoWrite 工具:

  • 让模型开始时写 Todo 列表逐项勾掉;
  • 每隔 5 轮对话加入系统消息,比如,「你还有这些 Todo 没做」。

*这个设计在当时很有效。*但随着 Opus 4.5 发布,情况变了。

  • 新模型不仅不需要被提醒 Todo,多余的系统提醒反而开始干扰它:模型不敢主动修改或扩展 Todo 列表,即使任务情况已经发生了变化。
  • 更重要的是,Opus 4.5 使用 Subagents 能力更强,但多个 Subagent 无法协调共享同一个 Todo 列表。

如果说 Todos 是贴在自己桌上的便签;Tasks 就是团队看板。

因此,Tasks 因此诞生,使用 CLAUDE_CODE_TASK_LIST_ID=project-name claude,把多个 CC 实例指向同一个 Task List(对 claude -p 和 Agent SDK 同样有效):

  • 依赖关系:Task A 未完成,Task B 不能开始。这让复杂项目的执行顺序有了保证,多个 Agent 不会同时踩到同一个依赖。

  • 持久化:Tasks 存储在 ~/.claude/tasks,任何 session 和 Subagent 都能读写;Session 关闭、重启,Tasks 依然在。

  • 多 Agent 跨会话广播:一个 Subagent 实例更新了某 Task 状态,所有当前正在运行的 session 都能实时感知这个变化。

03. 面向缓存命中率设计

传统缓存是基于 Key-Value 的,在 LLM API 中,Prompt Caching 是基于前缀匹配的。

想象成搭积木:底层是 System Prompt 和 Tool Schema,上面是历史对话,最顶层是当前的问题。

只要你动了底层的一块积木,上面所有的积木(也就是之前聊过的几十万 Tokens)都要重新全价计算。

这带来了四个极其反直觉的案例。

教训一:按需调用工具?

很多工程师直觉是:给模型当前任务(意图)需要的工具,不给多余的。多节约 token,为什么要给模型它不会用到的工具?

但在 Prompt Caching 的框架下,如果你在会话进行到一半时发现需求变了要修改工具集,那缓存就失效了。

Plan Mode 是最好的例子:进入 Plan Mode 时,直觉是「换成只有读取工具的工具集」。但 Claude Code 的实现中,工具集永不改变,缓存始终有效。CC 是把 EnterPlanModeExitPlanMode 本身做成工具,当用户触发 Plan Mode 时,给模型发送一条系统消息,说明当前处于计划模式、应该只读取文件、完成计划后调用 ExitPlanMode

这个设计还带来了一个额外好处:EnterPlanMode 是 Agent 可自主调用的工具,因此在在遇到复杂问题时,其可主动进入 Plan Mode。

为了缓存命中率,可用工具来模拟状态转换,而不是修改工具集本身来反映状态。

随着 MCP 生态扩张,一个 Agent 可以接入的工具数量急剧增长;7 个以上的 MCP 服务器,光工具描述就消耗了 70k tokens。这是一个真实的工程问题:API调用中,不能无限制塞工具描述,又不能在需要某个工具时才临时调用添加。

工具懒加载:保证 Prompt Caching 的前缀稳定性并提供 Tool Search 原子工具。

即当 MCP 工具描述超过上下文预算的 10% 时,工具被替换成轻量级 stub(只保留工具名和 defer_loading: true 标记)。当 Agent 需要某个工具时,可以自主调用 ToolSearchTool 来搜索并加载完整的工具定义。

教训二:切换到便宜模型省钱

假设你和 Opus 聊了 100k tokens,现在有个很简单的问题,想切 Haiku 省钱。

这个想法听起来符合直觉,但切换到 Haiku 意味着它没有这 100k tokens 的缓存,所有这些 tokens 都需要以全价重新处理,很可能比直接让 Opus 回答还贵。

如果需要切换模型,正确方式是用 Subagent 做 handoff:让 Opus 准备一条交接摘要,把任务背景和当前进展压缩成简短说明,启动一个低成本高速度的模型(比如指定了 haikuBuilt-In Explore)接手;这样新启动的 Subagent 需要处理的上下文极短,不仅真正节省了 Token 成本,还能避免被主对话长历史中积累的无关信息干扰,提高了单次子任务的响应速度和专注度。

其次,Subagent 需考虑「最小权限原则」,限制模型的爆炸半径。例如,笔者观察到 CC 内置的 ExplorePlan 不仅在系统提示词中被反复使用大写字母(CRITICAL、STRICTLY PROHIBITED)禁止修改文件,也在代码层面上通过黑名单 disallowedTools 剥夺了写入和编辑的工具权限,屏蔽了 CLAUDE.mdomitClaudeMd: true)以防被项目特定规则带偏。

教训三:日期/文件修改写在系统提示词

更好的方式是:在下一条用户消息或工具结果里,用一个标记(例如,<system-reminder>)把 update 注入进去,让模型知道「btw,今天是周三」或「xx文件已被用户改动」。

教训四:用专门系统提示词做压缩

对话上下文将满,需要压缩把对话历史总结为摘要,继续新 session。

一个朴素实现是:用不同的 System Prompt 和无工具请求调用 API 生成摘要。然而,这破坏了缓存,这个请求和主对话完全没有共同前缀,所有 tokens 都需要全价处理。

更好的方式是 Cache-Safe Forking:使用完全相同的 System Prompt、工具定义和上下文,把主对话的所有历史消息也附上,*在最后追加压缩指令。*保证前缀缓存直接命中,只有最后的压缩指令是新 tokens。

05. Skills 是 Agent 的避坑指南

Tool Set 确定了 Agent 可供使用的工具范围,Skill Set 进一步确定了工具调用顺序模式的确定性,对齐偏好。

参数 必填 说明
name 省略时使用目录名,只允许小写字母、数字和连字符
description 建议 使用时机,Claude 据此判断何时应用。超过 250 字符会被截断,关键信息放前面。
argument-hint 自动补全时显示的参数提示,例如 [issue-number][filename] [format]
disable-model-invocation 设为 true 可禁止 Claude 自动加载此 skill,改为手动用 /name 触发。默认 false
user-invocable 默认 true。设为 false 则从 / 菜单中隐藏,适合不应由用户直接调用的 skill。
allowed-tools 无需询问权限即可使用的工具列表
model 激活时使用的模型
effort 激活时的推理 effort,会覆盖会话级别的设置。默认继承会话设置。
context 设为 fork 时在独立的子 agent 上下文中运行
agent context: fork 时指定使用的子 agent 类型
hooks 限定在此 skill 生命周期内的 hooks 配置
paths Glob 模式,限制此 skill 仅在匹配的文件路径下自动激活。支持逗号分隔的字符串或 YAML 列表。
shell skill 内 !`command` 块使用的 shell。可选 bash(默认)或 powershell。使用 PowerShell 需设置环境变量 CLAUDE_CODE_USE_POWERSHELL_TOOL=1

2026 年 1 月,Slash Commands 和 Skills 正式合并。2026 年 3 月,skill-creator 全新升级,新增多智能体 benchmark 评估能力。

下面是迭代 Skills 的最佳实践:

  • **少写怎么做,多写坑在哪。**识别 Agent 最容易犯的错误(Gotchas),一个好的 Skill 的 Gotchas 区会随着使用不断增长。
  • 用好 assetsreferencesscriptsSet Up 可以使用config.json,必要时可提示使用 AskUserQuestion 工具询问用户。
  • 不要事无巨细规定执行步骤,提供一定的灵活度,尽量聚焦于能让 Claude 跳出常规思维模式的信息。程序员写 API 文档喜欢罗列功能,但大模型通晓默认常识性观点,只是不懂领域知识。
  • 在 Description 写清楚触发时机,这个字段不是给「人」看的功能摘要。
  • 在 scripts 文件夹提供支持组合链式调用的 CLI/helper functions。
  • Skill 可以用文件系统存储历史记录。比如 standup-post 把每次发出的日报存在 standups.log 里,下次运行时 Claude 会先读取历史,然后告诉你"和昨天相比,今天新增了 X、完成了 Y"。注意:升级 Skill 时可能会删除 Skill 目录里的文件,建议把持久化数据存在 ${CLAUDE_PLUGIN_DATA} 提供的稳定目录里。
  • 可包含只在该 Skill 被调用时才激活的 Hooks,持续到 session 结束,例如 /careful 激活后,通过 PreToolUse Hook 阻止
Skill 功能 适用场景
/careful 通过 PreToolUse 匹配器拦截 rm -rfDROP TABLEforce-pushkubectl delete 等危险命令 明确在操作生产环境时启用,常驻会令人抓狂
/freeze 阻止任何不在指定目录下的 Edit/Write 操作 调试时防止"本想加日志,却不小心修了不相关的代码"

Skills 分发观测

  • 小团队使用代码仓库自动共享,大团队建立内部 Plugin Marketplace。

  • PreToolUse Hook 记录每个 Skill 的调用频率。 关注「高频但不够好,值得投入打磨」技能和「从不被触发,可能 description 写得不够好,或者根本没人用」。 例如,https://gist.github.com/ThariqS/24defad423d701746e23dc19aace4de5

06. Playground

Playground:让 Agent 生成交互式的 HTML 小工具,支持拖拽、点击、调整参数,然后把操作结果以 prompt 的形式输出,粘贴回 Agent 继续对话。

对于用纯文本难描述清楚的任务可以采用 Playground 方法,例如:调整一个 UI 组件的视觉设计、讨论系统架构的某个节点、平衡游戏里某个角色的能力数值。

对于 PM 而言,与其长篇大论写 PRD 画 Mockup,不如让 CC 做一个核心逻辑的 MVP 原型,再决定是否要投入资源真做。

Finally

Agent 没有放之四海而皆准的科学公式;设计 Agent Harness,是一门科学,也是一门艺术。

试想如果把你关在一个小黑屋里解一道复杂数学题,你希望手边有什么工具?

  • 如果你只会心算,你需要纸和笔;
  • 如果你懂进阶操作,一个科学计算器更好;
  • 如果你懂编程,一台带有 Python 环境的电脑才是大杀器。

不要像 Agent 一样活着,但也不要拒绝共情 Agent。

请试着像 Agent 一样思考,这才是走向 AGI 前夜,每个超级个体的必修课。

参考资料
  1. Tool Search now in Claude Code
  2. We’re turning Todos into Tasks in Claude Code
  3. Merging Slash Commands into Skills in Claude Code
  4. Making Playgrounds using Claude Code
  5. How we use Claude Code in Slack
  6. Lessons from Building Claude Code: Prompt Caching Is Everything
  7. Lessons from Building Claude Code: Seeing like an Agent
  8. Lessons from Building Claude Code: How We Use Skills
  9. Claude Agent SDK Workshop
  10. Improving skill-creator: Test, measure, and refine Agent Skills
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐