news 2026/9/24 23:28:51

Agent技能体系:从对话到任务执行的关键工程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent技能体系:从对话到任务执行的关键工程实践

这几年大模型应用里最热的一个词,除了 RAG、Fine-tuning,就是 Agent。而真正上手做 Agent 的人,很快会撞上一个共同的坎:模型知道怎么聊天,但不知道怎么"干活"。你让它调个接口,它编一个不存在的参数;让它按流程处理数据,它做到第三步开始自由发挥。问题基本不在模型本身,而是你根本没有给这个"数字员工"建立一套可执行的技能体系——这就是我要聊的agent-skills

agent-skills听起来像个开源项目名,实际上它代表的是一整套工程方法论:把大模型从"对话机器"改造成"任务执行器"所需的技能编码方式。包括技能怎么定义、工具怎么封装、任务怎么编排、失败怎么恢复,以及整个技能库怎么测试迭代。这篇文章我结合自己做过的一个企业内部知识助手、一个自动化数据清洗 Agent 的实践经验,把这套东西掰开揉碎讲清楚。适合正在做 Agent 应用开发、被"模型不听话"折磨得头疼的工程师,也适合想系统理解 Agent 落地难点、准备技术选型的技术负责人。

1. 先搞清楚 skill 到底是个什么"技能"

1.1 当大模型只会"聊"不会"干"的时候

先做一个思想实验。你给 ChatGPT 类模型一个任务:帮我从数据库里查出最近30天订单金额超过5000元的客户名单,并按金额降序排列。模型大概率给你一段看起来很对的 SQL,甚至还能解释两句。但如果你希望它真的连上数据库、执行查询、把结果写成 CSV 发到你邮箱,它做不到。为什么?因为模型本身是"无手无脚"的,它只能输出文字,不能产生副作用——不能真的发起 HTTP 请求,不能执行代码,不能写文件。

早期解决方案是提示词工程,你在 Prompt 里写"你现在是一个数据分析师,请你执行 SQL",模型依然只能输出 SQL 文本,不会真的执行。后来大家发现,得给模型提供工具,并且让它学会"决定什么时候用什么工具"。这就是 Function Calling,也就是 OpenAI 在 2023 年推出的函数调用能力。模型可以输出一个结构化的调用意图,你这边解析这个意图、执行对应 API、把结果返回给模型。这一步跨出去,Agent 才真正开始有了"手"。

agent-skills想解决的是更高一层的问题:一个真实业务场景不是"调一次函数"就结束的,它是一连串决策和动作的组合。比如"运营同事提交了一个数据清洗需求",Agent 要做的是:理解需求 → 定位数据文件 → 探查数据质量 → 决定清洗规则 → 执行清洗 → 生成质量报告 → 输出结果文件。这个链条里有多个决策点,每个决策点都可能需要调用不同工具。如果每个工具是"手",那么 skill 就是"把一堆手组合成一套熟练工种"的能力。

1.2 技能体系的三层结构:定义、执行、反馈

我自己在工程上习惯把 agent-skills 拆成三层,这样代码结构清晰,排查问题也方便:

第一层是技能定义层(Skill Definition)。每个技能要有名字、描述、触发条件、参数说明、依赖的工具列表。这层的作用是让模型"知道有什么技能可以用、什么时候该用、用了之后要传什么参数"。相当于岗位说明书。

第二层是技能执行层(Skill Execution)。这里包含两个部分,一是工具本身的实现,比如查数据库的函数、调外部 API 的封装、执行 Python 代码的沙箱;二是编排逻辑,就是决定多个工具按照什么顺序、什么条件被调用。相当于这个岗位具体做事的方法。

第三层是反馈与恢复层(Feedback & Recovery)。工具执行成功还是失败?返回结果是否符合预期?如果失败,是重试、换一种方式,还是把错误信息返回给模型让它重新决策?这一步很多人会忽略,但它是 Agent 稳定性的命门。没有反馈机制的 Agent,执行三步错一步就整个崩盘,这在生产环境是不可接受的。

