扫码打开虎嗅APP
本文来自微信公众号: 叶小钗 ,作者:叶小钗,原文标题:《【万字】Agent 的本质:用 Token 换架构》
市场今年刚看到Manus这种Agent的时候很兴奋,所以他们为什么这么兴奋?
Agent这东西又为什么会出现,他到底解决了哪一部分问题?其次,他到底能不能解决这些问题,在解决的过程中的困难与卡点是什么、又要如何解决?
带着上述问题,进入今天的学习:为什么需要Agent?
unsetunset为什么Agent会出现?unsetunset
模型当前虽然很强大,但他是天生缺陷的,他本身只包含了训练后的内置数据,这里就产生了第一个矛盾点:
所以,Agent出现的第一个原因是,他至少需要与外部世界进行信息交流,尤其是一些垂直领域,如果数据不足,模型很容易胡言乱语的。
其实在这里很多同学是有疑问的,如果仅仅是这个原因,那直接采用Workflow的模式就好了嘛,这也是最标准的RAG逻辑嘛:

但就简单的信息检索这个需求,也是随时递增的,他现在拿的是公网数据,后续一会要拿A公司数据、一会要拿B公司数据,这种数据源变多了后怎么办呢?
谁去判断他应该去哪拿数据呢?这种让RAG系统处理起来就会很麻烦,比如以下问题:
什么是组织结构?你们公司的组织结构是怎么样的,A公司是怎么样的,B公司又是怎么样的?他们为什么要这么设计?
直接使用RAG也能做,流程是用模型判断到底有哪些问题,做下问题重写,分拆后再到各个信息渠道去获取信息,一套复杂的Workflow类RAG就能搞定。
这里关于Agent最深的冲突也就出现了:Agent能做的事情Workflow都能做,那么Agent存在的意义是什么?
毕竟,Workflow可以做循环、可以做重试、可以做复杂策略,只不过这些循环与策略必须由人显式编码。当环境复杂度上升,Workflow的成本曲线会很难看:

在企业真实场景里,复杂度增长通常来自三类“不可穷举”:
当然可以把这些都写进Workflow,但会变成典型的分支爆炸+维护爆炸:
这时候Agent架构的优势就出来了,如果多了CDE有可能增加3个工具配置,有可能什么都不做,搜索工具自己就兼容了。
最重要的是,判断用户意图和怎么调用工具,工具调用后的数据对不对这些繁琐的事情全部丢给模型了,当然循环肯定会多很多次、效率肯定要低点、Token肯定要高点,毕竟本身Agent就是一套时间/成本换架构简洁度的架构。
这里再加一句:Agent解决的不是怎么回答的问题,而是给出了一套将问题编译为可执行计划的框架,甚至于你把Agent这套架构本身理解为一套Workflow,也是可以的,这个是一套现阶段验证出来,很不错的范式。
最后再总结一下:相较于Workflow,Agent架构是一种工程架构层面的优化,它的核心不是“更聪明”,而是把一部分原本由工程师在开发期显式写死的控制流(if/else、编排、异常处理),迁移到运行时由模型来决定(路由、工具选择、多轮尝试、失败重试、补槽追问、结果校验)。
Agent是用更多的成本(多轮推理+多次工具调用+更高延迟/Token),换开发与维护成本的下降(分支更少、扩展更快、长尾更适配)
在这个基础之下,我们再来看看整个Agent的发展史,这有助于我们进一步抓住其脉络。
unsetunsetAgent的发展史unsetunset
当前最经典的Agent架构是ReAct,他大约是在2022年提出,论文《ReAct:Synergizing Reasoning and Acting in Language Models》。
那时候并不支持Function Calling这种最基本工具调用的能力,所以需要我们自己做实现,这里可以用提示词做识别并输出、也可以做微调(但成本要高点)。
其中Function Calling整体流程大概这样做的:
第一,我们会定义Agent会调用的所有工具,这是一个JSON对象,里面最核心的是description;
第二,模型会根据用户问题和预设的工具集去做对比,看看这次要调用哪些工具,当然最主要的还是根据描述判断;
第三,如果这次判断是有工具调用的话,模型会返回工具的名称,然后结束这次流程;
第四,我们拿着工具信息,去各种调用拿到数据,然后组装最终的提示词,连着用户的问题去做模型调用
只不过上述动作毕竟太繁琐,于是在23年6月,OpenAI提出了Function Calling,将他作为ChatGPT产品的正式能力,后续逐渐成为事实上的标准,各个基座模型都有对应实现,有了这个基础后,Agent的出现就变得更加顺滑了。
而后的事情大家就很清楚了。国内Agent概念的火热从年初的Manus开始,但如果真要追溯早期、又出圈的Agent的话可以是2023年3月的开源项目Auto-GPT;
只不过就算今年的Manus在早期因为基座能力不足都表现不佳,遑论更早期的Auto-GPT了呢?
从Manus发布后,2025 AI应用元年逐渐转移成2025 AI Agent元年,模型也取得了长足的发展,包括整体的推理能力、上下文长度得到了极大的加强,而且我相信各个基座模型一定在工具调用这块做了大量微调训练,其直接的结果是下半年的工具调用能力有明显的加强。
在这个阶段,因为基座模型,大家发现Agent对工具的需求量极大,并且一定会产生很多类似的工具。
所以MCP的概念火了起来,一方面要解决之前Function Calling留下的工程维护问题,另一方面也想让人少开发工具,直接用社区的,MCP也几乎变成了事实上的标准,然后Agent发展进入了一个疯涨的阶段;
而后模型的稳定性调用能力有不小的加强,但在工具多了后依旧会有找不到、乱调用的问题。
于是Claude开始收集了大量Tools调优经验,在25年10月正式提出了Skills技术,可以认为他是在对整体Function Calling进行补足,当然Skills除了提升工具识别能力之外,还做了很多其他工作。
总之,现阶段使用Skills+Function Calling+上下文工程,已经可以将准确率做得很不错了,比如我们就能折腾到90%+,这在之前是很难的,在工程上要做很多动作。
以上,是我从技术层面看到的,近三年Agent发展的情况,也就是说:在今年之前想要做出个好的Agent几乎不可能;在今年下半年开始,整体难度会小非常多;
最后这里的推测是:之前对于Agent的很多质疑乃至产品体验差的问题,在2026年应该会得到很大的缓解。
所以,要说Agent直接依赖于模型能力的变迁,这句话还真的没问题,你怎么优化都可能比不上模型一次能力升级。
了解了Agent为什么会出现,发展脉络是什么,也知道了几个关键点,接下来我们就来具体聊聊这几个关键点:Function Calling、MCP和Skills:
unsetunsetFunction Callingunsetunset
根据前面的描述,FC是干什么的大家已经很清晰了,单说FC其实就是用一套工程架构把之前模型判断(如何用工具)的工作流给替代掉:

具体的交互逻辑为:在对话中,LLM根据用户的问题(今天北京的天气如何?)判断是否需要调用函数。
如果需要,它会输出一个结构化的JSON请求,其中包含了要调用的函数名和参数,然后再调用我们的程序,整个官方的案例非常清晰:

具体的流程,直接看GPT官方的定义即可:
#这是给模型看的工具定义,不是真正的代码tools=[{"type":"function","name":"get_weather","description":"Retrieves current weather for the given location.","parameters":{"type":"object","properties":{"location":{"type":"string","description":"City and country e.g.Bogotá,Colombia"},......},}}]
每次调用API时都需要传递tools参数,这里直接调用GPT接口(发起请求):
#每次调用API时都需要传递tools参数,调用GPT接口发起请求response=client.responses.create(model="gpt-5",messages=[...],tools=tools#←这个每次都要带)
这里也可以看出来,模型具有哪些工具调用能力,全部是我们预定义好的,模型会根据用户输入,选择使用哪个工具:
#用户输入user_query="今天北京天气怎么样?"#模型会分析:#-用户问的是"天气"→匹配到get_weather的description#-提到了"北京"→对应location参数#-决定调用get_weather函数
只不过,模型事实上并不会直接调用工具,他只会返回结构化的调用指令,这里返回这个东西是模型专门任务训练的结果:
{"function_call":{"name":"get_weather","arguments":"{\"location\":\"北京\",\"unit\":\"celsius\"}"}}
真正根据返回JSON数据调用脚本的是我们后台程序,并且这里需要将调用结果给到模型:
#把天气结果返回给模型#result是返回的结果final_response=llm.chat(model="gpt-5",messages=[{"role":"user","content":"今天北京天气怎么样?"},{"role":"assistant","function_call":model_response["function_call"]},{"role":"function","name":"get_weather","content":json.dumps(result)}])
逻辑很清晰,如果意图识别没有工具(函数)调用,则直接调用大模型返回给用户,如果判断有工具调用,那么就拿着首次模型返回的参数,拿到结果后二次调用模型,再将最终结果返回给用户。
这里有几个点要特别注意:如果你的工具接口挂了,容错做得不好的话,那么模型就不会回答用户了。
另外还有几个问题,理解后几乎就能了解Fuction Calling的本质,乃至为什么他用得不太频繁的原因:
第一,如果Tools工具过多(数组过多),这个也是要占用上下文长度的,所以真实使用会做很多小处理;
第二,Fuction Calling使用好坏非常依赖于模型本身对意图识别的能力,模型判断要不要调用一个函数,主要是根据description参数来的。
这里看上去风险挺大的,因为一定会出现模型调用出问题的情况,只不过模型容错能力强,多拿了数据也未必会影响回答;
在这个基础下,我们再来说MCP和Skills,先说MCP:
unsetunsetMCPunsetunset
那么MCP为什么会出现呢?这东西出现的意义是什么?要回答还得回归Function Calling...
关于Function Calling为什么会出现我们已经很清楚了,他解决的是:单个模型怎么“按你定义的JSON协议”去调你自己的API的问题。
但一旦工具变多后会有很多痛点:维护起来爆炸了!
MCP就是为了解决这个问题而生的,比较夸张的说法就是,MCP是帮Function Calling“擦屁股”的...
这里大家可能不太理解,给个案例:企业中有10个AI Agent(N)需要接入20个数据源/工具(M)。
如果每个应用都为每个工具编写专用适配代码,就需要200个集成点。这里面维护成本是较高的,任何工具API变更都会很烦。
并且要注意的是,生产上的Agent不会只调用一个模型,他可能同时调用ChatGPT、Gemini还有DeepSeek,而他们每个Tools调用接口都不一样,这个维护起来就更麻烦了。
在这个基础下,MCP出现了他引入“客户端-服务器”架构标准化。你只需编写一次MCP客户端,就能接入所有符合MCP协议的服务器。而工具提供者只需实现一个MCP服务器,就能被所有MCP客户端使用,集成点从N×M骤降到N+M。
案例说明
大家可能读起来有点迷糊,这里给个案例,这里有两个工具:
用户的问题是
“帮我查北京天气,再给我腾讯的股价,最后总结一下。”
传统的FC流程分四步:
一、预定义工具:
每次调用模型(或每个会话)都要把tools定义带进去:
tools=[{"type":"function","name":"get_weather","description":"Get weather by location","parameters":{"type":"object","properties":{"location":{"type":"string"}},"required":["location"]}},{"type":"function","name":"get_stock_price","description":"Get stock price by ticker","parameters":{"type":"object","properties":{"ticker":{"type":"string"}},"required":["ticker"]}}]
二、模型返回“工具调用指令”(结构化JSON)
{"tool_calls":[{"name":"get_weather","arguments":{"location":"Beijing"}},{"name":"get_stock_price","arguments":{"ticker":"AAPL"}}]}
三、我们自己后台程序做工具调用
def get_weather(location):returnweather_api.query(location)def get_stock_price(ticker):returnmarket_api.query(ticker)
四、拿到工具结果,组装提示词最终调用模型生成回答
tool_results=[{"name":"get_weather","content":"..."},{"name":"get_stock_price","content":"..."}]final=llm_call(messages+tool_results)
如果,这个工具只服务了一个Agent,那没问题,但如果服务了2个就会麻烦一点:
比如在工具参数变了的时候,他就要改2个Agent的配置了,如果应用变成20个的话就很麻烦了,因为我们大概率也记不清楚谁在调用工具了...
如果有MCP后,就简单很多了,他用工程的方式把一些复杂的维护封装了:把Tool A/Tool B的接入从“应用内部代码”搬到“独立的MCP Server”里。
AI应用不再直连Weather API/Market API,而是只连MCP Server。
这里其实逻辑很简单,甲乙双方之前口头约定参数,然后两边写,下游发现老是被坑,就说你他妈别约定了,参数是什么,你一起传给我算了!
Agent也不直接连接工具AI了,只连接MCP Server,可以把MCP当成一个“工具总线”:
方便大家理解,这里依然走个流程:
一、MCP Server暴露工具
#mcp_server.py@tool("get_weather",input_schema={"location":"string"})def get_weather(location):returnweather_api.query(location)@tool("get_stock_price",input_schema={"ticker":"string"})def get_stock_price(ticker):returnmarket_api.query(ticker)run_mcp_server(transport="stdio")#或HTTP/SSE等
二、Host连接MCP Server,并发现工具
client=MCPClient(connect="stdio:python mcp_server.py")tools=client.list_tools()#tools->[{name,description,input_schema,...},...]
三、把发现到的工具“翻译/映射”给当前使用的模型平台
注意:这一步仍然需要做“向上适配模型”,但这是一层通用适配,不会因为Tool A/Tool B的内部细节而变化。
四、模型基于工具合同做决策,返回tool_call(name+arguments)
{"tool_calls":[{"name":"get_weather","arguments":{"location":"Beijing"}},{"name":"get_stock_price","arguments":{"ticker":"0700.HK"}}]}
五、Host不再直连外部API,而是把调用转发给MCP Server
forcallintool_calls:result=client.call_tool(call["name"],call["arguments"])tool_results.append({"name":call["name"],"content":result})
至此基本结束了,其实大家也看出来了,Agent这东西黑盒是真的多啊...
遗留问题
虽然MCP确实可以解决工具过多的维护问题,但他并不能解决工具多了,乱调用、错调用的问题,而且还会有工具过多时候的爆炸问题,工具如何组织的问题。
当然,在比较差的架构下(团队能力不行),FC要求开发者在每次API调用时预先声明所有可用工具。
但这个是可以被优化的,也就是每次用户问题要过一次模型,判断这次到底要用哪些工具,要用才加载,只不过可能会有错漏。因为这个机制也能做到动态添加/移除工具。
但这一切依旧不太优雅,工具调用还是老是出问题,所以在MCP之后又有擦屁股的工程能力诞生了,他的名字叫:
unsetunsetSkillsunsetunset
我们前面说了,用户无限的意图需要用有限的工具来收敛。
只不过工具多了后,排列组合也多,收敛不收敛不知道,Agent最大诟病就是工具调用不准、Agent整体响应慢倒是真的,为了解决这一切,又叠加了一个新的工具:
Anthropic对Skill的定义是:一个文件夹,里面装着说明文档、脚本和资源,Claude在执行任务时会先扫一圈所有Skills,觉得哪个对当前任务有用,就把完整内容拉进上下文来用。
翻译翻译是:
Skill=一份可反复调用的专业SOP+说明书,由模型自己按需加载
结合之前我们说Skills的诞生原因,其实就是将工具调用不准的问题搬到了Skills里面,不需要模型自己去语义理解自己做工具组合了,Skills里面写得很清楚,该用什么工具、怎么用,这样就会缓解之前的工具错误。
当然除此之外,Skills还有其他意义,总结下来Skills诞生的原因有:
一、提高工具调用稳定性
绝大多数团队都会面临,一旦Tools多了后就会束手无策,他们会被“乱调用/漏调用/参数错/顺序不稳/失败不重试”折磨,直接导致体验差、不可交付。
Skills的核心价值之一就是把“怎么用工具把事做对”的套路(选择条件、步骤、校验、兜底)沉淀成可复用模块,从而显著降低随机性。
其实这个之前是做到ReAct工程架构里的,现在有Skills,可以有效降低工程难度;
只不过要特别注意,Skills也不能彻底解决Tools调用错误问题,还得有其他工程手段。
二、长提示词与硬编码流程的维护问题
关于这点,很有点之前MCP出来的重要原因,都是项目大了会导致的烦躁工程维护问题。
维护提示词多的同学会有感受,现在提示词正在往伪代码的方向发展,为了让模型稳定输出,需要往里面不断加东西,比如一个数据分析的案例:
结果:
Skills的解题思路就跟之前MCP很类似了,把所有的这类配置信息全部写到统一的地方,需要用到时候再拿出来。
另一个角度,既然提示词现在越来越像代码工程了,那么对应的版本管理的概念就会出现,包括追求的灰度和回滚等问题,而Skills正是处理提示词工程管理复杂而诞生的。
这里给个案例做,为什么需要Skills的说明:
案例对比
帮我查一下技术部张三上周的差旅报销总额,然后按项目拆分一下
这里直接使用FC的话:
[{"name":"get_employee_info","description":"获取员工基本信息","parameters":{"employee_name":"string"}},{"name":"get_department_info","description":"获取部门信息","parameters":{"department_name":"string"}},{"name":"query_reimbursements","description":"查询报销记录","parameters":{"employee_id":"string","start_date":"string","end_date":"string"}},{"name":"query_projects","description":"查询项目信息","parameters":{"department_id":"string"}},{"name":"analyze_reimbursement_data","description":"分析报销数据","parameters":{"reimbursement_data":"array","group_by":"string"}}]
在ReAct架构中需要自己去实现正确的调用逻辑:
这里常见问题就产生了:
能不能解决呢,也是可以的,但会加大工程复杂度,可能加大循环次数,最终响应速度和成本都会有影响。
而使用Skills后,相当于认为的为这个需要加了一套强的工作流,或者CoT:
用户:"张三上周差旅报销"模型:检测到"报销"关键词→加载"报销查询"Skill按Skill流程执行:1.自动调用get_employee_info("张三")→拿到ID:1232.自动调用时间解析("上周")→得到:2025-12-08~2025-12-14 3.调用query_reimbursements(employee_id=123,start_date=...,end_date=...)4.发现用户没提"项目"→跳过项目拆分步骤5.调用标准化报告模板生成结果直接返回:"张三上周差旅报销总额5,200元,共3笔..."用户体验:✅好-一次搞定
CoT都出来了,稳定性肯定高啊!
这里再说下维护性问题,如果财务的差旅标准变了,之前所有涉及提示词部分的数据需要改,但用Skills就只需要改一个地方,很清晰的。
其他案例
在一个老板BI Agent里配置了,一批Tools/MCP工具:
两个Skills:
这时候触发条件来了:帮我看看今年Q3的营收和投放,简单说说是不是该收一收预算?这里具体的流程是:
一、先走Skill检索
模型首先会理解,这是一个老板视角的财务分析+决策建议,接下来模型会遍历Skills里所有的meta,发现boss_bi_dashboard_cn的描述里有类似:
用于解读公司经营指标、营收、成本、预算,输出老板视角决策建议
所以它会激活这个Skill,读取instructions.md,把这份“说明书+SOP”拉进当前上下文。
此时,Tools/MCP还没被调用,模型完成了:从很多工具定义+一堆Skills里,选出一个最合适的技能包。
二、Skill里面决定工具调用
boss_bi_dashboard_cn的instructions.md可能会写类似这样的话:
如果用户问的是某个时间段的“营收+投放”,先调用get_sales_report拿营收数据,再调用get_marketing_spend拿投放数据;然后根据「同比/环比/ROAS」给出老板能看懂的判断;输出结论时,要用以下结构:一句话结论2–3个关键数字建议动作风险提示
Claude读了这份说明后,就知道下一步应该:
get_sales_report({"period":"2024-Q3"})get_marketing_spend({"period":"2024-Q3"})
到这里Function Calling/MCP出场了。
三、数据处理+SOP
这里走Function Calling的逻辑拿到最终反馈数据即可(这里不展开):
{"sales":12345678,"growth_rate":0.12,"gross_margin":0.31}
然后就是数据使用,这个instructions.md里面已经说得很清楚了:
输出结构怎么写;哪些数字要重点强调;语气要偏老板视角,少讲实现,多讲结论和动作;有哪些“常见坑”要避开;#输出案例结论:Q3的营收仍在增长,但投放效率明显走低,建议适度收缩预算、把钱放到ROAS更高的渠道上。......后面是建议+风险......
以上就是Skills,相信大家搞懂了,最后说下Agent架构的核心:ReAct。
unsetunsetReAct框架unsetunset
了解了Agent的最原子能力依赖后,我们就要进入其真正的编排层核心ReAct了:

