Agent Skills 实战:从环境搭建到多 Agent 协作的完整指南
2026/9/9 21:49:44 网站建设 项目流程

AI Agent 在 2024 到 2025 年之间经历了一次明显的变化:从“能聊天的对话模型”逐渐演变成“能调用工具、能拆分任务、能多步执行的智能体”。但真正让 Agent 从演示走向工程化落地的,不只是大模型本身,而是一层常被忽略的能力封装单元——Agent Skills。Skill 把一类可重复执行的任务固化成结构化描述、参数定义和实现代码,让模型在需要时按描述调用,而不是每次都在长长上下文中重新理解需求。这也是很多课程和教程把“从安装到 Skills 实战,再到多 Agent 协作”作为一条完整学习路径的原因。

本文围绕 Agent Skills 这条主线展开,前半部分讲清楚 Skill 是什么、它和 Tool、Task、Workflow 有什么区别,然后从环境准备开始,按“安装框架 -> 注册 Skill -> 跑通单 Agent -> 扩展到多 Agent 协作”的顺序完成一个最小可运行案例。后半部分重点讲常见报错和排查顺序,并给出一份可以直接用于团队协作模式检查的清单。读者学完后,可以自己把一个重复性任务封装成 Skill,也能在设计多 Agent 系统时判断哪些环节适合独立成 Agent、哪些应该交给 Skill 完成。

1. Agent Skills 是什么:从对话能力到可复用执行单元

1.1 为什么 Agent 需要 Skills

先看一个常见场景。用户在对话中要求 Agent “把这份 CSV 里的日期统一成 yyyy-MM-dd 格式,再统计每个分类的记录数”。如果每次都由模型从头看字段名、猜日期格式、现场写脚本,结果是:格式不稳定、偶尔写错正则、同一件事换一批数据又要重新调试。Agent Skills 解决的就是这个问题:把“清洗日期、聚合分类统计”这类高频任务写成标准化的 Skill,模型看到 Skill 描述后知道什么时候用、传什么参数、返回什么结构,底层逻辑则由固定代码执行,不依赖模型的临场发挥。

从模型视角看,Skill 就是一段增强提示词和一段可执行逻辑的组合。模型不需要知道实现细节,只需要根据任务匹配 Skill 描述并填好参数。从开发者视角看,Skill 是代码资产的载体,可以像函数库一样组织、复用、测试和版本管理。

1.2 Skills、Tools 与 Workflow 的边界

很多初学者会把 Agent Skill、Tool、Workflow 混在一起。这里用一张对比表说明边界:

维度ToolSkillWorkflow
粒度单个操作一组相关操作多个 Agent/系统协作流程
是否涉及多步通常单步内部可以多步显式编排多角色
模型参与程度模型决定是否调用模型读取描述后调用流程可预设,模型按节点执行
典型示例查询天气、发送邮件数据质量检查、文档生成需求分析 -> 编码 -> 测试 -> 发布
复用范围函数级任务级流程级

这四类不是互斥关系。实际项目中 Skill 内部会调用多个 Tool,Workflow 里的某个节点也可能是 Skill 的执行入口。理解边界的意义在于选型:如果任务需要固定代码保证结果稳定,封装成 Skill;如果任务需要控制和观察多个角色协作,使用 Workflow。

1.3 典型应用场景

适合封装成 Skill 的任务有几个共同特征:重复出现、结果可校验、步骤相对固定、对稳定性的要求高于创造性。例如:

  • 日志分析:输入日志文本,输出异常归类和时间线。
  • 数据清洗:统一日期格式、去重、字段映射。
  • 代码审查:按团队规范检查变量命名、安全风险和 API 使用方式。
  • 文档生成:根据代码结构生成接口说明或更新 README。
  • 运维巡检:收集系统指标、对比基线、输出风险项清单。

如果用一句话概括:Skill 是 Agent 的“职业技能”,对应人类工作中的岗位能力,而不是某一条工具命令。

2. 环境准备:先把学习和开发环境对齐

2.1 版本选择和运行环境要求

不同的 Agent 框架对 Skill 的实现方式不同。常见方案包括基于 Claude Skills 的 skill 目录约定、基于 LangGraph 的节点封装、基于 OpenAI Agents SDK 或 AutoGen 的自定义 Skill 模块。本文示例采用“Python 环境 + 一个通用 Agent 框架 + 自定义 Skill 目录”的方式,目的是把原理讲清楚,落地到具体框架时只需要替换注册接口。

