1. 项目概述:从“万能管家”到“专业团队”的思维转变
最近在折腾各种AI Agent项目时,我发现一个挺有意思的现象:很多开发者,包括我自己在早期,都习惯性地想把所有事情都塞给一个“超级大脑”。具体表现就是,在调用大模型(比如GPT-4、Claude 3)时,我们会写一个巨长无比的system prompt,试图一次性告诉AI:“你是一个全能的助手,既要懂编程,又要会写文案,还得能分析数据、画图表、联网搜索……” 结果呢?往往事与愿违。这个“万能管家”要么表现得像个“半吊子”,每个领域都懂一点但都不精;要么在处理复杂、多步骤任务时逻辑混乱,频频出错。
这让我开始反思,我们是不是用错了设计模式?为什么在软件工程里,我们推崇“单一职责原则”和“模块化设计”,到了AI Agent这里,却总想造一个“巨无霸”呢?“Agent为什么需要Skills”这个问题的核心,其实就是在探讨如何为AI智能体构建一个高效、可扩展的“技能工具箱”,而不是把所有知识都硬塞进它那容量有限且容易混淆的“短期记忆”(即system prompt)里。
简单来说,一个设计良好的Agent,应该更像一个项目经理或指挥家。它自身(核心LLM)具备优秀的理解、规划和协调能力(这由相对精简、稳定的system prompt来定义其角色和核心推理逻辑)。而具体执行某项专业任务,比如写一段Python代码、调用一个特定的API、进行复杂的数学计算,则应该交给专门的、训练有素的“技能专家”(Skills)来完成。这样分工明确,各司其职,整个系统的可靠性、可维护性和性能都会得到质的提升。
2. 核心需求解析:为什么“大而全”的Prompt行不通
在深入探讨Skills的构建之前,我们必须先理解,为什么把所有能力都写在system prompt里是一个糟糕的主意。这背后有几个关键的技术和工程限制。
2.1 上下文窗口的“黄金地段”与注意力稀释
大语言模型(LLM)的上下文窗口(Context Window)就像一块昂贵的内存。虽然现在动辄128K、200K甚至更大,但它依然是稀缺资源。更重要的是,LLM的注意力机制(Attention)在处理长文本时,对开头和结尾部分的信息通常更为敏感,中间部分的信息容易被“稀释”。
当你把一个包含编程语法、文案风格、数据分析指令、API调用规则等数十条混杂指令的巨型system prompt丢给模型时,会发生什么?
- 关键指令被淹没:模型在生成回复时,需要从这海量信息中检索相关部分。如果指令过于庞杂,真正与当前用户查询相关的核心指令可能被埋没在文本深处,导致模型“忘记”或“忽略”它。
- 指令间相互干扰:不同领域的指令可能在表述上存在冲突或歧义。例如,文案写作要求“生动活泼”,而代码生成要求“严谨准确”,当它们共存于同一个提示词中时,模型可能会在风格上产生混淆。
- 浪费宝贵的“头部位置”:
system prompt通常位于上下文的最开始,这是注意力权重最高的“黄金地段”。本应用来定义Agent最核心的身份、目标和行为准则,却被各种琐碎的操作细节占据,严重影响了Agent的“人格”稳定性和决策质量。
实操心得:我曾在一个项目中,将一段复杂的JSON解析规则(约500字)塞进了
system prompt。结果发现,当用户问题稍微偏离核心时,Agent就会开始胡言乱语,甚至把JSON规则当成对话内容来复述。后来我把这部分规则抽离成一个独立的“解析技能”,只在需要时通过函数调用(Function Calling)动态引入,系统的稳定性立刻大幅提升。
2.2 系统提示词的“角色污染”与行为失准
system prompt的核心作用是定义Agent的“角色”和“基础行为框架”。它应该回答:“你是谁?”“你的核心目标是什么?”“你应遵循的基本准则是什么?” 例如,“你是一个乐于助人且严谨的编程助手,你的目标是安全、高效地解决用户的技术问题。”
当你把具体的“技能”描述(如“使用Python的requests库发起GET请求”)也混入其中时,就造成了“角色污染”。模型会模糊其核心身份定位,可能在某些时刻表现得像一个API调用工具,而不是一个协调者。这直接导致了行为不可预测。
2.3 可维护性与迭代的噩梦
从工程角度看,一个长达数千字、包罗万象的system prompt是维护者的噩梦。
- 更新困难:如果你想优化“数据分析”技能,你不得不在一大段文本中定位、修改,极易引入错误或遗漏。
- 调试地狱:当Agent输出不符合预期时,你很难定位问题根源:是核心角色设定有问题?还是某个技能指令写错了?或者是技能之间的组合逻辑有冲突?
- 无法复用:一个好的“代码生成”技能,应该能被不同的Agent(如编程助手、代码审查员)复用。如果它被固化在某个Agent的
system prompt里,复用就无从谈起。
2.4 超越文本:与外部世界交互的必然需求
AI Agent的终极价值在于成为连接数字世界与物理世界的“行动者”。这意味着它需要:
- 执行计算:进行模型自身不擅长的精确数学运算。
- 查询数据库:获取实时、结构化的私有数据。
- 调用API:操作其他软件服务,如发送邮件、管理日历、控制智能设备。
- 使用工具:操作浏览器、IDE、命令行等。
这些能力无法,也不应该通过自然语言描述在system prompt中“教会”模型。它们必须通过预定义的、可编程的接口(即Skills)来提供。模型只需要知道“有什么技能可用”以及“何时调用哪个技能”,具体的执行交给技能背后的代码或服务。
3. Skills的本质与架构设计:构建Agent的“瑞士军刀”
理解了“为什么不要”,接下来就是“应该怎么做”。Skills(技能)不是一个模糊的概念,在现代AI Agent框架(如LangChain、AutoGen、CrewAI,以及新兴的Hermes、MCP等)中,它有非常具体的表现形式和架构模式。
3.1 Skill是什么?从Function Calling到可执行模块
在最基础的层面上,一个Skill就是一个可供大模型调用的、具有明确定义的功能单元。它的核心组成部分包括:
- 名称(Name):唯一标识符,如
search_web,execute_python_code。 - 描述(Description):用自然语言清晰描述这个技能是做什么的。这部分描述是给大模型“看”的,决定了模型是否能正确理解并调用它。描述应简洁、准确,突出功能和使用场景。
- 参数模式(Parameters Schema):严格定义输入参数的名称、类型、是否必需、描述及约束。这通常以JSON Schema格式定义。
- 执行体(Implementation):真正执行功能的代码。这可以是一段本地函数、一个远程API调用、一个命令行工具的执行,甚至是调用另一个AI模型。
一个典型的Skill定义示例(以OpenAI Function Calling风格为例):
{ "type": "function", "function": { "name": "get_current_weather", "description": "获取指定城市的当前天气情况。", # 给模型看的描述 "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "城市名称,例如:北京,上海。" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位,默认为摄氏度(celsius)。" } }, "required": ["location"] } } }对应的执行体可能是一个调用天气API的Python函数。
3.2 分层技能架构:从基础工具到复杂工作流
一个成熟的Agent系统,其Skills通常是分层组织的:
- 基础工具层(Atomic Tools):最细粒度的技能,执行单一、原子的操作。例如:
read_file,write_file,http_get,calculate。- 设计要点:保持高度内聚和单一职责。一个工具只做一件事,并做好。
- 组合技能层(Composed Skills):由多个基础工具按一定逻辑组合而成,完成一个更复杂的子任务。例如:
analyze_csv_and_plot这个技能,内部可能依次调用read_csv_file,perform_statistical_analysis,generate_matplotlib_plot,save_plot_to_image等基础工具。- 设计要点:定义清晰的输入输出接口,内部逻辑对Agent核心透明。Agent只需要调用这个组合技能,而不必关心内部步骤。
- 领域智能体层(Domain-Specific Agents):对于极其复杂的领域(如高级财务分析、药物分子设计),可以专门训练或配置一个具备该领域深度知识的“子Agent”。主Agent通过更高级的协调协议(如通过消息队列或RPC)与这些子Agent协作。这可以看作是宏观层面的“技能复用”。
注意事项:不要过度设计。对于大多数应用,基础工具层和简单的组合技能层已经足够。过早引入复杂的多层架构会增加系统的复杂性和调试难度。我的经验是,先从原子工具开始,随着业务逻辑复杂度的提升,自然地将频繁连续使用的工具组合成更高级的技能。
3.3 System Prompt与Skills的职责边界划分
明确了Skills的构成,我们就可以清晰地划分它与system prompt的职责:
| 特性 | System Prompt | Skills |
|---|---|---|
| 核心目的 | 定义Agent的身份、目标、人格和核心推理原则。 | 提供Agent可调用的具体操作能力和专业知识。 |
| 内容性质 | 相对稳定、高层级的自然语言描述。 | 动态、模块化、有明确接口(名称、描述、参数)的可执行单元。 |
| 变化频率 | 低频修改。只在Agent角色定位发生根本变化时调整。 | 高频迭代。可以随时增加、删除、修改或优化单个技能,不影响Agent核心。 |
| 信息载体 | 主要存在于LLM的上下文记忆中。 | 存在于外部代码/服务中,通过函数调用等方式动态接入。 |
| 类比 | 公司的企业文化、愿景和核心价值观。 | 公司各部门的专业团队和工具(如财务部、法务部、设计软件、CRM系统)。 |
一个优秀的system prompt模板可能长这样:
你是一个名为[Agent名称]的AI助手。你的核心角色是[角色描述,如:资深软件开发顾问]。你的首要目标是[核心目标,如:帮助用户设计、实现和调试高质量的软件解决方案]。你遵循以下原则: 1. 安全性第一:绝不生成或执行可能造成危害的代码或指令。 2. 循序渐进:对于复杂问题,先提供思路,再给出实现细节。 3. 诚实透明:如果你不知道或不确定,请明确告知,不要虚构信息。 你可以使用一系列工具(Skills)来帮助你完成任务。当需要时,我会告诉你有哪些工具可用。请根据你的判断,决定是否需要以及何时调用这些工具。可以看到,这个prompt完全聚焦于“我是谁”和“我要怎么做决策”,而把“我能做什么”的具体能力,交给了外部动态管理的Skills。
4. 实操:如何为你的Agent设计和接入Skills
理论说完了,我们动手搭建一个简单的Agent,看看Skills如何实际接入和工作。这里我们以Python环境为例,使用流行的LangChain框架来演示,因为它对工具(Skills)的支持非常成熟和直观。
4.1 环境准备与基础框架搭建
首先,安装必要的库并设置环境变量(假设你使用OpenAI的模型)。
pip install langchain langchain-openai python-dotenv创建一个.env文件存放你的API密钥:
OPENAI_API_KEY=your_api_key_here然后,我们创建一个基础的Agent运行脚本:
# main.py import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder # 加载环境变量 load_dotenv() # 1. 初始化大模型 llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0) # 2. 定义System Prompt (这里我们把它放在PromptTemplate里) prompt = ChatPromptTemplate.from_messages([ ("system", """你是一个全能且务实的AI助手。你的思考过程应该严谨,在回答用户问题或执行任务时,应优先考虑使用可用的工具来获取准确信息或执行操作。如果你不确定,可以询问澄清问题。"""), MessagesPlaceholder(variable_name="chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]) # 3. 定义工具列表 (Skills) - 我们先创建一个空列表,后面会填充 tools = [] # 4. 创建Agent (稍后绑定工具) # 5. 创建Agent执行器 (稍后绑定Agent)4.2 创建你的第一个Skill:一个自定义计算器
让我们创建一个比简单四则运算更实用一点的技能:一个能计算复数运算的计算器。我们将使用langchain.tools的基类来构建。
# tools/calculator_tool.py from langchain.tools import BaseTool from pydantic import BaseModel, Field import math import cmath # 用于复数计算 class ComplexCalculatorInput(BaseModel): """复数计算器的输入参数模型。""" expression: str = Field(description="一个包含复数的数学表达式,支持 +, -, *, /, **, sqrt, sin, cos, abs, phase。复数用 'a+bj' 或 'a-bj' 格式,例如:'(3+4j) * (1-2j)' 或 'abs(3+4j)'。") class ComplexCalculatorTool(BaseTool): name = "complex_calculator" description = "执行包含复数的数学表达式计算。输入应为有效的Python复数表达式字符串。" args_schema = ComplexCalculatorInput return_direct = False # 结果返回给Agent继续处理 def _run(self, expression: str) -> str: """执行计算。""" try: # 安全警告:在实际生产中,直接eval是危险的,这里仅作演示。 # 应使用更安全的表达式解析库(如 ast.literal_eval 配合自定义解析)或沙箱环境。 # 此处为简化,我们做一个极简的“安全”替换和eval。 # 注意:这仍然不安全,切勿在生产环境用于处理不可信输入! safe_globals = {"__builtins__": None} safe_locals = {"abs": abs, "sqrt": cmath.sqrt, "sin": cmath.sin, "cos": cmath.cos, "phase": cmath.phase, "math": math, "cmath": cmath} # 将表达式中的 'j' 替换为 Python复数单位 'j' (其实一样),并确保括号匹配 # 这是一个非常简陋的演示,真实工具需要更严谨的解析和沙箱。 result = eval(expression, safe_globals, safe_locals) return f"表达式 `{expression}` 的计算结果是:{result}" except Exception as e: return f"计算失败,表达式可能无效或存在错误:{e}。请确保使用正确的格式,例如 '(3+4j)*(1-2j)'。" async def _arun(self, expression: str) -> str: """异步版本(可选)。""" return self._run(expression)关键点解析:
- 继承
BaseTool:这是LangChain中所有工具的基类。 - 定义输入模型:使用Pydantic的
BaseModel来严格定义输入参数的格式和描述。这会被自动转换成JSON Schema供模型理解。 - 填写核心属性:
name和description至关重要,模型根据它们来决定是否以及如何调用此工具。args_schema指定了输入参数模型。return_direct如果设为True,工具的结果会直接作为最终回复返回给用户;设为False(默认)则结果会交给Agent,让Agent决定下一步(是继续调用工具还是总结回复)。
- 实现
_run方法:这里是技能的实际执行逻辑。请注意代码中的安全警告:在生产环境中,绝对不要用eval()直接执行用户或模型提供的字符串,必须使用沙箱、严格的白名单过滤或专用的数学表达式解析库。
4.3 创建第二个Skill:一个模拟的网页搜索工具
为了演示多技能协作,我们再创建一个模拟的搜索工具(真实项目中可以接入SerperAPI、Google Search API等)。
# tools/search_tool.py from langchain.tools import BaseTool from pydantic import BaseModel, Field import random import time class SearchInput(BaseModel): query: str = Field(description="需要搜索的关键词或问题。") class MockSearchTool(BaseTool): name = "web_search" description = "在互联网上搜索信息,获取与查询词相关的简要摘要和链接。当需要最新信息、事实核查或未知领域知识时使用此工具。" args_schema = SearchInput return_direct = False def _run(self, query: str) -> str: """模拟搜索过程。""" # 模拟网络延迟 time.sleep(0.5) # 模拟返回一些“搜索结果” mock_results = [ f"根据网络资料,'{query}' 通常指的是... (来源: example.com/wiki)", f"近期关于 '{query}' 的讨论主要集中在... (来源: news.site/article)", f"一项研究显示,与 '{query}' 相关的技术趋势是... (来源: research.org/paper)", ] result = random.choice(mock_results) return f"搜索关键词:'{query}'\n结果:{result}\n(注:此为模拟数据)" async def _arun(self, query: str) -> str: return self._run(query)4.4 集成Skills并运行Agent
现在,我们将这两个技能集成到主Agent中。
# main.py (续) from tools.calculator_tool import ComplexCalculatorTool from tools.search_tool import MockSearchTool # ... 之前的初始化代码 ... # 3. 定义工具列表 (Skills) - 现在填充它们 tools = [ComplexCalculatorTool(), MockSearchTool()] # 4. 创建Agent agent = create_openai_tools_agent(llm, tools, prompt) # 5. 创建Agent执行器 agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True) # 6. 运行一个示例查询 if __name__ == "__main__": # 示例1:需要计算的问题 query1 = "计算一下复数 (1+2j) 和 (3-4j) 的乘积,然后求其幅角。" print(f"用户: {query1}") result1 = agent_executor.invoke({"input": query1, "chat_history": []}) print(f"助手: {result1['output']}\n") # 示例2:需要搜索的问题 query2 = "什么是LangChain框架?" print(f"用户: {query2}") result2 = agent_executor.invoke({"input": query2, "chat_history": []}) print(f"助手: {result2['output']}\n") # 示例3:混合型问题(最能体现Agent的规划能力) query3 = "请搜索一下‘量子计算的最新进展’,然后假设有一个量子比特的状态用复数表示为 (0.6+0.8j),帮我计算它的概率幅。" print(f"用户: {query3}") result3 = agent_executor.invoke({"input": query3, "chat_history": []}) print(f"助手: {result3['output']}")运行这个脚本,你将看到verbose=True模式下Agent的完整思考过程(ReAct模式):
- 思考:分析用户问题,判断是否需要使用工具。
- 行动:选择工具(
web_search或complex_calculator),并生成符合参数模式的调用。 - 观察:接收工具返回的结果。
- 循环:基于观察结果,再次思考,决定下一步(继续调用工具还是给出最终答案)。
通过这个流程,你可以清晰地看到,一个精简的system prompt定义了Agent的思考方式,而具体的“搜索”和“计算”能力,则由独立的、可插拔的Skills提供。这就是模块化设计的威力。
5. 高级技巧与最佳实践:打造健壮的Skills生态
掌握了基础搭建后,我们来探讨一些提升Skills系统质量的高级技巧和避坑指南。
5.1 Skill描述的“艺术”:如何让Agent准确理解并调用
Skill的description字段是连接模型意图和工具功能的桥梁。写得好坏直接决定工具是否被正确调用。
- 坏描述:
“一个计算工具。”(太模糊,模型不知道何时用) - 好描述:
“执行数学表达式计算,支持加减乘除、乘方和括号。当用户问题涉及数值计算、公式求解或需要得到精确数字结果时使用此工具。” - 更好描述:
“获取指定城市的当前天气、温度和湿度预报。当用户询问天气、穿衣建议或出行是否需要带伞时使用此工具。输入参数‘location’应为城市名。”
撰写要点:
- 明确功能:开头一句话概括核心功能。
- 界定场景:说明“在什么情况下使用”。可以列举典型问题类型。
- 提示输入:简要说明关键输入参数是什么。
- 区分相似工具:如果你有多个检索工具(如搜索网页、搜索内部文档),要在描述中强调它们的区别(如“搜索公开网络信息” vs “检索公司内部知识库”)。
5.2 技能编排与规划:让Agent学会“分步骤思考”
简单的Agent一次调用一个工具。但复杂任务需要多步骤规划。如何让Agent具备这种能力?
- 依靠模型自身能力:GPT-4等高级模型在精简、清晰的
system prompt指导下,已经具备不错的链式思考(Chain-of-Thought)和规划能力。我们的示例中,模型自动处理了“先搜索,再计算”的流程。 - 使用规划器(Planner):对于极其复杂的工作流,可以引入一个专门的“规划”Skill或一个子Agent。它的输入是终极目标,输出是一个分步骤的计划(例如:
[步骤1: 调用 search_web, 步骤2: 调用 summarize_text, 步骤3: 调用 send_email]),然后由主Agent或执行器按步骤调用。 - LangChain的Agent类型:LangChain提供了多种预设的Agent类型(如
ZERO_SHOT_REACT_DESCRIPTION,OPENAI_FUNCTIONS,PLANNER_REACT),它们内置了不同的推理逻辑。OPENAI_FUNCTIONS与最新的GPT模型配合很好,支持并行函数调用,效率更高。
5.3 错误处理与技能降级
Skills执行可能会失败(网络超时、API限流、参数错误)。一个健壮的Agent需要处理这些情况。
- 在Skill内部处理:像我们计算器示例中的
try...except,返回清晰的错误信息,而不是抛出异常崩溃。 - 在Agent层面处理:在
AgentExecutor中设置handle_parsing_errors=True可以处理模型输出不符合工具格式的解析错误。你还可以自定义回调函数,在工具执行失败时触发备用逻辑或向用户请求澄清。 - 技能降级策略:例如,当精确的“数据库查询”技能失败时,可以降级到模糊的“全文搜索”技能。
5.4 技能的管理与发现:Skill Registry
当Skills数量增长到几十上百个时,管理就成了挑战。你需要一个“技能注册中心”(Skill Registry)。
- 集中注册:一个中心化的地方注册所有可用的Skills及其描述、参数模式。
- 动态加载:Agent在初始化时,或根据对话上下文,从注册中心动态加载所需的技能子集,而不是一次性加载所有技能。这可以减少模型的认知负担,并实现基于上下文的技能推荐。
- 新兴标准:Model Context Protocol (MCP)正在成为一个有前景的标准,它定义了AI应用与外部工具/数据源之间统一的通信协议。使用MCP,你可以将Skills作为独立的“资源”或“工具”服务器来运行,Agent可以通过标准协议动态发现和调用它们,实现真正的解耦和可扩展性。
6. 常见问题与排查技巧实录
在实际开发和调试Agent系统时,你会遇到各种问题。以下是我踩过的一些坑和解决方案。
6.1 问题:Agent拒绝调用任何工具,总是尝试自己回答
- 症状:即使提供了合适的工具,Agent的回复也是“根据我的知识...”,而不触发工具调用。
- 排查步骤:
- 检查
system prompt:确保prompt中明确鼓励或要求Agent使用工具。例如,加入“请充分利用我为你提供的工具来获取准确信息或执行操作。” - 检查工具描述:工具的描述是否清晰?是否明确说明了使用场景?模型可能因为描述模糊而无法匹配。
- 检查模型能力:某些较小的或旧版的模型(如
gpt-3.5-turbo的某些版本)的函数调用/工具使用能力较弱。尝试切换到gpt-4-turbo或claude-3系列模型。 - 提供示例(Few-Shot):在
system prompt或初始消息中,给出一两个使用工具解决问题的对话示例,这能极大地引导模型行为。
- 检查
6.2 问题:Agent错误地调用了工具(选错工具或参数格式错误)
- 症状:Agent调用了工具,但工具名称不对,或生成的参数完全不符合定义的Schema。
- 排查步骤:
- 简化测试:先用一个最简单的工具(如
get_current_time)测试,看基础流程是否通。 - 审查工具描述和参数描述:这些描述是给模型看的“文档”。确保它们像给人类开发者写的API文档一样清晰、无歧义。参数名最好使用英文,因为模型在训练时见到的代码和API大多是英文的。
- 启用详细日志:设置
verbose=True,查看模型的完整思考链(Chain of Thought)。它可能会输出“用户想计算,我需要用计算器工具,参数是...”这样的内部语言,帮助你判断是规划错误还是参数生成错误。 - 使用更严格的参数Schema:在Pydantic模型中,充分利用
Field的description,enum(枚举值),gt(大于),lt(小于)等约束条件,给模型更明确的指引。
- 简化测试:先用一个最简单的工具(如
6.3 问题:多轮对话中,Agent“忘记”了可用的工具或之前的上下文
- 症状:在对话的第二轮或第三轮,Agent不再使用工具,或者对之前工具执行的结果视而不见。
- 解决方案:
- 管理聊天历史:确保将完整的对话历史(包括用户的输入、Assistant的回复、以及工具调用和工具返回的结果)作为上下文传递给下一轮。在LangChain中,这通常通过
MessagesPlaceholder和正确管理chat_history变量来实现。 - Summarization技巧:对于超长对话,可以将久远的历史总结成一个摘要,再将摘要和近期对话一起作为上下文,以节省Token并保持关键信息。
- 在
system prompt中提醒:可以在prompt末尾加上一句“在整个对话过程中,你都可以使用上述工具。”
- 管理聊天历史:确保将完整的对话历史(包括用户的输入、Assistant的回复、以及工具调用和工具返回的结果)作为上下文传递给下一轮。在LangChain中,这通常通过
6.4 性能优化:减少延迟与Token消耗
- 并行调用:如果任务中的多个工具调用没有先后依赖关系,可以利用支持并行函数调用的模型(如
gpt-4-turbo)和框架特性,同时发起调用,显著减少总耗时。 - 技能粒度权衡:技能不是越细越好。如果一个复杂操作总是被连续调用,将其封装成一个组合技能,可以减少模型规划的次数和来回交互的延迟。
- 精简工具描述:在保证清晰的前提下,尽量缩短工具的名称和描述,以减少它们占用的上下文Token。但切忌为了省Token而牺牲清晰度,导致误调用。
设计AI Agent时,把Skills看作其可扩展的“双手”和“专业工具箱”,而把system prompt看作其“大脑”和“决策核心”。两者各司其职,才能构建出强大、稳定且易于维护的智能体系统。下次当你又想往system prompt里塞东西时,先问问自己:这定义的是“我是谁”,还是“我能做什么”?如果是后者,那就为它打造一个独立的Skill吧。