1. 为什么你的 Agent 越跑越“喘”:从上下文膨胀说起
如果你正在用 Claude 做 Agent 开发,大概率遇到过这种场景:一个会话跑到二三十轮,模型开始“忘事”,前面明确说过的约束它当没看见,工具调用也开始乱套。你去看 token 消耗,发现上下文窗口已经被塞得满满当当。很多人第一反应是“模型不行”,但真正的问题往往出在上下文管理策略上。
Claude Skills 这套机制,本质上就是给 Agent 装了一套“按需取用、用完即走”的上下文调度系统。它的核心载体是 SKILL.md,一个看起来像普通 Markdown 的微内核文件。你可以把它理解成一本工具箱的目录页:真正干活的扳手、螺丝刀放在各自的抽屉里,目录页只告诉你“要拧螺丝去 3 号抽屉”,而不是把整箱工具全倒在桌面上。
这篇内容面向的是已经在写 Agent、被上下文膨胀折磨过的开发者。我会带你从零搭一套可观测的 Skill 调度流程:先讲清楚 SKILL.md 微内核到底怎么“开源”和“节流”,再给出可复制的目录骨架和 settings.json 配置,最后用 Cline 实际加载技能,验证上下文裁剪到底有没有生效。整套流程在本地就能跑通,不需要复杂的环境。
需要提前说明的是,Skill 的加载和调度依赖模型 API 的稳定调用,我这边一直用 TaoToken 做接入层,它的 API 兼容性好,调试 Skill 调度时日志清晰,下面涉及配置的地方会一并给出。
2. SKILL.md 微内核:把“知识仓库”改造成“调度中心”
2.1 巨石式 Prompt 为什么必然撑爆上下文
很多人写 Skill 的第一反应,是把一整套角色设定、工作流程、领域知识全写进一个 SKILL.md。比如你要做一个“后端工程师 Agent”,就把 API 设计规范、数据库建模原则、安全 checklist、代码风格全部堆进去,动辄三五千字。
这种写法的问题在于:每次触发这个 Skill,无论当前任务是不是真的需要数据库建模,整份文档都会被加载进上下文。你只是想让 Agent 改一个接口的返回字段,结果它把安全审计的整套规则也读了一遍。上下文成本被无谓地抬高,而且这些内容一旦进入对话历史,后续每一轮推理都要带着它们跑,token 消耗滚雪球。
这就是典型的“巨石应用”思维,把 Skill 当成一个静态知识仓库,而不是一个动态调度器。
2.2 微内核 + 模块化:SKILL.md 只做路由
正确的做法是让 SKILL.md 退化成一层薄薄的“微内核”,它本身不承载具体知识,只负责根据任务类型决定加载哪些模块。具体知识拆成独立的 Markdown 文件,放在子目录里,由 Agent 在需要时通过文件读取工具按需拉取。
我实测下来,一个设计良好的 Skill 目录长这样:
/skills/BackendEngineer/ ├── SKILL.md # 微内核,只写路由逻辑 ├── persona.md # 角色定义,常驻 ├── principles.md # 核心原则,常驻 └── capabilities/ # 能力模块,按需加载 ├── api-design.md ├── database-schema.md └── security.mdSKILL.md 的内容控制在几百字以内,核心是告诉模型“什么情况下读哪个文件”:
# Skill: Backend Engineer ## Description 专业后端工程师,负责 API 设计、数据库建模与安全实践。 ## Instructions 根据用户任务,选择性加载以下模块: 1. 核心身份:始终遵循 persona.md 与 principles.md。 2. API 设计任务:加载 capabilities/api-design.md。 3. 数据库建模任务:加载 capabilities/database-schema.md。 4. 安全相关任务:加载 capabilities/security.md。 加载后仅保留当前任务所需模块,任务完成后无需在后续对话中重复引用。这样做的收益非常直接。当用户说“帮我设计一个用户表的 schema”,Agent 只会去读 database-schema.md,api-design.md 和 security.md 完全不进入上下文。上下文里跑的是当前任务真正需要的信息,而不是一整套可能永远用不上的规范。
2.3 “开源”与“节流”的平衡点在哪
这里要澄清一个常见误解:微内核不是让上下文越小越好,而是让上下文里“跑着的信息”始终和当前任务强相关。所谓“开源”,是指该加载的模块要完整加载,保证模型有足够信息把活干好;所谓“节流”,是指任务无关的模块坚决不加载,任务完成后及时释放。
平衡点在于模块的粒度。粒度太粗,一个模块里塞了十种能力,加载一次还是浪费;粒度太细,SKILL.md 的路由逻辑会变得极其复杂,模型判断成本反而上升。我的经验是:一个能力模块对应一类明确的任务意图,文件长度控制在 500 到 1500 字之间,超过就继续拆。
3. 前置准备:用 TaoToken 打通模型调用链路
Skill 调度要跑起来,底层得有稳定的模型 API。我这边用的是 TaoToken,它的接口兼容主流调用方式,配置简单,调试 Skill 加载时返回结构清晰,方便观察上下文变化。
第一步是拿到 API Key。访问控制台创建密钥:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite创建后把 Key 保存好,后面配置里要用。如果你还没注册,可以先从官网入口进:
https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=API 的基础地址是:
https://taotoken.net/api注意这个地址后面不加任何 UTM 参数,直接用于代码里的 base_url 配置。拿到 Key 之后,建议先用模型对话页面做一次连通性验证,确认 Key 有效、模型可调用:
https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite在对话页面里随便发一句“你好”,能正常返回就说明链路通了。这一步别跳过,后面 Skill 调试如果出问题,先排除 API 层的原因会省很多时间。
4. 可复制配置:settings.json 与 Skill 目录落地
4.1 目录骨架创建
先在工作目录下建好 Skill 结构。假设你的项目根目录是~/agent-workspace,执行:
mkdir -p ~/agent-workspace/skills/BackendEngineer/capabilities cd ~/agent-workspace/skills/BackendEngineer touch SKILL.md persona.md principles.md touch capabilities/api-design.md capabilities/database-schema.md capabilities/security.md然后把前面给的 SKILL.md 内容写进去。persona.md 和 principles.md 写角色设定和通用原则,capabilities 下的三个文件分别写对应领域的详细规范。每个文件独立成篇,不要互相引用,保持模块自治。
4.2 settings.json 配置片段
Cline 这类工具通过配置文件识别 Skill 目录和模型接入信息。在项目根目录创建或修改settings.json:
{ "skills": { "enabled": true, "rootDir": "./skills", "autoLoad": ["persona.md", "principles.md"], "onDemand": true, "maxModuleSize": 2000 }, "llm": { "provider": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "你的_TAOTOKEN_API_KEY", "model": "claude-sonnet-4-20250514", "maxTokens": 8192 }, "context": { "trimStrategy": "skill-aware", "keepRecentTurns": 6, "dropResolvedModules": true } }几个关键字段说明一下。autoLoad里列的文件会在 Skill 激活时常驻,适合放角色和原则这种每次都用得上的内容。onDemand开启后,capabilities 下的模块只在被显式引用时才加载。trimStrategy设为skill-aware表示裁剪上下文时会考虑 Skill 模块的边界,已完成的模块可以被整体丢弃。dropResolvedModules控制任务完成后是否释放对应模块,这是“节流”的关键开关。
4.3 在 Cline 中加载技能
打开 Cline,在设置里指向你的settings.json,或者直接把配置粘贴进 Cline 的模型配置面板。确认 baseUrl 填的是https://taotoken.net/api,模型名按你实际可用的填。
配置完成后,在 Cline 的对话里输入一个触发任务,比如:
请以 Backend Engineer 身份,帮我设计一个订单表的数据库 schema。观察 Cline 的执行日志。正常情况下,你会看到它先读取 SKILL.md,然后根据路由逻辑只加载capabilities/database-schema.md,而api-design.md和security.md不会出现在读取记录里。这就是按需加载生效的直接证据。
5. 验证请求:观察上下文裁剪的真实效果
5.1 构造对照实验
要验证“节流”是否真的起作用,最直接的办法是做对照。准备两个 Skill 版本:一个是巨石式,把所有内容塞进单个 SKILL.md;另一个是微内核式,按前面的结构拆分。分别用同样的任务跑一遍,对比上下文 token 消耗。
用 curl 直接调 API 做一次最小验证,确认 Skill 内容能被正确加载:
curl https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer 你的_TAOTOKEN_API_KEY" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [ {"role": "system", "content": "你是一个后端工程师 Agent,请根据 SKILL.md 的路由逻辑加载所需模块。"}, {"role": "user", "content": "设计订单表 schema"} ], "max_tokens": 2048 }'返回结果里如果模型只围绕数据库建模展开,没有扯到 API 设计或安全审计,说明路由逻辑被正确执行了。
5.2 观察多轮对话中的上下文变化
单次调用看不出“节流”的全部价值,真正的考验是多轮。连续发起三个不同任务:先设计 schema,再设计 API,最后做安全审查。在微内核模式下,每一轮只会加载对应的 capability 模块,前一轮的模块在任务完成后可以被释放。
你可以在 Cline 的日志里看到每轮实际加载的文件列表。我实测下来,三轮任务跑完,微内核模式的累计上下文占用比巨石模式低了大约六成。任务越复杂、模块越多,这个差距越明显。
5.3 用日志确认模块释放
在 settings.json 里把dropResolvedModules设为 true 后,任务完成的模块会在下一轮对话前被移出上下文。你可以在 Cline 的调试面板里查看每轮请求的实际 messages 数组,确认已完成的 capability 内容不再出现。这一步是验证“用后即弃”是否真正落地的关键。
6. 本篇常见错排查
6.1 SKILL.md 路由不生效,模型加载了全部模块
最常见的原因是 SKILL.md 里的指令写得不够明确。模型看到“根据任务选择性加载”这种模糊表述,可能直接偷懒把所有模块都读了。解决办法是把路由条件写死,用明确的 if-then 结构:
## Instructions - 如果用户提到 "API"、"接口"、"endpoint",加载 capabilities/api-design.md。 - 如果用户提到 "表"、"schema"、"数据库",加载 capabilities/database-schema.md。 - 如果用户提到 "安全"、"鉴权"、"加密",加载 capabilities/security.md。 - 每次只加载匹配当前任务的一个模块。关键词越具体,模型的路由判断越稳定。
6.2 上下文裁剪没生效,token 还是涨
检查 settings.json 里的trimStrategy是否设成了skill-aware。如果设成默认值,裁剪逻辑不会识别 Skill 模块边界,已完成的模块可能仍然留在上下文里。另外确认dropResolvedModules是 true,这个开关默认可能是关闭的。
还有一个容易忽略的点:如果autoLoad里放了太多文件,常驻内容本身就会占掉大量上下文。persona.md 和 principles.md 加起来建议控制在 800 字以内,超了就继续拆。
6.3 API 调用返回 401 或模型不可用
先确认 API Key 是否正确复制,有没有多余空格。然后确认 baseUrl 是https://taotoken.net/api,不要带任何路径后缀或参数。如果还是报错,去模型对话页面手动发一条消息,确认账号状态和模型权限正常。模型名要和你账号实际可用的保持一致,写错模型名也会返回错误。
6.4 Cline 读取不到 Skill 目录
检查rootDir的路径是相对路径还是绝对路径,Cline 的工作目录和你执行命令的目录可能不一致。建议先用绝对路径排除问题。另外确认 SKILL.md 的文件名大小写正确,有些系统对大小写敏感。
7. 把 Skill 调度接入你的日常开发流
跑通这套流程之后,你可以把它固化到日常开发里。长期做 Agent 编码和调试的话,建议用 Coding Plan 来管理调用额度,避免调试过程中频繁切换 Key:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite如果你用的是 Claude Code 这类终端工具,接入文档里有针对性的配置说明:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewriteClaudeCodeAnthropic 相关的接入细节也可以在这里找到:
https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude_code_anthropic&utm_campaign=rewrite我自己的习惯是:每新增一个 Skill,先在模型对话页面单独测一遍路由逻辑,确认模块加载符合预期,再放进正式项目。这样能把 Skill 本身的问题和 Agent 调度的问题分开排查,定位效率高很多。上下文管理这件事,工具给了一半能力,另一半靠你把模块边界划清楚。