学习环境建议:

  • Python 3.10 或以上,建议 3.11。
  • 操作系统:macOS、Linux 均可,Windows 需要保证路径和 shell 命令兼容。
  • 需要安装的依赖:openai、anthropic、langchain 或本项目选用的 Agent 框架。
  • 大模型 API:至少准备一个支持 Function Calling 或 Tool Use 的模型接口。

生产环境还需要额外考虑访问凭证管理(不要在代码里写死 API Key)、网络出口稳定性、日志采集和模型调用成本控制。

2.2 安装框架和依赖

以 Python 环境为例,先创建虚拟环境,避免依赖冲突:

python3 -m venv .venv source .venv/bin/activate pip install --upgrade pip

再安装 Agent 框架。如果使用 LangChain 系列,可以这样安装:

pip install langchain langchain-openai python-dotenv

如果使用 OpenAI Agents SDK,可以这样安装:

pip install openai-agents

这里要说明一点:框架版本变化很快,安装前先确认当前项目的依赖锁定文件,不建议直接pip install最新版本到生产项目。学习阶段可以用最新版本跑通,进入团队项目后建议用requirements.txtpyproject.toml锁定版本。

2.3 验证安装是否成功

安装完成后,先写一个最小调用,确认模型接口和框架能连通:

import os from dotenv import load_dotenv load_dotenv() from openai import OpenAI client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "请回复:技能装载正常"}] ) print(response.choices[0].message.content)

运行:

python check_api.py

预期输出是一句正常回复。这一步的检查点包括:API Key 是否配置、网络是否可以访问模型服务、模型名称是否在当前账号权限内。很多后续问题都源于这一步没有跑通,后面排查时会很被动。

3. 从零实现第一个 Agent Skill

3.1 Skill 目录结构与最小文件

多数 Skill 框架遵循“目录即 Skill”的约定。以 Claude Skills 风格为例,一个 Skill 目录内通常包含:

skills/ date_normalizer/ SKILL.md script.py requirements.txt

其中SKILL.md是模型的说明书,script.py是实际执行逻辑,requirements.txt是 Skill 自身的依赖。不是所有框架都强制用这三个文件,但保留这个结构有助于统一工程规范。

在学习环境中,这个目录可以放在项目根目录下,Agent 启动时通过配置加载。生产环境建议把 Skill 目录当作独立模块,纳入版本管理,并且为每个 Skill 单独配置权限边界。

3.2 SKILL.md 的作用

SKILL.md是模型判断“何时调用这个 Skill”的依据。它通常包含:

  • 名称:Skill 的标识。
  • 描述:说明 Skill 的功能边界和适用场景。
  • 输入参数:每个参数的类型、含义、默认值。
  • 输出格式:执行成功后返回什么字段。
  • 示例:一个最小输入输出对。
  • 限制:哪些情况不要使用该 Skill。

一个最小示例:

--- name: date_normalizer description: 将 CSV 或文本中的日期统一转换为 yyyy-MM-dd 格式。 参数说明: text: 包含日期字段的文本或 CSV date_column: 需要转换的列名,默认是第一列 输出: normalized_text: 转换后的文本 error: 如果失败返回错误信息 限制: 仅处理常见日期格式,不处理中文日期大写形式 --- 示例输入: 2024/01/05,2024-01-06,2024年1月7日 示例输出: 2024-01-05,2024-01-06,2024-01-07

关键点是:描述写得越清楚,模型越少做出错误调用。与其依赖模型自己猜参数含义,不如把边界和示例全部写清楚。

3.3 在 Agent 中注册 Skill

注册过程通常是把 Skill 目录路径交给框架的 Agent 配置。以 OpenAI Agents SDK 为例,可以在 Agent 的定义里挂载 Skill 列表:

from agents import Agent agent = Agent( name="DataAssistant", instructions="你是数据处理助手,请根据用户请求选择合适的 Skill 执行。", skills=[ "skills/date_normalizer", "skills/log_analyzer" ], )

这里skills参数在不同框架里名称和类型不同,有的框架使用load_skill("path")返回对象后再传入。意思是统一的:Agent 在启动时读取 Skill 描述,并在对话过程中决定是否调用。

3.4 执行脚本的设计

