最近在项目里被 Agent 折腾到差点怀疑人生。模型明明很聪明,可一旦让它处理多步任务,它就开始抓瞎:会写代码但不会先做计划,会搜资料但看不懂哪段有用,会回答知识库问题但每次都没出处。后来我把一套 Agent Skills 逐步拆开、封装、复用到别的项目里,问题才算真正收口。这篇文章会把五个实测最常用的 Skills 完整拆给你看,再给一份可以直接照着写自定义 Skill 的教程,适合已经跑过 Agent 但总觉得不稳定的开发者,也适合刚接触技能体系、想从“单次提示词”走向“可复用能力资产”的人。
1. 为什么模型很聪明,Agent 却很笨:Skills 填了哪个坑
1.1 三个让人崩溃的真实现场
先说第一个现场。某同事用 Agent 批量整理 200 个项目文件,模型写了一段整理脚本,第一次运行失败,返回报错,模型又生成一次,还是失败,来回折腾了十几轮,上下文已经塞满了报错日志,最后 Agent 完全分不清哪些是旧日志、哪些是新结果。这不是模型笨,而是我们给了它“写代码”的临时指令,却没给它“怎么安全地写、写到哪里、如何自检”的结构。
第二个现场是知识库问答。给 Agent 接了一个内部文档库,它确实能找到相关内容,但回答里经常混入模型自己的“知识”。有人问“某配置项现在支持哪些值”,它回答出来一个文档里根本不存在的值。原因很简单:检索返回了候选片段,但模型没有被约束必须引用来源,也没被要求“检索不到就说不确定”。
第三个现场看似小事但同样烦人:周报。每隔两周我都要提醒 Agent“按项目、本周进展、下周计划、风险清单四段输出”,稍微换一种问法它又开始自由发挥。每次重新描述规则,效果还忽好忽坏,前面强调过的东西下一轮就忘。
这三个现场指向同一个问题:把“怎么做”写在对话里,是一次性的;把“怎么做”封装成结构化的能力,才是可复用的。Agent Skills 要解决的就是这个。
1.2 Prompt、工具调用和 Skills 到底差在哪
先看一张我常用的对比表:
| 形态 | 能不能自己执行 | 跨项目复用 | 开发成本 | 典型问题 |
|---|---|---|---|---|
| Prompt(提示词模板) | 否 | 需复制粘贴 | 低 | 每次重复灌输,容易漂移 |
| Function Calling(工具调用) | 是 | 需重新注册 | 中 | 粒度太细,不会自动组合多步 |
| 插件体系 | 是 | 部分复用 | 高 | 绑定平台,迁移成本高 |
| Skill | 是,文档+脚本 | 目录即资产 | 中 | 需要写清楚触发条件 |
这个概念有个很直观的类比:Prompt 像是每次喊“西红柿鸡蛋要放盐”,Function Calling 像是给厨师一把勺子,而 Skill 则是给厨师一张完整菜谱——从什么时候做这道菜、怎么备菜、火候怎么控制、出锅前怎么尝,都写明白了。模型加载 Skill 时看到的不只是一段文字,还包括可以执行的脚本和参考样例。
1.3 为什么说 Skill 是目前投入产出比最高的封装方式
第一个原因是稳定性。脚本一旦写清楚,输出格式就是固定的,模型不会再自由发挥字段。第二个原因是可控性。调用前你可以设置开关、白名单、超时,比让模型自己去“探索”安全得多。第三个原因是沉淀。一个 Skill 调试好之后,可以像工具一样上传给别人用,也可以在不同 Agent 之间复用。这也是为什么我推荐有条件的人优先尝试把常用能力做成 Skill。
2. 第一个值得封装的 Skill:任务拆解器
2.1 它处理的是什么问题
复杂需求是 Agent 最容易翻车的地方。你让它“把用户反馈按严重程度分级,并生成一份处理计划”,它不先想清楚边界条件,直接开始列处理方案,列到一半又发现信息不够,再回头问你。更麻烦的是,这种执行过程是不可审查的,你没法判断它在哪一步的假设出了问题。
任务拆解器的思路很直接:让 Agent 先把目标拆成一串可执行步骤,每个步骤都有依赖关系、验证方式和完成定义,然后停下来等人类确认,确认之后才真正开始执行。它是在模型“动手”和“动脑”之间加了一道闸门,也给了开发者一个干预点。
2.2 Skill 的文件结构与触发设计
目录结构不需要复杂,一个典型版本是这样:
task-planner/ SKILL.md scripts/ plan.py examples/ sample-input.json sample-output.jsonSKILL.md 开头是元信息,模型主要靠 description 里的触发词来决定是否调用,所以我会把适用场景写得非常具体,而不是只写“任务规划工具”这种模糊描述。
--- name: task_planner description: 当用户交给一个需要多个步骤才能完成的目标,或需要规划执行顺序、判断并行/串行任务时使用。适合项目启动、故障排查、方案评审等场景。 --- # 任务拆解器使用说明 当你收到复杂目标时,不要直接执行。先调用本技能生成计划。 输出格式必须是 JSON,包含: - objective:原始目标 - steps:步骤列表 - step_id:编号 - action:具体动作 - depends_on:依赖的前置步骤 - definition_of_done:完成定义 - estimated_time:预估耗时 关键规则: 1. 每一步必须有可验证的完成定义,禁止写“持续推进”这类模糊表述。 2. 能并行的步骤放进 parallel_group。 3. 拆解结束后,等待用户确认再继续执行。脚本plan.py本身做得很轻,它只负责校验模型生成的计划格式是不是符合上面的 schema,如果不合规,会返回具体缺了哪些字段。真正做拆解的还是模型,但脚本把格式约束住了,模型的输出就不会“放飞”。
2.3 为什么必须让计划先经过人工确认
这一步是我踩过坑之后才加上的。最初版本没有确认闸门,模型拆解完直接开干,结果它在某一步选择了错误的数据库接口,后面所有步骤全白费,浪费了十分钟才发现方向错了。加了确认闸门之后,这个错误能在 20 秒内被我发现并纠正。
对那些需要长期稳定运行的 Agent 场景,我建议把确认逻辑做成半自动:低风险步骤自动放行,高风险步骤强制人工确认。比如读操作可以直接过,写操作、删除操作、外部通知操作一律暂停等待确认。风险分级写在 Skill 规则里,模型每次调用都能看到。
2.4 实测效果
在某个测试计划生成的项目里,没有拆解器时,模型直接开始写测试用例,写完的用例东一块西一块,覆盖也不全。接入拆解器后,它会先列出环境确认、接口清单、用例分组、执行顺序、回归范围,每个环节还附带了验证方式。对比下来,计划的完整度明显高于手工列的任务清单,因为模型会用“依赖”和“完成定义”去倒推有没有遗漏步骤。
3. 第二个值得封装的 Skill:网页清洗工
3.1 为什么直接丢 URL 给模型不靠谱
很多开发者觉得,模型能上网就能读网页,实际上模型拿回的是整个 HTML 渲染后的文本,里面混杂导航、广告、页脚、推荐位。你让它提炼一篇文章的核心观点,它可能被侧边栏的“大家都在看”干扰,把毫不相干的内容当成事实。更浪费的是上下文,几篇页面下来,token 消耗巨大,响应速度肉眼可见地变慢。
网页清洗工这个 Skill 解决的是“从 URL 到干净信息”的转换:抓取页面、剔除噪音、提取正文、表格,最后输出标准 JSON。它是 Agent 做资料调研和情报整理时最基础的底座。
3.2 抓取、清洗、结构化三个环节
我用 Python 标准库组合实现了一个能跑通大多数静态页面的版本,核心思路分三步。
第一步是发请求。超时一定要设,默认 15 秒,失败后按指数退避重试两次。UA(用户代理)也不要一直用默认值,否则很容易被静态站拦截。第二步是解析。优先找 main、article 这类语义标签,或者按正文区块的字数和链接密度判断哪些段落是正文。导航区通常链接数量多但文本密度低,正好作为过滤依据。第三步是转 Markdown 或 JSON,表格单独抽出来。
import json import re from urllib.request import Request, urlopen def clean_html_to_markdown(html: str) -> str: # 去掉脚本和样式 html = re.sub(r"<script.*?</script>", "", html, flags=re.S) html = re.sub(r"<style.*?</style>", "", html, flags=re.S) # 按标题、段落、表格转 Markdown text = re.sub(r"<h[1-6][^>]*>", lambda m: "\n" + "#" * int(m.group(0)[2]) + " ", html) text = re.sub(r"<p[^>]*>", "\n", text) text = re.sub(r"<tr[^>]*>", "\n| ", text) text = re.sub(r"<td[^>]*>", " | ", text) # 去掉剩余标签 text = re.sub(r"<[^>]+>", "", text) return text这段代码很简化,真实项目里我会在解析前先判断页面编码,否则中文页面很容易乱码。判断方式是先看 HTML 头部的 charset,如果不存在,就用解码探测库猜一遍。碰到动态渲染页面,再考虑用无头浏览器,但那是少数情况,后面单独讲。
3.3 能不动用无头浏览器就尽量别动
这是我反复强调的一条经验。无头浏览器能解决动态页面问题,但代价极大:每个页面平均耗时可能从 2 秒涨到 20 秒甚至更久,并发一高,内存占用直接起飞。实际项目中,80% 的页面通过挺简单的 HTTP 请求加解析就能拿到核心正文,真正需要完整渲染的是那些用前端框架硬撑起来的网站。我的策略是先用快速请求试一次,拿不到有效内容再降到无头浏览器,并在 Skill 配置里标记哪些域名可以直接走重策略。
3.4 让模型把内容填进固定 Schema
清洗完的文本给模型看,模型还需要按固定结构整理信息。我会在 Skill 里定义一个输出 Schema,要求模型只负责填充,不负责发挥。
{ "title": "标题,缺失则为空字符串", "author": "作者,缺失则为空字符串", "publish_date": "原文发布时间,没有就不填", "content_markdown": "正文 Markdown,禁止添加原文没有的内容", "tables": [] }这里最关键的规则是:字段缺失时填空字符串或空数组,不能为了让输出“好看”而编造。这个约束很多人会忽略,但它直接决定了后续环节的准确率。下游做知识库入库也好、做情报对比也好,最怕的就是模型“润色”过的假数据。
4. 第三个值得封装的 Skill:代码沙箱
4.1 模型最大的毛病是“嘴上跑代码”
大模型写代码很像一个自信的实习生,它看过很多代码、能说出思路,但你不让它真正跑一遍,它永远不知道自己的代码在真实环境里能不能通过。我见过太多次模型在对话里笃定地说“这段脚本可以完成批量改名”,实际上运行起来连路径拼接都写错了。解决办法只有一个:把它生成的代码交给一个隔离的沙箱去跑,然后把标准输出、错误堆栈和退出码原样返回给它,让它根据真实反馈继续改。
4.2 沙箱要保证安全和可复现
沙箱是给 Agent 设置的一个“练习场”,每次运行都是干净环境,跑完就销毁,不留下任何状态。默认策略如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
| 超时时间 | 30 秒 | 超时直接杀死进程,防止死循环 |
| 内存上限 | 2 GB | 防止异常的大数组或内存泄漏 |
| 网络访问 | 关闭 | 默认不联网,需要时单独开启 |
| 文件系统 | 只读 | 只能写临时目录,不能动宿主文件 |
| 最大重试次数 | 3 次 | 模型根据报错修复代码,最多循环三次 |
运行脚本的核心逻辑不复杂,就是把代码写入一个临时文件,然后用受限子进程执行,捕获 stdout 和 stderr,返回 JSON。关键在“受限”两个字:默认不允许 shell,不继承宿主环境变量,工作目录固定在一个临时目录里。
import json import subprocess import sys code = sys.stdin.read() with open("/tmp/agent_code/run.py", "w", encoding="utf-8") as f: f.write(code) try: result = subprocess.run( ["python3", "/tmp/agent_code/run.py"], capture_output=True, text=True, timeout=30, cwd="/tmp/agent_code", ) output = { "exit_code": result.returncode, "stdout": result.stdout[-5000:], "stderr": result.stderr[-5000:], } except subprocess.TimeoutExpired: output = {"exit_code": -1, "stdout": "", "stderr": "timeout"} print(json.dumps(output, ensure_ascii=False))4.3 自校验闭环是它好用的核心
代码沙箱如果只负责“跑一次返回结果”,价值并不大。真正让 Agent 变强的是“跑-看结果-改-再跑”的闭环。我会在 Skill 规则里写明:如果退出码不是 0,模型必须基于 stderr 的报错修复代码,然后重新提交执行,而不是直接给用户号称“已经完成”。
在某个图像处理 Demo 的批量缩放任务里,模型第一次跑挂是因为路径写错,它看到报错后修正了路径,第二次又在输出目录上出错,第三次才成功。整个过程没用我干预,而如果只在对话里给提示词,模型八成会在第一次失败后就开始编一个“看起来成功”的总结糊弄过去。
4.4 一些必须提前设置的防护
沙箱不是越严格越好,太严会让模型任务频繁失败。比如很多脚本要用网络下载资源,你直接禁网它就跑不通。我通常按任务类型分级:数据分析类脚本禁网,网页抓取类脚本允许固定放行目标域名,所有写操作一律重定向到临时目录。还有一个容易忽略的点:临时目录要定期清理,否则跑上一个月就会积累大量垃圾文件,磁盘塞满以后沙箱启动都会失败。
5. 第四个值得封装的 Skill:表格分析师
5.1 数据不规整是常态,不是例外
Agent 处理 CSV、Excel 这类表格数据时,最常见的问题是“睁眼瞎”和“凭空编”。模型其实看不到数据文件,它只能看到你喂给它的描述,如果描述不到位,它就会根据经验猜测数据分布,然后编出一个看起来合理、实际对不上的统计结论。更麻烦的是真实业务表格从来都不干净:日期列有的写“2024/1/3”,有的写“2024-01-03”,数值列里混着“待确认”这样的文本,编码一不小心就是乱码。
表格分析师的核心职责是:先把文件读取、清洗成标准形态,再做字段级画像,输出一份数据“体检报告”,让模型基于真实统计来回答,而不是基于想象。
5.2 输出一份不依赖可视化环境的体检报告
我设计这个 Skill 时没有让它直接出图表,原因是图表依赖具体环境,不好通用。我更倾向于让它输出结构化的统计摘要,这样模型可以基于摘要写结论,也能按需转成 Markdown 表格或文字描述。
{ "source_file": "orders.csv", "file_bytes": 1024, "total_rows": 1024, "columns": [ { "name": "order_date", "dtype": "date", "missing_rate": 0.01, "unique_values": 87, "sample": ["2024-01-03", "2024-03-12"], "issues": ["存在两种日期格式"] } ], "warnings": ["order_id 存在重复值"] }模型拿到这份摘要之后,被要求必须先看到 summary 里面的数据才能开始分析。每个结论必须带字段名和计算条件,比如“近 30 天订单均值为 X 元”,要能对应回 summary 里的字段和过滤条件。这一步就切断了模型自由发挥往回编数据的通道。
5.3 处理大文件的第一法则是“别硬塞”
有人会把一个十万行的 CSV 直接截断喂给模型,这个做法又慢又费 token。正确思路是先做概览,再做聚合,最后只把聚合结果给模型看。这个 Skill 会默认做三件事:检查编码、统计缺失、按关键列做分布概览。碰到超大文件,先抽样 1 万行做快速画像,再提示用户是否需要用全量数据跑某个聚合指标。
5.4 真实案例:运营表格的清洗过程
某次需要分析订单表的异常情况,原始文件里日期列混进了 Excel 自动转换出来的 45231 这类数字格式,还有一列金额带有“¥”符号和空格。表格分析师先跑了清洗模块,把金额列统一为浮点数,把日期列双重解析,最后输出的 summary 里明确标出异常值分布。模型据此回答“有 3% 的订单金额为负数,可能是退款单”,这个结论就是有据可循的,而不是看着文件名猜出来的。
6. 第五个值得封装的 Skill:知识库检索器
6.1 裸检索为什么不够
给 Agent 接一个内部文档库,很多人以为就是“把文档灌进去,让模型回答”,结果就出现开头说的那种问题:模型答得头头是道,其实有一半内容是从训练数据里脑补出来的。要避免这个,需要把“检索+引用”变成强制流程。模型不能凭记忆回答私有知识库问题,回答里必须有检索片段的来源编号,检索不到就要直说“不知道”,而不是绕开。
6.2 混合检索 + 重排是性价比最高的组合
知识库检索器这个 Skill 内部通常包含三类能力:切片、检索、重排。切片负责把文档拆成适合模型阅读的块,同时保留标题层级和原始来源;检索负责从知识库里召回候选片段;重排负责从上一步粗筛出来的上百个候选中挑出最相关的 5~10 个。
我会把检索分成两路:一路走关键词匹配,适合型号、人名、配置项这类精确词;另一路走向量匹配,适合“这个模块的失败原因是什么”这类语义问题。两路结果合并后重排,效果比任何单一路数都稳定。这个设计说穿了就是让精确匹配兜底,让语义匹配负责召回,两条腿走路总比单腿稳。
6.3 让模型必须带引用回答
Skill 规则里最重要的一段约束是这样的:如果候选片段的相关度低于阈值,模型必须回答“知识库中没有足够信息”,并且不能扩展任何未引用内容;如果引用,要用 [来源编号] 标注,同时附上原文片段。我还会在脚本返回的结果里带上每个片段来源文档的路径信息,模型引用时直接把路径带出来。
某次内部评审,原来最大的争议点是 Agent 回答里的某些参数没有出处。换用带引用约束的版本之后,每条回答都可以追溯到具体文档段落。评审从“你觉得它说得对不对”变成“它引用的原文是不是准确”,这是完全不同的审查层次,整个流程的可信度一下子就上来了。
6.4 阈值设得太低是灾难
很多项目把知识库检索结果直接全量塞给模型,哪怕两个片段跟问题毫无关系,也一并送进去。模型很容易被不相关片段带偏。我的做法是去掉那些相关度明显低的候选,宁可返回片段少一些,也不要拿噪音去干扰模型。同时,我把它放在 SKILL.md 的“注意事项”里,提醒每次调用都要检查是否满足阈值,防止模型在信息不足时强行给答案。
7. 自定义 Skill 手把手教程:从目录结构到调试
7.1 先建一个最小可用的骨架
自定义 Skill 不需要一步到位,我建议大家先从一个能跑通完整链路的最小骨架开始,再逐步加细节。标准目录结构一般长这样:
my-skill/ SKILL.md scripts/ run.py examples/ sample-input.json sample-output.json这个结构里,SKILL.md是给模型看的说明书,scripts/run.py是真正会被执行的代码,examples/给模型提供输入输出样例。别小看 examples 这个目录,模型很多时候是靠样例而不是靠文字说明来理解格式的,尤其当你要它输出固定 JSON 的时候,样例几乎能直接纠正它的格式错误。
7.2 SKILL.md 逐行解剖
拿一个批量重命名的 Skill 来演示。SKILL.md 的 frontmatter 里写着name和description,description 决定模型什么情况下调用这个 Skill,所以它是整个文件里最重要的一段文字。
--- name: batch_file_rename description: 当用户需要批量重命名、批量整理文件名,或根据规则统一修改文件扩展名/添加前缀时使用。 --- # 批量文件重命名 ## 适用场景 - 一批文件需要按规则改名 - 文件名存在无规则前缀、后缀、空格等需要清理的情况 ## 操作步骤 1. 收集需要重命名的文件路径列表。 2. 根据用户给的重命名规则生成新旧文件名映射。 3. 执行重命名操作。 4. 输出结果 JSON:{"renamed": [...], "failed": [...]} ## 注意事项 - 重命名前必须输出完整的映射表,等待用户确认。 - 禁止覆盖已存在的文件。 - 如果规则不明确,先向用户询问,不要猜测。这段 Markdown 里写的是给模型看的操作手册。注意描述里那句“等待用户确认”和“禁止覆盖已存在文件”,这两个约束如果写在对话提示词里,很容易在长对话里被模型忘掉,但写在 Skill 说明里,每次调用都会被重新加载,所以效果稳定得多。
7.3 脚本编写规范
脚本是 Skill 的执行部分,我的经验是尽量让它保持“无状态、自包含”。无状态是指脚本不依赖上一次调用的结果,每次调用都把输入完整传入;自包含是指脚本所依赖的运行环境要在 SKILL.md 里写清楚,比如用什么语言、需要装什么库、从哪里读输入。
输入规范我用两种方案:轻量任务走标准输入,复杂任务走临时文件参数。输出统一是 JSON,脚本自身的人类可读日志一律写到标准错误,不要混进标准输出。如果不这样做,模型会拿到一堆乱七八糟的调试日志当成结果,下一次解析直接崩溃。
import json import sys data = json.load(sys.stdin) print(json.dumps(data, ensure_ascii=False))这段代码演示了读取标准输入并输出 JSON 的基本流程。真实 Skill 脚本通常会在中间加上逻辑和异常捕获,但接口规范保持完全一致。这样做的好处是,将来升级脚本、替换脚本,都不会影响模型调用方式。
7.4 放对位置,触发才有效
写好 Skill 之后不是放哪都行,必须放进 Agent 运行时的技能目录里,具体位置可以看平台文档,但道理是一样的:Skill 加载是可发现的,不是靠你把文件路径告诉模型。模型看到的是这个目录下所有 Skill 的 metadata,也就是 frontmatter 里的名称和描述,因此描述写得准不准,直接决定模型会不会在正确时机调用它。
测试时我常用一句话验证:“给我把当前目录下所有 .log 文件重命名成带当天日期的文件”。如果模型回答“没有可用工具”或试图自己写代码而不是调用 Skill,多半是描述里的触发条件没覆盖到用户的原话。这时候要调的不是正文,而是 description。
7.5 调试 Skill 最常见的问题和处理方式
| 问题 | 可能原因 | 处理办法 |
|---|---|---|
| 模型始终不调用 Skill | description 太抽象,没覆盖用户原话 | 增加触发词,写清使用场景 |
| 模型在不需要时误调用 | 描述太宽泛 | 在描述中增加排除条件,如“不要用于……” |
| 脚本执行失败 | 依赖环境不对或输入格式不符 | 检查运行环境,用 sample-input 自测脚本 |
| 输出格式不符合 Schema | 模型没看到样例 | 更新 examples 目录,或在 SKILL.md 里贴一段标准输出示例 |
| Skill 调用后依然乱回答 | SKILL.md 约束不够显式 | 用“必须”“禁止”写清楚边界 |
这几个问题我几乎每次写新 Skill 都会遇到一轮。尤其是第一个,模型不调用 Skill,往往不是我脚本写得有问题,而是 description 里没有把用户可能说的各种“说法”覆盖进去。用户说“这些文件命名太乱了”,和说“按项目名和日期重命名文件”,表达方式完全不同,但都应该触发同一个 Skill。
7.6 让 Skill 能长大多年
Skill 开发完成只是第一步,我更建议把它纳入版本管理,并写一个最小测试。测试可以直接是 shell 脚本:构造一个临时目录,放几个样例文件,调用 Skill 的run.py,检查输出 JSON 是否符合预期。这样每次改动代码或者更新描述后,都可以先跑一轮回归,确认没有破坏已有功能。
8. 实测数月之后,我对 Skills 的几个真实体会
8.1 最值回票价的三个改进
我自己的 Agent 项目在接入这套 Skills 之后,最明显的改变有三个。第一,复杂任务不再失控,任务拆解器逼着模型先给方案,方案通过后我再放行,方向上不会突然跑偏。第二,代码相关的输出能验证了,模型说要做什么,就让代码沙箱跑一遍,跑不通它就得继续改,而不是拿“应该没问题”来糊弄我。第三,知识库回答终于敢拿出去给别人看了,每条结论都能追溯到文档,再也不用靠“感觉它说得对”来判断。
8.2 最大的坑:一个 Skill 塞了太多功能
我最早做的任务拆解器,试图把目标拆解、进度跟踪、风险预警、复盘总结全塞进一个 Skill 里。结果运行起来非常不稳定,因为模型拿到手就不知道该先做哪个部分,经常跳步骤。后来我把它拆成三个独立 Skill,每个 Skill 只负责一件事,调用准确率和输出质量都明显回升。这个教训我记到现在:Skill 的边界要窄,一个 Skill 只解决一个明确问题,宁可数量多一点,也不要让单个 Skill 变得臃肿。
8.3 关于是否会取代提示词
Skills 并不会取代提示词,它更像是一个让提示词体系化、可复用化的外壳。系统提示词里仍然需要保留全局的行为准则,比如语气、安全边界、处理风格;而具体的操作流程和经验知识,就应该沉淀进 Skill。这样做的最大好处是隔离:改一个 Skill 不会影响其他任务的运行,而传统提示词模板往往牵一发而动全身。
基于我个人的实际使用体验,建议你从一个小而实用的 Skill 开始,比如批量文件整理或网页正文提取,让它先在真实任务里跑通三五次,确认稳定以后再逐步扩展。把常用能力逐步变成可积累的技能资产之后,你会发现 Agent 的开发开始变得像拼积木,而不是每次从零开始教育模型。