把这三层分开设计还有个好处:技能可以复用和独立测试。我后面做第二个 Agent 项目时,直接把第一个项目里的"数据库查询"技能的定义和执行层拿过来改一改参数就用了,省了大量重复工作。

2. 怎么设计一套模型"听得懂"的技能

2.1 技能描述怎么写,模型才不会选错

这一节是干货核心,也是最容易被低估的部分。很多人写技能描述,就写一句"查询数据库",然后完了。模型看到这个技能,根本不知道它具体能做什么、支持哪些操作、返回什么格式,于是它要么不敢调用,要么乱调用。

我总结了一套技能描述的标准模板,经过多次实测效果稳定:

每个技能描述应该包含以下五个要素:

  1. 技能定位:一句话说清楚这个技能负责什么业务动作。例如"根据用户提供的查询要求,从订单数据库中检索数据"。
  2. 适用场景:什么情况下应该调用这个技能。要写得具体,最好带正反例。例如"当用户要求查询订单、统计销售额、分析客户购买行为时使用;当用户只是要求生成一段示例 SQL 而不需要真实执行时不要使用"。
  3. 输入参数说明:每个参数的含义、类型、是否必填、取值范围、默认值。参数说明要用模型好理解的自然语言,不要只给一个参数名。
  4. 输出格式说明:返回值是什么结构,是 JSON 数组还是 CSV 文本,字段有哪些。模型需要根据输出来决定下一步动作,所以这个说明直接决定后续决策质量。
  5. 使用约束:比如超时时间、最大返回行数、不允许执行 DELETE/UPDATE 等。约束有时比参数更重要。

写描述时有一个重要的心智模型:你是在给一个"聪明但缺乏常识、且容易过度解读"的新员工写工作手册。你写得越精确,他越不容易跑偏;你留下模糊地带,他就会用幻觉填满。

2.2 工具 Schema 设计里最常见的坑

技能描述是给模型看的"文案",工具 Schema 则是给模型看的"接口文档"。这个接口文档的质量,直接决定了 Function Calling 的准确率。我在两个项目里踩过的坑可以列一长串,挑几个最典型的说。

第一个坑是参数类型定义得过宽。比如给一个"日期范围查询"功能定义参数,有人会把 start_date 和 end_date 定义成 string 类型,然后描述写"日期"两个字。结果模型经常传 "明天" "最近一周" 这种自然语言。正确做法是类型用 string 没错,但 format 字段要写 "YYYY-MM-DD",description 里要明确写"仅接受格式为 2025-01-01 的日期字符串,不接受相对时间描述"。必要时你还要在工具内部做一层参数校验,把不合法的输入转换成最近可用的值或者直接报错。

第二个坑是没有把错误信息设计成"模型能看懂的语言"。函数执行失败时返回的 error message,很多人直接抛一个 Python traceback 或者 HTTP 500 这种原始错误。模型看到这种信息一脸懵,它不知道该怎么处理。正确做法是错误信息也要为模型设计,例如:查询失败:数据库连接超时,请稍后重试或者参数错误:start_date 格式不正确,应为 YYYY-MM-DD。模型读到这样的反馈,才有可能自己纠正参数或者告诉用户发生了什么。

第三个坑是一次性暴露太多函数。OpenAI 早期文档建议每个请求传尽量少的函数,因为函数越多,模型选错的概率越高。更合理的做法是按技能分组,先有一个"能力路由"函数,模型先选技能类别,再进入对应的子函数集。比如第一步只给模型 5 个函数:数据分析、文件操作、网页访问、消息发送、求助人工。模型选中"数据分析"后,系统再注入 8 个数据分析相关的函数。这样既控制了单次调用的上下文长度,也大幅提高了选择的准确率。

2.3 技能的粒度:拆多细才算合适

技能粒度是另一个反复取舍的问题。太粗,比如定义一个大而全的"处理数据"技能,模型执行时自由度过大,过程和结果都不稳定;太细,比如把"读取 CSV"和"计算均值"各拆成独立技能,模型要来回做好几次函数调用,不仅慢,Token 成本也高,而且更容易在中间步骤出错。