script.py是 Skill 真正的执行体。它接收模型解析出的参数,返回可序列化的结果。一个最小实现:

import json import sys def normalize_dates(text, date_column="1"): lines = text.strip().splitlines() result_lines = [] for line in lines: parts = line.split(",") for idx, part in enumerate(parts): part = part.strip() if idx == int(date_column) - 1 or date_column == "1": parts[idx] = part.replace("/", "-").replace("年", "-").replace("月", "-").replace("日", "") result_lines.append(",".join(parts)) return "\n".join(result_lines) if __name__ == "__main__": input_data = json.load(sys.stdin) output = { "normalized_text": normalize_dates( input_data.get("text", ""), input_data.get("date_column", "1") ), "error": None } print(json.dumps(output, ensure_ascii=False))

这个示例为了可读性只处理了最简格式,实际项目中建议引入pandas处理 CSV,并且针对日期解析失败做单独处理。脚本要遵守一个重要约定:输入从标准输入读取 JSON,输出写到标准输出 JSON,这样 Agent 框架可以稳定地传参和读取结果,不依赖临时文件。

3.5 运行验证

手动验证时,可以直接用管道测试:

echo '{"text":"2024/01/05,2024-01-06,2024年1月7日","date_column":"1"}' | python script.py

预期输出:

{"normalized_text": "2024-01-05,2024-01-06,2024-01-07", "error": null}

这个手动验证非常关键。它把 Skill 的逻辑测试和 Agent 集成测试分离开来:如果手动执行都失败,先修脚本;如果手动成功但 Agent 调用失败,问题在模型解析参数或注册配置,不在脚本本身。

4. Skills 实战:把重复任务封装成可复用能力

4.1 从需求到 Skill 的拆解方法

封装 Skill 前先完成三步拆解:

  1. 列出任务的所有步骤,确认是否稳定。如果步骤每次都不一样,不适合封装成固定 Skill。
  2. 定义输入和输出。输入尽量结构化,输出要能被后续步骤直接消费。
  3. 决定哪些步骤用代码完成,哪些步骤交给模型判断。安全性敏感的步骤必须用代码完成。

以“代码安全检查”为例,需求是:检查一段 Python 代码是否使用了evalexec或危险反序列化接口。这个任务适合用正则和 AST 静态扫描实现,不适合让模型自由判断。封装成 Skill 后,每次调用结果都一致,且不依赖模型幻觉。

4.2 一个完整 Skill 示例:CSV 汇总统计

下面给出一个稍微完整的 Skill 来展示“输入 -> 处理 -> 输出检查点”的完整闭环。

import json import sys import csv from io import StringIO from collections import Counter def summarize_csv(text, category_column): reader = csv.DictReader(StringIO(text)) counter = Counter() for row in reader: key = row.get(category_column, "unknown") counter[key] += 1 return [{"category": k, "count": v} for k, v in counter.items()] if __name__ == "__main__": data = json.load(sys.stdin) result = summarize_csv(data.get("text", ""), data.get("category_column", "")) print(json.dumps({"summary": result}, ensure_ascii=False))

对应 SKILL.md 里的描述要写清楚:

--- name: csv_summarize description: 对 CSV 数据按指定分类列统计记录数。 参数: text: CSV 文本内容,要求包含表头 category_column: 分类列名 输出: summary: [{category, count}] 限制: 不处理缺失分类值;如需忽略缺失项,预处理后再调用 ---

这个例子的价值不在于统计逻辑多复杂,而在于示范了“稳定代码 + 清晰描述”的组合方式。逻辑越固定,Skill 的可靠性越高。

4.3 参数设计与结果返回规范

参数设计直接影响模型调用成功率。推荐做到这几点:

  • 参数数量控制在 3 到 5 个以内,太多会让模型填错。
  • 每个参数给默认值,降低模型漏传导致失败的概率。
  • 返回结果使用 JSON,字段名保持稳定,便于下游解析。
  • 错误信息单独用error字段返回,不要把异常堆栈直接作为正常输出。

参数设计错误的表现通常是:模型生成了错误的 JSON、字段名不匹配、类型不对。出现这类问题首先检查 SKILL.md 中的参数表和示例,而不是改执行脚本。

5. 多 Agent 协作:让 Skills 在团队中生效

5.1 单一 Agent 的边界

