理解AI智能体:工具调用、MCP与智能体循环
从增强型大语言模型出发,跳过那些流行术语,探讨工具调用、MCP以及智能体循环如何共同构成人工智能智能体的实际架构。
当人们开始探索人工智能智能体时,总有那么几个术语频繁出现:
智能体、工具、函数调用、MCP、上下文、内存。
乍看之下,这些似乎是一堆互不相关的技术。
但只要花足够时间研究真正的智能体系统是如何构建的,尤其是仔细阅读 Anthropic 关于智能体和 MCP 的技术文档,就会发现其背后其实存在一种更为简单的架构。
本文将从开发者的实际视角来解析这一架构。
究竟是什么让人工智能系统成为智能体?
典型的基于大语言模型的应用可以这样表示:
User
↓
LLM
↓
Response
在这里,模型只是接收输入并生成输出。
但许多实际任务仅靠生成文本是无法解决的。
以这个请求为例:
“查看这个 GitHub 仓库中的待解决问题,挑选其中最关键的那个,然后概述仍需修复的内容。”
要处理这类问题,系统必须:
- 理解请求内容。
- 确定需要哪些信息。
- 选择合适的工具。
- 执行该工具。
- 检查结果。
- 决定下一步该做什么。
- 可能需要调用其他工具。
- 生成最终响应。
这正是智能体系统发挥作用的地方。
Anthropic 在工作流与智能体之间划出了明确的界限。
工作流是按照固定的步骤顺序来执行的:
LLM → Step 1 → Step 2 → Step 3 → Answer
而智能体则会自行决定使用哪些操作和工具:
┌──────────────┐
│ LLM │
└──────┬───────┘
│
choose action
↓
Tool
↓
Result
│
└──────────→ LLM
│
choose next action
关键点并不只是流程的某个环节中使用了大语言模型。
而是大语言模型本身能够参与决定流程的走向。
Anthropic将智能体视为这样的系统:大语言模型在其中主动掌控自身的工作流程及工具使用方式,而传统工作流程则依赖开发者预先定义的编排逻辑。
增强型大语言模型
Anthropic的资料中有一个特别有用的概念,即增强型大语言模型。
不必将大语言模型简单理解为:
LLM → Text
可以将其理解为:
┌─────────────┐
│ LLM │
└──────┬──────┘
│
┌────────────┼────────────┐
↓ ↓ ↓
Retrieval Tools Memory
在这种视角下,大语言模型能够突破自身训练参数的限制,与外部信息及能力进行交互。
Anthropic将信息检索、工具访问和内存功能视为增强手段,通过这些手段可将普通的LLM转变为构建更强大智能系统的基础组件。
这一点很重要,因为它明确了模型本身并不会神奇地变成完整的软件系统。
真正提供那些额外功能的是围绕模型开发的应用程序。
那么什么是工具调用?
在探讨MCP之前,先了解一些更基础的概念会有所帮助。
假设让LLM能够使用某个工具,比如:
get_weather(city)
随后有用户提问:
“科伦坡的天气如何?”
模型不会立即回答,而是会以请求的形式要求调用相应函数:
{
"name": "get_weather",
"arguments": {
"city": "Colombo"
}
}
实际执行该函数的是其所在的应用程序。
该执行过程可能会返回类似以下内容:
{
"temperature": 29,
"condition": "Partly cloudy"
}
这些输出会被反馈到模型的上下文窗口中。
之后,模型可以生成如下回复:
“科伦坡目前的温度为29摄氏度,天气为多云。”
这里的关键点在于:
大语言模型仅负责决定是否调用某个工具,实际执行该工具的是应用程序。
模型永远不会直接与天气服务建立连接。
工具调用并非MCP
这可以说是理解整个领域时最重要的区别之一。
工具调用与MCP解决的是两个不同的问题。
工具调用的核心在于以下两者之间的交互:
LLM
↓
Tool request
↓
Application
↓
Tool result
相比之下,MCP是一种旨在规范人工智能应用如何连接外部工具、数据源及上下文的标准协议。
Anthropic于2024年11月发布了MCP这一开放标准,旨在将人工智能助手与实际存储数据和工具的系统相连。
根据Anthropic自身的文档,MCP规范了应用程序向大语言模型输入上下文的方式,他们将其比作人工智能应用领域的USB-C接口。
总结来说:
Tool Calling
↓
How an LLM requests an action
MCP
↓
How AI applications can standardize connections
to external tools and data
换言之,这两种理念是相辅相成的,而非相互竞争。
MCP的实际价值
想象这样一个人工智能应用,它需要访问:
- GitHub
- PostgreSQL
- Google Drive
- Slack
- 本地文件系统
- 公司内部API
如果没有统一的协议,这些连接中的每一个可能都需要独立的定制线路。这样一来很容易出现如下这样的架构:
AI Application
├── Custom GitHub integration
├── Custom Slack integration
├── Custom PostgreSQL integration
├── Custom filesystem integration
└── Custom internal API integration
MCP通过定义一种标准化协议来充当AI应用与各种提供功能的外部系统之间的桥梁。从概念上来看,它更像是这样:
AI Application
│
MCP Client(s)
│
┌───────────────┼────────────────┐
↓ ↓ ↓
MCP Server MCP Server MCP Server
GitHub Database Files
│ │ │
↓ ↓ ↓
GitHub API PostgreSQL Filesystem
采用这种架构后,AI应用无需对每个后端系统都有深入的了解。相反,MCP服务器通过统一的协议层来展示其功能。
MCP架构
MCP是基于客户端-主机-服务器模型构建的。从高层次上看,它如下所示:
┌─────────────────────────────────────┐
│ HOST │
│ │
│ AI Application │
│ │
│ ┌──────────────────────────┐ │
│ │ MCP Client │ │
│ └────────────┬─────────────┘ │
└─────────────────┼───────────────────┘
│
│ MCP
↓
┌──────────────────┐
│ MCP Server │
│ │
│ Tools │
│ Resources │
│ Prompts │
└────────┬─────────┘
│
↓
External System
该架构中的关键角色说明如下。
主机
主机是负责协调整个交互过程的人工智能应用。它可以是以下几种形式:
- 人工智能编程助手
- 桌面端人工智能应用
- 开发者工具
- 定制开发的任务代理应用
MCP客户端
MCP客户端存在于主机内部,负责维持与MCP服务器之间的连接并确保其正常运行。
MCP服务器
MCP服务器本质上只是通过MCP协议提供各种功能的程序。它可能具备与以下方面相关的功能:
GitHub
Databases
Files
Cloud services
Internal systems
Development environments
重要的是,MCP服务器本身无需成为任务代理,也不需要包含任何人工智能推理功能。它的职责仅仅是提供特定的功能。
MCP的功能远不止工具而已
容易让人误解的一点是,认为MCP仅仅是一种“工具调用协议”。实际上,MCP定义的远不止工具这类概念。
工具
这些是模型能够调用的操作,例如:
create_issue()
search_repository()
query_database()
send_message()
资源
资源是指应用程序可以获取并作为上下文传递给模型的信息,例如:
file://project/README.md
database://schema
提示词
MCP还可以将可重复使用的提示词模板作为独立的元素来提供。
Anthropic的MCP文档明确区分了各元素的控制方:工具由模型控制,资源由应用程序控制,提示词则由用户控制。正是这种分层控制机制使得MCP不仅仅是一种复杂的函数调用方式。
完整示例
以如下请求为例:
“请显示这个GitHub仓库中的未解决问题。”
该流程的简化版本可能如下所示:
User
│
│ "Show me the open issues"
↓
AI Application
│
↓
LLM
│
│ decides a GitHub tool is needed
↓
Tool Call
│
↓
MCP Client
│
│ MCP
↓
GitHub MCP Server
│
↓
GitHub API
│
↓
Issue Data
│
↓
MCP Client
│
↓
LLM
│
↓
Final Answer
注意这里涉及了多少个不同的层次。模型会思考自己需要哪些信息,应用程序负责协调与执行,MCP提供了与外部功能交互的标准通道,而外部服务则实际完成工作。这些都是相互独立的职责,而非一个合并的步骤。
Docker的作用是什么?
通常你会看到MCP服务器被打包并作为Docker容器发布,例如:
AI Application
│
│ stdio
↓
Docker Container
│
↓
MCP Server
│
↓
External Service
需要明确的是,Docker本身并非MCP。Docker只是打包和运行MCP服务器的一种便捷方式而已。同一台服务器同样可以作为普通的本地进程运行,也可以作为远程服务来部署。该协议本身完全独立于你的部署方式。
STDIO与Streamable HTTP
MCP可以通过多种传输机制进行通信。
在本地集成场景下,MCP客户端可以将MCP服务器作为独立进程启动,并通过STDIO与其进行交互。
从概念上讲:
AI Application
│
│ stdin/stdout
↓
MCP Server Process
对于服务器位于远程的情况,MCP则依赖Streamable HTTP来实现通信。
AI Application
│
│ HTTP
↓
Remote MCP Server
正因如此,无论相关工具运行在开发者的本地机器上,还是作为远程服务运行,MCP都能正常工作。
MCP与REST API
另一个值得强调的差异在于MCP与普通REST API的区别。
REST API的交互方式如下:
Application
│
│ HTTP request
↓
REST API
│
↓
Data
MCP的交互方式则如下:
AI Application
│
│ MCP
↓
MCP Server
│
↓
REST API / Database / Filesystem / Other system
有趣的是,MCP服务器可以在内部自由调用REST API。
因此MCP并非为了取代REST而存在。
它更应被理解为建立在现有系统之上的、面向AI的层。
为何MCP如此引人关注
一旦想到多个AI应用都需要与多个外部工具进行交互,集成问题的规模就一目了然了。
如果没有统一的协议,就会出现类似这样的情况:
AI App A ───── Custom ───── GitHub
AI App A ───── Custom ───── Slack
AI App A ───── Custom ───── Database
AI App B ───── Custom ───── GitHub
AI App B ───── Custom ───── Slack
AI App B ───── Custom ───── Database
每新增一组应用与工具的组合,都可能需要编写新的集成代码。
而统一的协议则彻底改变了这一状况:
MCP
│
┌────────────┼────────────┐
↓ ↓ ↓
GitHub Slack Database
MCP MCP MCP
Server Server Server
这正是 Anthropic 将 MCP 作为开放标准发布而非仅限于 Claude 使用的原因。
此后,Anthropic 扩展了 MCP 的功能,使其能够支持远程服务器,并将有线 MCP 连接直接整合到其 API 和产品中。
但工具越多并不一定意味着智能体就更好
这正是 Anthropic 后续的工程工作变得有趣的地方。
人们很容易认为:
工具越多 = 智能体能力越强。
但这一假设在实践中并不成立。
Anthropic 对工具设计的研究表明,如果给智能体提供过多重叠或设计不当的工具,其表现反而可能会变差。
一个设计良好的工具应当具备明确且单一的功能,能够返回有用的信息,同时避免在模型的上下文窗口中产生不必要的冗余内容。
例如,与其使用三个独立的调用方式:
list_users()
list_transactions()
list_notes()
不如为智能体提供一种整合后的功能,比如:
get_customer_context()
因为这样更符合智能体实际想要完成的任务。
换言之,工具界面本身就成为了智能体所处环境的一部分。
工具是智能体的接口
这一观察结果引出了一个值得强调的更广泛观点:
工具应当以智能体为核心来设计,而非仅仅是对现有API的重新包装。
当由确定性程序调用时,传统的API完全能够正常工作。
不过,由大语言模型驱动的智能体则受制于不同的约束条件。
它必须应对以下问题:
- 有限的上下文窗口
- 概率性输出结果
- 偶尔会在选择合适工具时出错
- 偶尔会在生成正确参数时出错
- 请求内容本身的模糊性
正因如此,工具的描述方式至关重要。
看看这种描述有多模糊:
search(id)
与这种清晰得多的描述相比:
search_github_issues(
repository,
query,
state
)
为了让模型能够正确使用工具,它需要了解:
- 该工具的实际功能
- 何时应该使用该工具
- 每个输入参数的含义
- 输出结果的形式
- 该工具的局限性
Anthropic在工具工程方面的指导强调精确的命名、清晰的描述、明确的参数设定、有用的返回结果以及持续的评估。
上下文正逐渐成为智能体工程的重要组成部分
Anthropic最近还强调了即时上下文这一概念。
处理上下文的简单方法如下:
Load everything
↓
Put everything into context
↓
Ask the LLM to reason
这种做法很快就会遇到扩展性问题。
一种更可持续的模式如下:
Small amount of initial context
↓
Agent identifies what it needs
↓
Tool retrieves relevant information
↓
Relevant information enters context
↓
Agent continues
智能体不会预先加载模型可能需要的所有信息,而会在确定某信息确实必要时才获取它。
Anthropic将此视为智能体系统向“即时”上下文处理方式发展的体现。
这直接与MCP相关联。
MCP提供了通往外部功能的标准化路径,而智能体本身则决定何时获取内容以及具体获取什么。
智能体循环
将所有这些要素整合在一起后,整体架构就会显得更加合理。
智能体循环的简化版本如下:
┌──────────────┐
│ User │
└──────┬───────┘
↓
┌──────────────┐
│ LLM │
└──────┬───────┘
↓
Need a tool?
/ \
No Yes
↓ ↓
Answer Tool Call
↓
Tool/MCP
↓
Tool Result
│
└─────────┐
↓
LLM
│
┌──────────┴──────────┐
↓ ↓
Continue Answer
这一循环处于当今大多数智能体系统的核心位置。
Anthropic用极其简单的术语来解释:智能体本质上就是一个在循环中调用工具的LLM,环境反馈会决定它下一步该做什么。
围绕这一循环构建的周边系统可能会变得相当复杂,但其核心机制依然保持如此简单。
框架又如何呢?
像 LangGraph 这样的框架能够为开发者提供结构化的开发环境,从而让构建这类系统变得更加容易管理。
不过,仍有一个重要的注意事项需要牢记。
Anthropic 的建议是了解框架背后的运作机制:原始的 LLM 调用、工具定义、调度逻辑以及响应结果,而非将框架视为一个黑箱。
通常情况下,框架会暴露出类似以下内容:
Agent
├── State
├── Nodes
├── Tools
├── Routing
└── Execution
但在这些抽象层之下,实际的运作流程依然表现为:
LLM
↓
Messages
↓
Tool calls
↓
Tool execution
↓
Tool results
↓
LLM
理解这些较低层次的流程后,就能更轻松地分析框架本身,因为你可以清楚地看到它正在自动化处理什么,而不仅仅是盲目信任它的功能。
MCP 并不能替代智能体框架
需要明确的是,这些属于系统的不同层次,并非相互竞争的选项。
简化的堆栈可能如下所示:
┌─────────────────────────────┐
│ User Interface │
├─────────────────────────────┤
│ Agent / Workflow │
├─────────────────────────────┤
│ LLM / Model API │
├─────────────────────────────┤
│ Tool Calling │
├─────────────────────────────┤
│ MCP │
├─────────────────────────────┤
│ External Tools / Systems │
└─────────────────────────────┘
代理框架通常负责管理以下内容:
- 状态
- 执行流程
- 路由
- 循环
- 重试机制
- 工具执行
而MCP则规范了如何连接外部功能。
工具调用为模型提供了请求执行某项操作的机制。
这三者之间不存在替代关系。
一些常见的误解
“MCP是一种人工智能模型。”
不对。
MCP只是一种协议而已。
它没有自行生成文本或进行推理的能力。
“MCP可以替代函数调用。”
同样不对。
实际发生的情况是,MCP服务器可以提供各种工具,而AI应用则通过其现有的工具使用机制将这些工具呈现给模型。
“大语言模型会直接调用GitHub。”
通常不会。
模型只会生成使用工具的请求。
真正执行操作的是应用以及相关的工具基础设施。
“每个MCP服务器都需要Docker。”
错误。
Docker只是部署服务器的一种可能方式而已。
MCP关注的是通信和功能暴露,而非事物的容器化方式。
“MCP服务器就是AI智能体。”
不一定。
MCP服务器可能只提供一些简单的、确定性的操作,例如:
search()
read()
create()
update()
delete()
“MCP只对GitHub有用。”
远非如此。
MCP是一种通用协议,用于将人工智能应用与外部数据及功能相连接。Anthropic最初的公告就已提到可与GitHub、Slack、Google Drive、数据库以及各类开发环境等系统进行集成。
更重要的启示:智能体工程不仅仅是提示词工程
可以说,研究这些内容后最显著的视角转变就在于此。
构建真正有用的智能体系统并不仅仅是:
Write a clever prompt
↓
Use a powerful model
↓
Get a smart agent
其中涉及多个不同的工程层面:
Model
↓
Tool Selection
↓
Tool Definitions
↓
Tool Execution
↓
Context Management
↓
State / Memory
↓
Control / Guardrails
↓
Evaluation
Anthropic自身的技术文档也越来越倾向于从更广泛的系统层面来阐述构建智能体实际上需要什么。
举个例子,他们近期在评估智能体方面的研究重点在于考察多步骤行为、工具使用情况、状态变化以及随时间产生的适应性,而非仅根据最终生成的文本块来评判质量。
这代表了一种截然不同的人工智能应用设计思路。
我最感兴趣的部分
这里关键的转变其实并非:
Chatbot → Agent
更准确地说应该是:
LLM
↓
LLM + Tools
↓
LLM + Tools + External Context
↓
LLM + Tools + Context + Control Loop
↓
Agentic System
MCP通过为人工智能应用提供一种标准化的方式来接入外部能力,从而融入这一发展进程。
模型提供智能功能。
应用负责控制。
工具执行具体操作。
外部系统提供现实世界的信息与功能。
MCP则充当将人工智能应用与这些能力连接起来的标准化桥梁。
我目前的思维模型
在研究了工具调用、MCP以及Anthropic关于智能体系统的相关论述后,以下是最简化的架构图,展示了这些组件是如何相互配合的:
USER
│
↓
┌─────────────┐
│ LLM │
│ │
│ Reasoning │
│ Decision │
└──────┬──────┘
│
Tool request
│
↓
┌─────────────────┐
│ Agent Runtime │
│ │
│ State │
│ Control Flow │
│ Tool Execution │
└────────┬────────┘
│
↓
MCP / Tools
│
┌────────────┼────────────┐
↓ ↓ ↓
GitHub Database Files
│ │ │
└────────────┼────────────┘
↓
Tool Results
│
↓
LLM
│
↓
USER
模型本身并非完整的智能体。
单个工具也不是。
MCP同样不是。
所谓“智能体”,实际上是由围绕模型的系统构成的,这个系统使模型能够进行推理、采取行动、观察结果,并持续朝着目标前进。
最终结论
如果想要构建AI智能体,有四个概念值得深入掌握:
1. 工具调用
模型可以要求应用程序执行特定的工具。
2. 智能体循环
系统可以反复对某一情况进行分析、采取行动、观察结果,然后继续下一步。
3. MCP
一种用于将人工智能应用与外部工具、资源及上下文相连的标准协议。
4. 工具工程
工具的质量、其描述、参数、返回的上下文以及评估标准,都会极大地影响智能体的实际表现。
从 Anthropic 的工程实践中学到的最宝贵的经验或许是:
不要仅仅因为有能力就增加复杂性。
先从能够解决当前问题的最简单架构开始。只有当某些组件能带来实际好处时,再引入工作流、更多智能体、工具、内存、MCP 服务器等其他组件。
目标从来不是打造最复杂的智能体,而是构建一个能够可靠完成任务的系统。