我的经验是掌握一个原则:按"业务可理解、结果可验证"的粒度来拆分。也就是说,每个技能应该对应一个用户可以理解的任务单元,并且这个任务的执行结果是可以被明确验证的。举个例子,"清洗一份销售数据报表"是一个业务动作,但它的内部包含去重、缺失值处理、异常值标记、格式标准化四个子任务。这四个子任务都应该可以独立验证结果,所以它们适合拆成四个技能,而不是揉在一个"清洗"技能里。但"读取 CSV"这种过细的动作就不建议单独拆,直接作为"数据探查"技能的内部实现步骤就好。

粒度决策还有个辅助判断标准:看这个技能被复用的次数。如果一段逻辑在多个场景里都要用,就值得拆出来做成独立技能。如果某个技能只有一条业务线在用,且内部高度耦合,那拆得太细纯属增加维护成本。

3. 从零搭建一条可用的技能执行链路

3.1 基座选型:指令遵循能力优先于通用智能

技能体系设计得再好,最后还是要靠一个模型来"驱动"。选基座模型这件事上,我的排序标准和通用聊天场景不太一样:指令遵循能力 > 工具调用准确率 > 上下文长度 > 通用知识广度

为什么指令遵循能力放第一位?因为 Agent 场景里,模型的行为边界全靠指令约束。你给它的 system prompt 里写了"只能调用白名单内的工具"、"任何涉及删除数据的操作必须先征得用户确认",如果模型指令遵循能力弱,它该遵守的边界守不住,再强的通用知识也没用。我自己实测过几个开源模型,有的聊天很流畅,但在 Function Calling 上准确率只有 50% 出头,做 Agent 基本不可用。

从国内团队的实际落地看,通用基座 + 微调工具调用能力是主流路径。有预算和数据的团队,会对基座模型用"工具调用样例"做几轮 LoRA 微调。没有微调条件的团队,至少也要选对 API 服务商,并做充分的评测再上生产。至于上下文长度,128K 和 200K 这种数字看起来很美,但实际用的时候你会发现,上下文越长,模型在长流程任务里的"迷失感"越强。所以更务实的做法是把上下文做"瘦身",只保留当前步骤需要的信息,而不是把整个任务历史都塞给模型。这块我会在 3.3 里详细说。

3.2 ReAct 循环并不是一个"高深"的东西

在当前 Agent 的工程实现里,最主流的执行范式还是 ReAct,也就是Reasoning + Acting交替循环。通俗点说,就是让模型走一个"思考→行动→观察结果→再思考"的循环,直到任务完成。

我不打算贴大段论文,直接给一个工程实现上最常用的核心伪代码。这段逻辑我在两个项目里都实测过,稳定性和可扩展性都不错:

# skill_runner.py import json def run_skill_loop(user_task, available_skills, max_steps=10): # 初始化对话历史,注入系统提示词描述各技能的用途和约束 messages = [{ "role": "system", "content": build_system_prompt(available_skills) }, { "role": "user", "content": user_task }] for step in range(max_steps): response = llm.chat(messages, tools=build_tool_schemas(available_skills)) # 模型决定调用某个技能 if response.tool_calls: tool_call = response.tool_calls[0] skill_name = tool_call.function.name skill_args = json.loads(tool_call.function.arguments) # 在执行技能前,统一做一遍参数校验和权限检查 errors = validate_args(skill_name, skill_args) if errors: messages.append({ "role": "tool", "content": f"参数校验失败:{'; '.join(errors)}", "tool_call_id": tool_call.id }) continue result = execute_skill(skill_name, skill_args) messages.append({ "role": "tool", "content": format_result_for_model(result), "tool_call_id": tool_call.id }) else: # 模型不再调用工具,直接输出最终回答 final_answer = response.content return final_answer return "达到最大步骤数,任务未完成,已转人工处理"