单个 Agent 同时承担“理解意图、拆解任务、调用所有工具、总结输出”时,会在长任务和复杂上下文中逐步失控。典型表现是:任务步骤一多,模型开始忽略之前的约束;上下文过长,最早的信息被截断;多个工具结果混在一起,最终回答质量下降。多 Agent 协作的价值不是“多个模型一起工作”,而是把一个大任务拆成职责清晰的子任务,每个子任务由不同 Agent 处理,每个 Agent 只维护自己关注的那部分上下文。

5.2 规划者-执行者模式

最常见也最容易入手的是 planner-executor 模式。一个规划 Agent 负责理解用户目标,拆解成子任务,分配给执行 Agent;执行 Agent 各自配备独立 Skill 和上下文,完成子任务后把结果返回给规划 Agent 汇总。

planner_prompt = """ 你负责拆解用户需求并调度执行 Agent。 要求: 1. 将需求拆成不超过3个子任务。 2. 每个子任务明确指定执行 Agent 名称和需要的结果格式。 3. 如果需求不明确,先向用户确认,不要直接拆解。 """ executor_prompt = """ 你是数据处理执行 Agent。只能处理分配给自己的子任务。 处理时必须调用对应 Skill,不得自行编造结果。 完成后返回 JSON:{"result": ..., "skill_used": "skill名称"}。 """

这个模式适合大多数业务场景,因为它控制逻辑清晰,排查时容易定位到具体节点。

5.3 协作中的上下文传递

多 Agent 协作最常见的失败原因是上下文传递丢字段。规划 Agent 把任务文本传给执行 Agent,执行 Agent 处理后返回结果,但如果返回的结果缺少字段名,规划 Agent 就无法判断是否成功。建议在协作协议层固定以下内容:

  • 每个子任务有唯一 task_id。
  • 每个返回结果包含 task_id、status、result、error。
  • 规划 Agent 汇总前先检查 status,失败则重试或降级。

这个协议看起来简单,但很多生产事故恰恰是因为执行 Agent 只返回了“完成”两个字,规划 Agent 拿不到结构化结果。

5.4 一个最小多 Agent 协作示例

下面示例展示一个简化的协作调度逻辑:

def run_planner(user_request: str): tasks = planner_agent.plan(user_request) results = [] for task in tasks: worker = select_executor(task["agent"]) task_result = worker.run(task["objective"], task.get("params", {})) results.append({ "task_id": task["task_id"], "status": "success" if task_result.get("error") is None else "failed", "result": task_result }) if all(r["status"] == "success" for r in results): return final_agent.summarize(results) else: return {"status": "partial_failed", "details": results}

在实际项目里,planner_agent.planworker.run是核心抽象,可以替换成任何框架的 Agent 实例。验证方法是在每个子任务之间打印 task_id 和状态,观察是否有失败重试或数据错位。

6. 常见问题排查

6.1 Skill 不被加载

现象:用户请求命中 Skill 场景,但 Agent 没有触发调用,直接给出基于自身知识的回答。

可能原因:

  • Agent 配置里没有注册 Skill 路径。
  • SKILL.md 的描述太模糊,模型没有把输入与 Skill 关联起来。
  • 模型不支持 Tool Use,而框架依赖这个能力。

检查方式:在注册处打印实际加载的 Skill 名称和数量,手动向 Agent 发送一个与 SKILL.md 示例几乎相同的输入,观察是否触发。如果仍不触发,在描述中增加更明确的关键词和示例。

6.2 参数解析失败导致脚本报错

现象:Agent 调用了 Skill,但脚本输出乱码或直接报错。

可能原因:模型生成的参数 JSON 不合法,或字段名与 SKILL.md 不一致。

检查方式:在执行脚本入口打印原始 JSON,人工核对参数结构。解决方案是把参数解析部分做容错处理,例如默认值兜底、类型强转,并在错误信息中返回是哪个字段解析失败。

6.3 多 Agent 协作中结果互相覆盖

现象:两个执行 Agent 的结果写入同一个全局变量,最后的汇总结果出现串数据。

可能原因:执行结果没有做隔离,调度器把结果存入共享结构后,后续 Agent 又对其修改。

检查方式:为每个任务结果增加 task_id,并在写入汇总前深拷贝。推荐做法:执行 Agent 只返回纯 JSON,汇总逻辑只读不修改。

6.4 排查清单