编排层是智能体系统的核心控制单元,负责组织信息流和执行推理循环。它模拟人类在做复杂任务时的认知过程:先获取信息、然后制定计划、执行行动、再根据反馈调整计划,不断循环直到完成目标。
一个常见的比喻是“厨师准备复杂菜品”:厨师会根据顾客需求获取食材信息,思考烹饪步骤,然后实际烹饪,过程中可能根据味道反馈不断调整方法。
类似的,Agent的编排层会按照设定的推理框架反复迭代,驱动模型生成“思考”并做出“行动”决策。
常见的推理框架大同小异,这里一定需要了解的是两个东西ReAct与CoT,除此之外可以延伸到ToT:
ReAct在前面我们做了基础介绍,该框架强调模型在回答前进行连续的内省和行动选择,有助于提高答案的准确度和可追溯性;
CoT(思维链)引导模型通过生成中间推理步骤来分解问题,促使其在最终答案前先列举思考过程,这种框架可以增强模型解决复杂问题时的准确性(幻觉问题)。
ToT(思维树)是在CoT的基础上,允许模型在多个备选思路间做比较,适用于需要探索多种方案的策略性任务,目的依旧是提升对复杂问题的解决能力。
篇幅有限,我们只讨论ReAct和CoT的配合即可(其他的都类似):
ReAct和CoT
首先,ReAct与CoT都是推理策略框架也就是Agent四大组件核心的编排层具象化实现,他们都描述的是如何组织模型的推理过程、生成步骤、提示词结构。
换句话说,ReAct是代码的核心,是AI工程的核心,他会决定如何去与记忆系统、工具系统做配合。
然后,ReAct逻辑上与CoT是同级别的,但现在更多的是在组合使用,显得CoT是ReAct的一个过程产物,其实并不是的,逻辑上CoT也可以调用工具;
只不过现在从流行范式的角度来说,ReAct被用作主框架的时间会多一点,并且过程中会包含很多CoT的部分,这里的结果是:ReAct是容器,CoT是内容。ReAct是最“Agent”化的、CoT是最基础的。
ReAct规定了:先思考(Thought)→行动(Action)→等待结果(Observation)→再思考...
而这个“Thought”怎么写?通常就是一个Chain of Thought推理块。
举个简单例子:
让Agent回答“某公司员工请假流程”的问题
举个简单例子:,Agent需要:
这块的简要流程是:
User:请问我们公司请假流程是什么?Step 1:Thought:先查找关于“请假流程”的文档。Action:search_docs("请假流程")Observation:找到文档《员工手册》第4章,列出了流程步骤。Step 2:Thought:首先读取这部分内容,理解流程的顺序。-第一步是员工提交请假申请-第二步是直属上级审批-第三步是HR备案因此我可以组织一份清晰的回答。Action:NoneFinal Answer:请假流程如下:1)提交申请;2)主管审批;3)HR备案。
这个“Step 2”的Thought部分就是一个简单的CoT,模型在没有行动前,分步思考、提取、组织信息,这是典型的思维链。
为什么这么用也很简单:Agent架构中也不可能每一步都调用工具,很多时候只是在“组织思维/语言”,CoT可以有效降低幻觉率。
总而言之,ReAct框架里可以有很多CoT内容穿插其中,这种组合也是最常见、最稳的做法,大家记住这点就行,这就是Agent的编排层。
unsetunset结语unsetunset
然后就是记忆系统了,这个其实才是整个Agent项目里面最恼火、最烦躁的部分,因为太过于复杂,我们今天就不继续了,后面有专门的课题。
最后总结一下:市场之所以为Manus这类Agent兴奋,不是因为它“更聪明”,而是因为它把原本需要工程师在Workflow里写死的路由、工具选择、重试等控制流,迁移到运行时由模型来决定,从而在“工具多、意图组合多、异常多”的企业场景里显著降低开发与维护成本。
过去三年的脉络也很清晰:ReAct提供推理+行动的循环框架,Function Calling让工具调用标准化,MCP缓解工具爆炸带来的集成维护成本,Skills把“怎么把工具用对”的SOP沉淀下来提升稳定性。
25年工具调用这块模型已经取得了长足进步,但记忆模块依旧是老大难问题,我认为2026年,底层模型一定会在这块做出突破,那种本地部署的模型(高阶向量数据库)是可能诞生的,让我们拭目以待吧...