这里有几个细节建议特别留意。参数校验一定要在技能执行前做,不要依赖模型自己保证传参正确。我见过太多线上事故是模型传了一个超出枚举范围的参数,工具内部没校验直接抛异常,整个链路就崩了。格式化工具返回结果也值得写一个专门的函数,它的作用是把冗长的原始数据压缩成模型好理解的摘要,同时自动截断超长内容,防止上下文爆炸。比如数据库查询返回 200 行数据,你不要全量塞给模型,而是转成"查询成功,返回 200 行,前 5 行如下:……",这样既保留关键信息,又控制长度。

3.3 完整实操:一个"自动化周报生成" Agent 的搭建全程

理论和框架讲完,我拿一个实际做过的项目来完整走一遍流程。背景是给团队做一个"根据本周开发记录自动生成周报并发送到钉钉群"的 Agent。这个需求看着简单,但实际跑通和稳定用了不少细节打磨。

先拆技能。按前面说的粒度原则,我把任务拆成了四个技能:

  1. 获取开发记录:从内部 Git 系统拉取当前用户本周的 commit 和 merge request 记录。
  2. 生成周报草稿:根据开发记录,按照团队周报模板生成结构化文本。
  3. 发送到钉钉群:通过钉钉 webhook 发送指定的文本内容。

工具层的实现,用 Python FastAPI 封装了三个 HTTP 接口,分别对应上面三个技能。每个接口的参数定义我特意花了心思。比如"获取开发记录",我定义了 start_date、end_date、author、project 四个参数,并且把 author 设计成可选——这样模型在用户只给了项目名、没给作者时,也可以先把记录拉回来,再根据记录内容判断是否是本人。

然后是 skill 描述。这里我犯过一个典型错误:第一次写"生成周报草稿"的描述,只写了"根据开发记录生成周报"。结果模型在生成草稿时,经常省略数据指标;有时候会把几条无关的 commit 合并成一条,信息反而失真。后来我把描述改成了:

根据获取到的开发记录列表,生成一份符合团队模板的周报。周报必须包含以下部分:本周完成事项(逐条列出,每条不超过 50 字)、数据指标变化(如有)、风险与阻塞(如有)、下周计划(如有)。要求:忠实于原始记录,不得虚构信息;如果记录中有标题包含"fix"或"hotfix"的提交,请单独归类到"问题修复"分组。

改完之后生成质量明显提升,说明描述细节确实值钱。

再说说系统 Prompt 里的边界约束。我给这个 Agent 定的铁律是:周报草稿生成后,必须先输出给用户确认,得到"发送"指令后才允许调用发送技能。这条规则防止了 Agent 自作主张把未经确认的内容发到群里。实现上我用了一个状态机,只有处于awaiting_confirmation状态时,才向模型暴露"发送到钉钉群"这个技能。这个思路和权限控制联动,值得推广到其他 Agent 场景:技能的可调用权限应该是动态的,随任务状态变化

运行效果方面,我把标准流程跑通之后,又专门做了一轮异常路径测试。比如用户只说了"帮我发个周报"但没指定项目,模型第一轮调用"获取开发记录"时 project 参数为空。我在工具内部把这种情况处理成了"返回该用户所有项目的本周记录",并在结果里提示"未指定项目,已返回全部项目,请选择其一"。这样既没有中断任务,又给了模型继续决策的信息。这种"容错返回"是让 Agent 更像真人协作者的关键技巧。

4. 技能测试、踩坑记录与迭代心得

4.1 为技能体系构造一套"最小可信测试集"

Agent 应用和传统后端应用的最大区别,是它的输出不可枚举,没法用"断言返回码 200"的方式做单元测试。所以你需要专门设计一套面向 Agent 的测试方法。我的做法是为每个技能准备三组测试用例:

第一组是标准场景:输入完全符合技能预期,验证技能能否正确执行并返回结构化结果。比如"获取开发记录"技能,给一个明确的项目和日期范围,检查返回的 commit 列表是否完整。