问题现象可能原因检查方式处理建议
Skill 未触发Skill 未注册或描述不清检查配置日志和 Skill 数量完善 SKILL.md 的示例与关键词
脚本执行报错参数 JSON 格式错误打印入口原始输入增加参数容错和默认值
结果不准确执行逻辑没有适配实际数据手动调用脚本验证补测试用例,不使用模型修正逻辑
Agent 上下文截断最早期信息被覆盖查看 token 使用记录拆分子任务,减少上下文传递
多 Agent 结果串数据共享变量未隔离检查任务结果 task_id结果只读,深拷贝后再汇总

6.5 排查顺序建议

出现任何问题时按以下顺序排查:

  1. 确认输入数据格式正确。
  2. 确认 Skill 目录和文件路径正确。
  3. 确认模型支持 Tool Use。
  4. 确认参数解析和默认值兜底是否生效。
  5. 确认执行脚本的标准输入输出约定符合框架要求。
  6. 查看框架日志里的 intent 或 tool call 记录。
  7. 最后才考虑框架和版本兼容问题。

这套顺序能避免浪费时间去查框架问题,而实际原因往往在第 1 到第 3 步。

7. 学习路径、生产落地与实践建议

7.1 学习环境与生产环境的差异

学习阶段的目标是跑通最小闭环,可以接受把 API Key 写在.env、用本地文件保存 Skill、日志只打印到控制台。但进入生产环境后,必须补齐几件事:

  • 配置外置化:Skill 路径、模型名称、API 地址通过环境变量或配置中心下发。
  • 凭证安全:使用密钥管理服务,不把 Key 写入代码仓库。
  • 日志和追踪:每个 Skill 调用记录输入摘要、输出摘要、耗时和错误信息,方便回溯。
  • 限流和成本控制:设置单次任务最大调用次数和模型 token 上限。
  • 版本回滚:Skill 目录纳入 Git,发布前打标签,出问题时快速回退。

学习环境可以直接写脚本逐个调试,生产环境建议把 Skill 调用封装成带有超时、重试和熔断的服务接口。

7.2 最佳实践清单

以下清单可以直接复制到团队文档中使用:

  • Skill 的职责单一:一个 Skill 只做一件事,如果一个 Skill 描述里出现多个“并且”,考虑拆分。
  • 描述先于代码:先写 SKILL.md,再写实现,确保模型能理解它将要调用的东西。
  • 固定参数数量:参数超过 5 个时,考虑把参数组合成对象字段。
  • 结果必须结构化:所有 Skill 返回 JSON,字段命名稳定。
  • 手动验证先行:任何 Skill 先脱离 Agent 单独运行通过,再接入 Agent。
  • 日志记录调用决策:记录模型选择了哪个 Skill、为什么选择,便于后续优化描述。
  • 为每个 Skill 准备至少一个测试用例,覆盖成功路径和失败路径。

7.3 独立验证 Skill 与 Agent 的构建顺序

对新手来说,最实用的练习顺序是:

  1. 先实现一个不需要 Agent 参与的脚本,例如 CSV 统计。
  2. 手动用 JSON 管道验证脚本输入输出。
  3. 编写 SKILL.md,把参数和示例写完整。
  4. 将 Skill 注册进 Agent,用同一份输入测试触发。
  5. 增加第二个 Skill,观察 Agent 是否能区分选择。
  6. 最后引入规划者和执行者两个角色,做最小多 Agent 协作。

如果第 4 步已经能稳定触发,说明你已经理解了 Skill 的核心机制。不要急着做大量并行 Agent,先把单个 Skill 的可靠性做扎实。

7.4 需要继续深入的知识点

如果继续往工程方向深入,可以按顺序研究:

  • 函数调用(Function Calling)与 Skill 的触发链路。
  • 上下文窗口管理:如何压缩历史、如何只保留必要任务信息。
  • RAG 与 Skill 的组合:检索到资料后,用 Skill 做固定处理。
  • 不同框架的 Skill 规范差异:Claude Skills、LangGraph、OpenAI Agents 的目录约定和注册方式。
  • 多 Agent 模式扩展:除了 planner-executor,还有 reviewer、router、hierarchical 等模式各自的适用场景。

每一块都可以独立成专题。但无论研究到哪一层,核心判断不变:Agent 的稳定性来自边界清晰的能力封装,Skill 就是这种封装的载体。先把一个 Skill 做扎实,再考虑复杂的编排,这是少走弯路最有效的路径。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询