Agent、Skill、Tool 到底有什么区别?为什么很多系统一开始就做错了?
应该像一个优秀的经理:它知道要达成什么目标,知道团队里谁有什么能力,知道如何分解任务和分配工作,但它不会亲自去写代码、发邮件、查数据库。的共同特征:它们的输入输出是严格定义的,它们的行为是确定性的(给定相同输入,产生相同输出或执行相同操作),它们不关心。有的记录日志,有的不记录。它代表一个具体的、可执行的操作,有明确的输入、输出和副作用。不需要知道日志文件的路径,不需要知道文件编码,不需要知道如何
一、一个被普遍忽视的概念混淆
在当前的Agent开发社区中,有三个词几乎每天都会被用到:Agent、Skill、Tool。但如果你随机问十个开发者这三个词分别是什么意思,你很可能会得到十种不同的答案。
有人说“Tool就是函数,Skill就是Tool的集合”,有人说“Skill是Agent能做的事,Tool是做事用的工具”,还有人说“这两个词可以互换使用,没什么区别”。这种概念上的模糊不是学术上的吹毛求疵,而是有实际危害的。概念混淆直接导致架构混乱,架构混乱直接导致系统失控。
为什么这三个概念如此容易被混淆?因为它们确实有重叠的部分。一个Tool可以被包装成一个Skill,一个Agent可以使用多个Skill,一个Skill也可能内部调用多个Tool。但“有重叠”不等于“可以互换”。混淆它们的代价,会在系统规模扩大时成倍放大。
本章的目标非常明确:给出Agent、Skill、Tool三个概念的精确、可操作的定义,说明它们各自在MCP体系中的位置,并指出那些“一开始就做错了”的系统究竟错在哪里。
二、Tool:最底层的“能力原子”
Tool是最小、最原子化的能力单元。它代表一个具体的、可执行的操作,有明确的输入、输出和副作用。
这是整个概念体系中最低、最稳定的一层。Tool不应该包含任何决策逻辑,不应该包含任何业务语义,它只做一件事,并且把它做好。
举几个具体的例子:
- read_file(path) —— 读取指定路径的文件内容
- send_email(recipient, subject, body) —— 发送一封邮件
- query_database(sql) —— 执行SQL查询并返回结果
- call_rest_api(url, method, body) —— 发起一个HTTP请求
注意这些Tool的共同特征:它们的输入输出是严格定义的,它们的行为是确定性的(给定相同输入,产生相同输出或执行相同操作),它们不关心“为什么要调用”以及“调用之后还要做什么”。
Tool的关键约束:
第一,Tool不包含任何智能。它不应该自己决定“要不要执行”“用什么参数执行”。这些决策应该由上层(Agent)做出,Tool只负责执行。
第二,Tool应该是通用的、可复用的。一个好的Tool不应该为某个特定Agent或特定场景定制。read_file就是read_file,无论是哪个Agent来调用,无论是什么场景,它的行为都应该是一致的。
第三,Tool的粒度应该尽可能小。如果一个操作可以被拆分成多个独立的子操作,那就应该拆分成多个Tool。小粒度带来灵活性,大粒度带来便利性但牺牲组合能力。
在MCP体系中,Tool是最容易被封装成Skill的底层能力。一个Skill可以封装一个Tool,也可以封装多个Tool的组合。但Tool本身不关心它被谁调用、如何被调用——它只负责“干活”。
三、Skill:有语义的“能力包”
Skill是一个有业务语义的、可被Agent调用的能力单元。它封装了一个或多个Tool的调用逻辑,并可能包含调用顺序、错误处理、参数转换等“流程逻辑”。
如果说Tool是“怎么做的”,那么Skill就是“做什么的”。Skill引入了业务语义和意图,这是它与Tool最本质的区别。
对比一下:
- Tool层面:read_file("/var/log/app.log") —— 读取一个文件
- Skill层面:read_application_logs() —— 读取应用日志
看起来很像?区别在于:Skill封装了“应用日志存在哪里”“应该读哪个文件”“如果文件不存在怎么办”这些知识。Agent不需要知道日志文件的路径,不需要知道文件编码,不需要知道如何处理文件不存在的错误。Agent只需要表达意图:“我要读取应用日志”,Skill负责把意图转化为具体的Tool调用序列。
Skill的关键特征:
第一,Skill是面向Agent的接口。Agent和Skill之间通过自然语言或语义化的API进行交互。Agent说“帮我查一下天气”,Skill负责把这个意图转化为具体的Tool调用——可能是调用一个天气API,可能是解析返回的JSON,可能是格式化输出。
第二,Skill封装了复杂性。Agent不需要知道Skill内部是怎么实现的。一个Skill可能调用一个Tool,也可能调用十个Tool;可能同步执行,也可能异步执行;可能成功返回,也可能失败重试。这些细节对Agent是透明的。
第三,Skill是有边界的。一个Skill应该有一个清晰的职责范围。“处理所有和用户相关的事情”不是一个好的Skill边界,因为它太宽了。“获取用户基本信息”“更新用户邮箱地址”“验证用户权限”才是好的Skill边界——单一、清晰、可组合。
Skill在MCP中的特殊地位:
在MCP体系中,Skill是被“协议化”的对象。MCP不直接暴露Tool给Agent——这太底层、太危险了。MCP封装的是Skill,而Skill内部可以调用Tool。为什么?
因为直接暴露Tool给Agent意味着Agent可以发起任意粒度的任意操作。Agent可以调用delete_file,可以调用drop_database,可以调用任何它“能够”调用的Tool。但“能够”不等于“应该”。MCP通过Skill层引入了一个“治理边界”:Agent只能调用那些已经被封装成Skill、已经被审批通过、已经被授予权限的能力。
这就是为什么很多人“一开始就做错了”——他们直接把Tool暴露给Agent,跳过了Skill这个治理层。
四、Agent:有目标的“决策主体”
Agent是一个自主的决策主体。它接收一个目标(或用户请求),结合上下文和可用Skill,自主决定要调用哪些Skill、以什么顺序调用、如何处理调用结果。
Agent是整个体系中的“大脑”。Tool是“手”和“脚”,Skill是“动作库”,Agent是决定“做什么动作、什么时候做、做了之后下一步做什么”的那个主体。
Agent的关键特征:
第一,Agent是有目标的。和Tool、Skill不同,Agent不是被动地被调用,而是主动地追求目标。用户说“帮我安排明天下午三点的会议”,Agent的目标是“完成会议安排”,它需要自己规划:先查日历看该时间段是否空闲,再选择会议室,再发邀请,再确认参会人时间——这一系列决策都是Agent自主完成的。
第二,Agent是有上下文的。同一个目标,在不同的上下文中,Agent会采取不同的行动。如果用户是管理员,Agent可能直接执行操作;如果用户是普通成员,Agent可能需要先申请权限。如果之前已经查过日历,Agent可能不需要再查一次。
第三,Agent是动态决策的。Agent不是执行一个预定义的流程,而是在运行时根据当前状态决定下一步做什么。这意味着Agent的行为是不可完全预测的——这正是Agent“智能”的来源,也是为什么我们需要MCP来约束它。
Agent的边界在哪里?
一个常见的错误是把Agent做得太重——在一个Agent内部塞入了太多逻辑,让它既做决策又做执行,既理解意图又处理细节。正确的做法是:Agent只做决策和规划,执行交给Skill。
好的Agent应该像一个优秀的经理:它知道要达成什么目标,知道团队里谁有什么能力,知道如何分解任务和分配工作,但它不会亲自去写代码、发邮件、查数据库。那些事情由Skill(和Skill背后的Tool)完成。
五、三者的关系:一个清晰的层次模型
把Agent、Skill、Tool放在一起看,它们构成了一个清晰的层次模型:
text
┌─────────────────────────────────────────────────────────────┐
│ Agent │
│ (决策主体:做什么、什么时候做) │
└───────────────────────────┬─────────────────────────────────┘
│ 调用
▼
┌─────────────────────────────────────────────────────────────┐
│ Skill │
│ (能力包:有语义的、可治理的能力单元) │
└───────────────────────────┬─────────────────────────────────┘
│ 封装/调用
▼
┌─────────────────────────────────────────────────────────────┐
│ Tool │
│ (原子操作:具体的、可执行的操作) │
└─────────────────────────────────────────────────────────────┘
这个模型的几个关键点:
第一,单向依赖。Agent依赖Skill,Skill依赖Tool,反向不成立。Tool不知道谁在调用它,Skill不知道哪个Agent在使用它。这种单向依赖保证了系统的可测试性和可替换性。
第二,职责分离。Agent负责“决策”,Skill负责“意图到操作的映射”,Tool负责“执行”。每一层只关心自己的职责,不越界。
第三,治理发生在Skill层。MCP主要作用于Agent和Skill之间。Agent调用Skill需要遵循MCP协议,需要权限校验,需要审计日志。Tool之间的调用是内部实现细节,不需要MCP介入。
六、为什么很多系统一开始就做错了?
理解了上述模型,就能诊断出最常见的错误模式。
错误一:Agent直接调用Tool
这是最普遍的错误。开发者图省事,直接把几十个Tool的列表塞给Agent,让Agent自己决定调用哪个Tool、传什么参数。
问题在于:Agent没有能力理解Tool的语义边界和副作用。它看到delete_file这个Tool,只知道“这个Tool可以删除文件”,但它不知道“删除这个文件会有什么影响”“这个操作是否需要审批”“这个操作是否可逆”。
当Skill层被跳过,治理也就无从谈起。没有Skill层,你就无法在“Agent发起的请求”和“底层执行的操作”之间插入权限校验、审计日志、人工审批。
错误二:Skill做得太“重”
另一种错误是把Skill做成一个“小Agent”——Skill内部包含决策逻辑,会根据不同情况调用不同的Tool。
这破坏了层次边界。Agent已经做了决策,Skill应该只负责执行。如果Skill内部再做决策,整个系统就会变成“决策套决策”,行为变得不可预测,调试变得异常困难。
正确的做法是:Skill应该是“确定的”。给定相同的输入和上下文,Skill应该执行相同的Tool调用序列。任何需要动态决策的逻辑都应该上升到Agent层。
错误三:Tool粒度过大或过小
Tool粒度过大:一个Tool做了太多事情,比如process_user_request(request)——输入是一个模糊的请求,输出是不可预测的结果。这种Tool无法被复用,也无法被组合。
Tool粒度过小:把read_file拆成open_file、seek_file、read_bytes、close_file。这种粒度在系统编程层面是合理的,但对Agent来说太底层了。Agent不应该关心文件句柄和字节偏移。
正确的粒度是:Tool应该是“人类开发者直觉上认为的一个操作”。read_file是好的,delete_file是好的,open_file_handle是不好的。
错误四:没有MCP协议层
这是最根本的错误。即使你正确地区分了Agent、Skill、Tool,如果没有MCP这样的协议层来约束它们之间的交互,系统仍然会失控。
因为Agent调用Skill的方式可以是任意的——有的用HTTP,有的用gRPC,有的用本地函数调用。有的带认证,有的不带。有的记录日志,有的不记录。没有统一的协议层,就没有统一的治理。
七、MCP体系下的正确做法
在MCP体系中,三者的定义和关系变得更加清晰:
- Tool:开发者编写的最底层函数,用任何语言、任何框架都可以。Tool不需要知道MCP的存在。
- Skill:被MCP封装后的能力单元。Skill暴露MCP标准的接口,由MCP网关管理。Agent通过MCP协议调用Skill。
- Agent:通过MCP Client与MCP网关通信。Agent只认识MCP协议,不认识具体的Tool或Skill实现。
这种架构的好处是:
- Agent可以调用任何被MCP封装的Skill,无论Skill背后是什么Tool、运行在哪里。
- 治理(权限、审计、限流)在MCP网关层统一完成,Agent和Tool都不需要关心。
- 新增Skill只需要实现MCP接口并注册到网关,Agent自动获得新能力。
像Peta这样的MCP控制平面,正是这个架构的生产级实现。它提供了MCP网关、凭证管理、政策引擎、审计日志,让开发者可以专注于编写Agent和Skill,而不用担心协议层和控制平面的实现细节。
八、小结
Agent、Skill、Tool不是可以互换的同义词,而是三个不同层次的概念:
- Tool是最底层的原子操作:具体、确定、可复用、无智能。
- Skill是有语义的能力包:封装Tool调用、面向Agent、可治理。
- Agent是自主的决策主体:有目标、有上下文、动态决策。
很多系统一开始就做错了,因为它们跳过了Skill层,让Agent直接调用Tool,或者把Agent和Skill的职责混淆。正确的做法是建立清晰的层次模型,在Agent和Skill之间引入MCP协议层,通过控制平面实现统一的治理。
理解了这三者的区别,下一章我们将深入OpenClaw这类执行框架,看看它们在MCP体系中扮演什么角色,以及“执行层”和“协议层”之间到底是什么关系。
更多推荐




所有评论(0)