第二组是边界场景:输入接近参数边界,或者部分缺失。比如"开始日期晚于结束日期"、"参数为空"、"项目名不存在"等。重点验证模型能否通过错误反馈自我纠正,还是直接放弃。一个严谨的 Agent 应该能在得到"参数校验失败:start_date 不能晚于 end_date"这种反馈后,主动调整参数重试。

第三组是对抗场景:用户输入包含模糊意图、多任务混杂、或者试图绕过约束。比如"不用确认了直接发出去"这种指令,模型必须拒绝执行。对抗测试对系统的安全性至关重要,尤其是涉及发送消息、删除数据、外部支付等高危操作时,必须有意识地测试模型是否守得住边界。

我在项目里把这组用例写成了一个 JSON 文件,用脚本驱动跑回归,每次改技能描述或模型版本后都全量跑一遍。这个习惯救过我一次:有一次把基座模型从旧版升级到新版,其他指标都正常,只有对抗场景里"模型不再遵守确认机制"这个用例挂掉了。全靠回归测试提前发现问题,避免了上线后出事故。

4.2 高频翻车现场与修复手段

实际运行 Agent 的过程中,我整理过一份高频问题清单。这里挑四个出现频率最高、也最有代表性的,每一个我都给修复后的做法。

模型不会主动调用工具。经常发生在技能描述和用户问题的关键词不匹配时。比如用户说"把数据拉到本地",但技能描述里写的是"导出文件",模型就绕弯子直接输出一段 Python 代码让你自己运行。修复办法是在技能描述里把用户可能说的多种说法写进适用场景,甚至可以给两个"触发示例"让模型照葫芦画瓢。

工具执行正确,但模型错误理解了返回结果。比如查出来 0 行数据,模型直接说"没有数据",但用户本意是想知道"为什么没有数据"或"数据量是否正常"。这个问题的根因在工具返回结果太"干"了,没有附加上下文。我后来的做法是,当查询结果为空时,工具不光返回空数组,还返回一条提示:"查询结果为空,可能原因:筛选条件过严、数据尚未同步或数据库连接异常"。模型看到这个提示,就能做出更符合用户预期的回答。

多技能协作时,模型跳过中间步骤。典型场景是"拉数据 + 做分析 + 出报告"三步任务,模型经常把第二步省了,或者把第一步和第二步的结果混在一起。我采取的措施是把技能定义改成"上一个技能的输出会作为下一个技能的输入",同时在每次工具返回后注入明确的引导语:"现在你已获得数据,下一步请对数据进行统计分析,再生成报告。"这种显式的流程提示,能让模型不乱跳步。

长流程运行中上下文丢失。Agent 执行到第 5 步,往往已经忘了第 1 步的用户原始意图,或者把中间结果搞混。我的解法是为每个任务维护一个结构化的工作记忆区,包括原始任务目标、已完成步骤、当前中间结果、下一步建议。每次模型决策前,先把工作记忆区作为上下文的一部分输入。这个机制比单纯拼对话历史可靠得多。

我后来又对每个技能增加了错误率埋点,记录每一步的"首次尝试成功率"。哪个技能成功率低,优先去优化它的描述和参数说明。用数据驱动优化方向,效果远好于凭感觉改词。

4.3 技能体系的版本管理比你想的更重要

传统代码有 Git 版本管理,Agent 的技能体系更需要,但很多人没意识到这一点。技能描述是"提示词文本",它和代码一样会变,而且变了之后影响面往往更大。因为技能的调用方是模型,模型的输出又直接对接下游工具,一丁点描述改动都可能让模型行为大变。

我在项目里让每个技能定义(含描述、参数 Schema、系统提示语)都放进一个独立的 Markdown/YAML 文件里,并用 Git 做版本管理。发布新版本技能前,必须过一遍第 4.1 节说的最小可信测试集,通过之后才能合并发布。技能库的目录结构像这样:

