从零构建AI智能体技能:Agent Skills的设计与实现指南
1. 先搞清楚“Agent Skills”到底在解决什么问题如果你最近在关注AI应用开发尤其是想构建能自主调用工具、处理复杂流程的智能体Agent那么“Agent Skills”这个概念大概率已经出现在你的视野里。它不是什么全新的底层模型而是一套关于如何设计、实现和管理智能体核心能力的工程化方法和最佳实践。简单说它解决的是“如何让一个AI智能体稳定、可靠地完成特定任务”的问题比如让一个客服Agent能查订单、改地址、退换货或者让一个数据分析Agent能连接数据库、跑查询、生成图表。很多人容易把“Agent Skills”和“Agent Tools”混为一谈。根据我的经验可以这么理解Tools工具是Agent能用的“锤子”和“螺丝刀”比如一个搜索API、一个计算器函数而Skills技能是Agent使用这些工具完成一个完整任务的“手艺”和“流程”。例如“处理用户退货”是一个Skill它内部可能需要按顺序调用“查询订单详情”、“验证退货政策”、“生成退货标签”等多个Tools。只给Agent一堆Tools它可能不知道何时、以何种顺序使用而设计良好的Skills则定义了任务的目标、步骤、异常处理和结果验证。当前Anthropic、OpenAI等公司都在推动其模型更好地与外部工具和系统集成。所以围绕“Agent Skills”的教程和框架热度很高。但别被“天花板”、“保姆级”这类词唬住核心不是看哪个教程最全而是看它能否帮你建立起从单点工具调用到完整业务流程的落地能力。这篇文章我会结合常见的实践拆解从理解、设计到实现一个Agent Skill的完整路径重点放在可复现的步骤和实际踩过的坑上。2. 环境准备不只是安装库更是厘清边界在动手写代码之前先花点时间把环境和概念边界理清楚能避免后面很多“跑不通”的困惑。这里不依赖任何特定的“保姆教程”课件我们基于通用的开发逻辑来准备。2.1 核心组件与依赖要构建和测试Agent Skills你通常需要以下几个部分大语言模型LLMAPI或本地部署这是Agent的“大脑”。你可以使用Anthropic的Claude系列模型通过其官方API或者其他兼容OpenAI API格式的模型如GPT系列、国内的一些合规API服务。关键点确保你的API密钥有效并且网络环境能够稳定访问对应的服务端点。如果遇到类似“unable to connect to anthropic services”的错误第一步永远是检查网络连通性、API密钥和账户状态。开发框架或SDK为了更方便地构建Agent你可以选择成熟的框架如LangChain、LlamaIndex或者直接使用模型提供商提供的SDK如anthropicPython库。对于新手我建议从LangChain开始它的抽象层次较高社区案例丰富。工具Tools定义你需要用代码定义Agent可以调用的具体工具。一个工具通常是一个Python函数有明确的输入参数、处理逻辑和输出。技能Skills编排逻辑这部分是核心你需要用代码或某些框架提供的DSL来描述一个Skill的流程如何理解用户意图、按什么顺序调用哪些工具、如何处理中间结果和异常。基础环境配置示例假设我们使用Python和LangChain并计划通过Anthropic API调用Claude模型。# 创建虚拟环境推荐 python -m venv agent_skills_env source agent_skills_env/bin/activate # Linux/macOS # agent_skills_env\Scripts\activate # Windows # 安装核心依赖 pip install langchain langchain-anthropic # LangChain及Anthropic集成 pip install python-dotenv # 用于管理环境变量2.2 关键概念区分Skills vs. Tools vs. MCP在搜索材料里你可能还看到了“MCP”Model Context Protocol。这里快速澄清一下避免混淆Tools最原子化的操作单元。就是一个函数输入一些参数返回一个结果。例如get_weather(city: str) - str。Skills更高层次的任务单元。它封装了完成一个复杂目标所需的一系列决策和工具调用序列。一个Skill内部可能会根据条件判断动态选择调用不同的Tools。例如handle_customer_complaint这个Skill可能会先后调用get_order_history、classify_issue、escalate_to_supervisor等Tools。MCP这是一个协议由Anthropic提出旨在标准化模型如Claude与外部工具、数据源之间的通信方式。你可以把它想象成一套预先定义好的“插头插座”标准。遵循MCP协议来暴露你的Tools可以让Claude等模型更容易、更安全地发现和使用它们。MCP是实现Tools的一种方式而Skills是使用Tools的组织形式。对于初学者我建议先跳过MCP专注于用LangChain等框架的标准方式来定义Tools和编排Skills这样理解成本更低更容易跑通第一个例子。3. 从零构建你的第一个Agent Skill我们从一个具体的场景开始构建一个“旅行助手”Agent并赋予它一个book_flight预订航班的Skill。这个Skill需要查询航班信息调用一个模拟的查询工具并根据用户偏好做决定。3.1 第一步定义工具Tools首先我们模拟一个航班查询工具。在真实场景中这里会连接到一个真实的航班API。# tools.py from langchain.tools import tool from typing import List, Dict tool def search_flights(departure: str, destination: str, date: str) - List[Dict]: 根据出发地、目的地和日期搜索航班。 返回一个航班列表每个航班包含航班号、价格、起飞时间、航空公司等信息。 # 这里是模拟数据。真实情况应调用外部API。 print(f[工具调用] 正在搜索从{departure}到{destination}日期为{date}的航班...) mock_flights [ {flight_no: CA123, airline: Air China, departure_time: 08:00, price: 1200}, {flight_no: MU456, airline: China Eastern, departure_time: 14:30, price: 950}, {flight_no: CZ789, airline: China Southern, departure_time: 20:15, price: 1100}, ] return mock_flights tool def book_flight_ticket(flight_no: str, passenger: str) - str: 预订指定航班号的机票。 返回预订确认号。 print(f[工具调用] 正在为乘客{passenger}预订航班{flight_no}...) # 模拟预订逻辑 confirmation fCONF-{flight_no}-{passenger[:3].upper()}-2024 return f预订成功确认号{confirmation}关键点使用tool装饰器将普通函数转换为LangChain能识别的Tool。文档字符串内的内容非常重要LLM会依靠它来理解这个工具的用途和参数。3.2 第二步创建Agent并绑定工具接下来我们初始化LLM并将定义好的工具提供给Agent。# agent_setup.py import os from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_anthropic import ChatAnthropic from langchain.prompts import ChatPromptTemplate from tools import search_flights, book_flight_ticket # 1. 设置API密钥请从环境变量读取不要硬编码 os.environ[ANTHROPIC_API_KEY] your_anthropic_api_key_here # 替换为你的密钥或使用dotenv加载 # 2. 初始化模型 llm ChatAnthropic(modelclaude-3-haiku-20240307, temperature0) # 选用Haiku模型速度快成本低 # 3. 准备工具列表 tools [search_flights, book_flight_ticket] # 4. 设计提示词Prompt告诉Agent它的角色和可用工具 prompt ChatPromptTemplate.from_messages([ (system, 你是一个专业的旅行助手。请根据用户的需求使用提供的工具来帮助他们。 你可以使用以下工具 {tools} 使用工具时请确保参数正确。 如果用户的需求不明确请主动询问澄清。 最终请给出清晰、完整的答复。), (placeholder, {chat_history}), # 用于多轮对话历史 (human, {input}), # 用户当前输入 (placeholder, {agent_scratchpad}), # Agent思考过程占位符 ]) # 5. 创建Agent agent create_tool_calling_agent(llmllm, toolstools, promptprompt) # 6. 创建Agent执行器 agent_executor AgentExecutor(agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue)关键点verboseTrue会在控制台输出详细的推理和工具调用过程对调试至关重要。handle_parsing_errorsTrue能避免因为Agent输出格式偶尔不符合预期而导致整个流程崩溃它会尝试让Agent重试。3.3 第三步测试基础工具调用在构建复杂Skill之前先确保Agent能正确调用单个工具。# test_basic.py from agent_setup import agent_executor # 测试简单查询 result agent_executor.invoke({input: 帮我查一下明天从北京到上海的航班}) print(Agent回复, result[output])运行这个测试你应该能在控制台看到类似以下的输出这表明Agent正确理解了意图并调用了search_flights工具 进入新的AgentExecutor链... 我需要搜索从北京到上海的航班。用户没有指定具体日期但说了“明天”我需要获取明天的日期并调用搜索工具。 动作search_flights 动作输入{departure: 北京, destination: 上海, date: 2024-05-28} # 假设明天是2024-05-28 [工具调用] 正在搜索从北京到上海日期为2024-05-28的航班... 观察 [{flight_no: CA123, airline: Air China, ...}, ...] 思考我找到了3个航班。现在需要把这些信息清晰地告诉用户。 动作最终答案 动作输入我为您找到了明天2024-05-28从北京飞往上海的3个航班1. 国航CA12308:00起飞价格1200元... 链结束。 Agent回复 我为您找到了明天2024-05-28从北京飞往上海的3个航班...3.4 第四步设计并实现一个完整Skill现在我们要实现book_flight这个Skill。它不是一个单独的工具而是一个引导Agent完成“查询-选择-预订”流程的指令集。在LangChain中我们可以通过精心设计的系统提示词System Prompt来“教”Agent掌握这个Skill。我们修改之前的系统提示词使其更具引导性# skill_prompt.py from langchain.prompts import ChatPromptTemplate skill_prompt ChatPromptTemplate.from_messages([ (system, 你是一个专业的航班预订助手专门负责book_flight预订航班这个技能。 你的工作流程必须严格遵循以下步骤 1. **信息收集**首先你必须向用户确认或获取以下所有必要信息 - 出发城市 - 到达城市 - 出发日期精确到日 - 乘客姓名 - 可选偏好条件如价格范围、航空公司、起飞时间段。 **注意**如果用户没有提供全部信息你必须主动、一次性地询问缺失项。 2. **航班搜索**在收集到完整的出发地、目的地、日期后立即调用search_flights工具进行查询。 3. **结果呈现与选择**将查询到的航班信息清晰、有条理地呈现给用户包括航班号、航空公司、时间、价格。如果用户有偏好条件根据条件筛选或推荐。然后引导用户**明确选择**一个航班号flight_no。 4. **执行预订**在用户明确指定航班号并提供乘客姓名后调用book_flight_ticket工具进行预订。 5. **确认反馈**将预订工具返回的确认号完整、准确地告知用户完成服务。 在整个过程中请保持对话友好、专业。一次只进行一个步骤确保每一步都获得用户明确的输入或确认后再进入下一步。 你可以使用的工具有 {tools} ), (placeholder, {chat_history}), (human, {input}), (placeholder, {agent_scratchpad}), ])然后用这个新的skill_prompt替换掉之前agent_setup.py中的通用prompt重新创建agent_executor。3.5 第五步测试完整Skill流程现在用多轮对话来测试这个Skill。# test_skill.py from agent_setup import agent_executor # 假设已使用新的skill_prompt更新了agent_executor # 模拟一个多轮对话 conversation [ 我想订一张机票。, 从北京飞广州后天出发。, 乘客叫张三。, 价格便宜点的。, 就选CZ789吧。 ] chat_history [] for user_input in conversation: print(f\n[用户] {user_input}) result agent_executor.invoke({input: user_input, chat_history: chat_history}) agent_response result[output] print(f[助手] {agent_response}) # 更新对话历史简化处理实际应用可能需要更结构化的存储 chat_history.append((user_input, agent_response))一个理想的运行过程会是用户说“我想订一张机票”Agent会意识到缺失信息主动询问出发地、目的地、日期、乘客姓名。用户补充“从北京飞广州后天出发”Agent会继续询问乘客姓名。用户提供“乘客叫张三”Agent此时已集齐查询三要素北京、广州、日期自动调用search_flights工具并返回航班列表同时询问偏好。用户说“价格便宜点的”Agent会基于价格筛选或推荐最便宜的航班并请用户选择航班号。用户选择“CZ789”Agent调用book_flight_ticket工具完成预订并返回确认号。这个过程体现了Skill的核心引导性的、多步骤的、状态感知的任务流程。4. 进阶技能优化与生产环境考量当你的基础Skill能跑通后接下来要考虑的就是如何让它更健壮、更高效以及如何管理多个Skills。4.1 错误处理与鲁棒性上面的简单示例缺乏错误处理。在生产中你必须考虑工具调用失败网络超时、API返回错误。需要在Agent执行器中设置max_execution_time、max_iterations并在工具函数内部做好异常捕获返回清晰的错误信息供Agent处理。用户输入歧义比如“下周三”可能有不同理解。可以在Skill提示词中要求Agent对模糊日期进行确认“您指的是5月29日吗”或者集成一个日期解析工具。流程中断用户可能在中间步骤改变主意。你的Agent需要能处理这种对话流的转移这通常需要更复杂的对话状态管理。改进示例为工具添加基础错误处理tool def search_flights(departure: str, destination: str, date: str) - str: # 返回类型改为str便于包含错误信息 根据出发地、目的地和日期搜索航班。 返回一个格式化的航班列表字符串如果出错则返回错误描述。 try: # 模拟可能出错的API调用 # ... 调用逻辑 ... if some_error_condition: return 错误航班查询服务暂时不可用请稍后再试。 flights [...] # 获取航班数据 formatted \n.join([f{f[flight_no]}: {f[airline]} {f[departure_time]} 价格{f[price]}元 for f in flights]) return f找到以下航班\n{formatted} if formatted else 未找到符合条件的航班。 except Exception as e: # 记录日志 print(f工具search_flights调用异常{e}) return f查询过程中发生系统错误{str(e)[:100]}4.2 技能编排与路由一个成熟的Agent往往具备多个Skills如book_flightbook_hotelquery_attractions。你需要一个“技能路由器”来根据用户意图将对话引导至正确的Skill。这可以通过以下方式实现意图识别在Agent顶层使用一个专门的LLM调用或一个分类模型来判断用户当前请求最匹配哪个Skill。子Agent模式每个Skill对应一个独立的、拥有特定提示词和工具集的子Agent。主Agent负责路由子Agent负责执行具体Skill。框架支持LangChain的AgentExecutor本身可以管理多个工具但对于复杂的、有状态的技能流你可能需要借助其PlanAndExecute或更高级的代理类型或者使用像AutoGen、CrewAI这类更侧重于多智能体协作的框架。4.3 状态管理与记忆我们的简单示例用chat_history传递对话记录但这对于需要跟踪复杂跨轮次状态如已选择的航班号、用户身份ID的Skill来说很脆弱。生产系统需要考虑会话记忆使用ConversationBufferMemory、ConversationSummaryMemory等来维护更长的上下文。技能状态持久化将关键状态如预订中的航班信息、用户偏好存储到数据库或缓存中并在每轮对话开始时读入Agent上下文。4.4 评估与监控Skill上线前需要评估其成功率在测试集上能完整、正确完成任务的对话比例。工具调用准确率参数传递是否正确调用时机是否合理。用户体验对话轮次是否过多引导是否清晰。 上线后需要监控API调用成本与延迟。错误率特别是工具调用失败和解析失败。人工介入率即有多少对话需要转人工客服。5. 常见问题排查清单当你开发的Agent Skill出现问题时可以按以下顺序排查问题现象可能原因排查步骤Agent不调用工具直接闲聊式回答1. 提示词Prompt未明确要求使用工具。2. 工具描述不清LLM不理解其用途。3. LLM的temperature参数过高导致输出随机。1. 检查系统提示词是否清晰赋予了“使用工具”的指令和步骤。2. 检查工具函数的文档字符串是否清晰描述了功能、输入和输出。3. 将temperature设为0或较低值确保输出确定性。工具调用参数错误1. LLM对参数格式理解有误。2. 工具函数参数类型与描述不符。1. 开启verboseTrue查看Agent传递给工具的action_input是什么。2. 确保工具参数有明确的类型提示如str,int且文档字符串中有说明。遇到unable to connect to anthropic services等API错误1. API密钥错误或过期。2. 网络问题代理、防火墙。3. 服务端故障或区域限制。1. 验证API密钥是否正确是否有调用额度。2. 使用curl或ping命令测试到API端点的网络连通性。3. 查看Anthropic官方状态页或社区确认服务是否正常。多轮对话中Agent忘记之前内容未正确维护和管理chat_history。1. 确保在每次invoke时都传入了历史的chat_history。2. 考虑使用LangChain的Memory模块来更可靠地管理历史。Skill流程混乱步骤跳跃提示词中对流程的约束不够强或者LLM未能严格遵循。1. 强化系统提示词中的流程步骤描述使用“必须首先”、“然后”、“在完成X之后才能进行Y”等强约束性词语。2. 考虑使用更复杂的代理结构如采用“规划-执行”模式的Agent。处理长任务时上下文超长对话历史或工具返回结果过长超出模型上下文窗口。1. 使用ConversationSummaryMemory来压缩历史。2. 对工具返回的大段结果进行摘要提取后再喂给LLM。3. 升级到支持更长上下文的模型。6. 总结从Demo到可用的关键点构建一个Demo级别的Agent Skill不难但要让它在真实场景中可靠工作你需要关注以下几个超越“教程”的关键点第一提示词工程是核心。Agent的行为几乎完全由提示词塑造。把你的Skill流程、约束条件、异常处理逻辑都用清晰、无歧义的语言写进系统提示词。多轮测试反复迭代提示词。第二工具设计要健壮。工具函数不要只考虑成功路径。必须有完善的错误处理、日志记录并返回对Agent友好的结构化或清晰文本化的结果。一个总是抛出异常的工具会让整个Agent崩溃。第三状态管理是难点。对于涉及多轮交互和复杂状态的Skill需要一个清晰的状态机或数据存储方案。不要依赖LLM在冗长的对话历史中自己“悟”出当前状态。第四评估不可或缺。不要只靠手动测试几个例子。构建一个涵盖正常用例、边界用例和异常用例的测试集定量评估你的Skill的成功率、平均对话轮次和成本。最后从简单开始逐步复杂化。不要一开始就设计一个包含十几个步骤、无数分支的超级Skill。先实现一个最小可行流程例如固定条件预订跑通它然后再逐步添加信息确认、偏好筛选、异常处理等模块。“Agent Skills”的本质是将人类的工作流程和决策逻辑通过提示词、工具和状态管理“编译”成LLM可以理解和执行的形式。它一半是艺术设计流程一半是工程实现稳定。理解了这一点再去看各种教程和框架你就能抓住重点知道该学什么以及如何应用到自己的项目中了。