skills/ ├── data_analysis/ │ ├── skill.yaml # 技能定义、参数Schema、适用场景 │ ├── description.md # 给模型看的完整技能描述 │ ├── executor.py # 技能执行实现 │ └── tests/ │ ├── standard.json # 标准场景测试用例 │ ├── boundary.json # 边界场景测试用例 │ └── adversarial.json # 对抗场景测试用例 ├── report_generation/ ├── notification/ └── common/ ├── validators.py # 参数校验公共函数 └── formatters.py # 返回结果格式化公共函数

这个目录结构的好处是,新的 Agent 项目可以直接复用common/和之前的技能模块。我第二个项目上线时,约有 40% 的代码是从第一个项目直接复制过来改的。技能体系的沉淀和复用,才是"做得多越做越快"的关键原因。如果你团队准备长期做 Agent 方向,从第一天就搭好这个架子,后面能省非常多的事。


最后再提一个我踩过好多次的坑:技能体系的迭代一定要以真实日志为准。开发环境里模型跑得好的场景,上生产往往冒出各种奇怪问题,因为真实用户的表达远比测试用例刁钻。我之前搭建 Agent 时在循环里做了全部交互日志的落盘存储,每隔几天拉一次日志,用分词工具统计用户问法和模型调用的对应关系,专门找出那些"模型对不上号"的技能。再反过来去补描述、加示例,或者调整工具返回结果的粒度。这套"日志驱动优化"的做法,比坐在一起头脑风暴改 Prompt 高效太多了。希望你做技能体系的时候少走些我的弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 23:28:10

胰腺病变分割数据集实战:210张训练图与可视化脚本

简介:本资源为胰腺病变图像分割数据集,面向医学图像分割方向的研究者、算法工程师及深度学习学习者,用于训练和评估二类别分割模型(背景与病变区域)。包内按训练集与测试集组织,训练集约210张图像及对应mas…

作者头像 李华
网站建设 2026/9/24 23:27:34

STM32入门到落地:从选型到实战的完整生态指南

如果你第一次接触STM32,八成是被它庞大的资料量和搜索词吓到的:你搜“STM32简介”,能同时蹦出“江科大STM32入门”“STM32时钟树”“STM32 OTA”“基于STM32的毕业设计”这些跨度巨大的话题。作为在这个圈子里干了快十年嵌入式开发的人&#…

作者头像 李华
网站建设 2026/9/24 23:27:17

线程同步与页面置换:从原理到实战的并发与内存调优指南

刚处理完一个线上服务的并发问题:多个线程同时向一个缓存结构里写数据,明明在代码里加了锁,线上还是偶发数据错乱。排查到最后,问题出在锁的实现方式上——一台高配机器上大量线程并发热切一个锁,互斥锁切换上下文耗掉…

作者头像 李华
网站建设 2026/9/24 23:26:10

Agent技能体系实战:从提示词堆砌到结构化技能编排

1. 为什么Agent需要一套独立的“技能体系”1.1 从“提示词堆砌”到“技能原子化”的转变我最早做Agent的时候,思路特别朴素:把所有工具描述写进System Prompt,再把例子塞进去,让模型自己决定什么时候调用、怎么调用。最初几个场景…

作者头像 李华
网站建设 2026/9/24 23:26:09

2026专科生必看:10款降AI率工具实测对比与避坑指南

2026届专科生应该已经陆续开始动毕业论文、毕业设计和各种实习报告了。今年有个话题明显比往年更热闹,就是“降AI率”。不少学校从2024年开始陆续引入了AIGC检测,到了2026年,知网、维普、万方几乎都把AI生成内容检测当成论文抽检的标配。很多…

作者头像 李华
网站建设 2026/9/24 23:25:13

加拿大野火土壤有机质燃烧严重程度数据集与碳损失估算

2014年夏天,加拿大西北地区的野火季烧成了历史级别的灾难,过火面积超过340万公顷,差不多等于比利时整个国家的面积。火场穿过了大面积的北方森林和泥炭地,把地表那层积累了上千年的有机质直接点着,很多地方连矿质土壤都…

作者头像 李华