Agent 与 LLM 的交互协议:从 ReAct 到工具调用

引言:Agent 的核心引擎

现代 AI Agent(如 Claude Code、Cursor Agent、Aider)能够自主完成编程、数据分析等复杂任务,其背后依赖两个核心层:

  • 工具执行层:通过 MCP 等协议与外部系统交互(文件读写、命令执行、API 调用)
  • 推理决策层:Agent Host 与 LLM 之间的交互协议,决定 Agent"何时做、做什么、怎么做"

本文聚焦于推理决策层------Agent 与 LLM 之间的交互协议。你将理解:

  • Agent Host 如何将工具能力"翻译"给 LLM
  • LLM 如何输出结构化的决策(思考 + 行动)
  • 为什么 ReAct 模式和 XML 格式成为行业标准
  • 一次完整的 Agent 推理循环是如何运转的

第一章:Agent Host 的双重身份

1.1 Agent Host 在架构中的定位

在 MCP 架构中,Agent Host(如 Claude Code)处于中间层:

  • 向下(工具层) :通过 MCP Client 与 Server 通信,发现并调用 read_filerun_commandget_weather 等工具
  • 向上(模型层) :将工具列表和对话历史组织成 Prompt,调用 LLM API,解析 LLM 的响应

LLM 不直接理解 MCP 协议 。它看到的不是 tools/list 或 JSON-RPC,而是经过 Host 转换后的、符合该模型 API 规范的工具定义。

1.2 为什么需要这层"翻译"?

不同 LLM 提供商的工具调用格式各不相同:

模型提供商 工具调用格式 关键字段
OpenAI Function Calling tools, tool_calls
Anthropic Tool Use tools, tool_use content block
Google Gemini Function Calling tools, functionCall

Agent Host 的核心职责之一,就是将 MCP 的标准化工具定义,转换为目标 LLM 所能理解的格式。这种"适配器模式"使得 Agent 可以灵活切换底层模型,而无需修改工具实现。

第二章:Agent ↔ LLM 交互全流程

2.1 整体流程图

复制代码
用户输入
    │
    ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Agent Host                                │
│                                                                 │
│  ① 发现工具                                     ② 格式转换     │
│  ┌─────────────────┐    ┌──────────────────────────────────┐  │
│  │ MCP Client      │    │ 将 MCP Tool 定义转换为           │  │
│  │ tools/list ────►│───►│ 目标 LLM 的 tools 参数格式       │  │
│  │ ◄─── Tool 列表  │    └──────────────────────────────────┘  │
│  └─────────────────┘                      │                    │
│                                           ▼                    │
│  ③ 发起 LLM 推理                          ④ 解析模型响应       │
│  ┌──────────────────────────────────┐  ┌────────────────────┐  │
│  │ 调用 LLM API,传入:              │  │ 检测响应中是否包含 │  │
│  │ - 系统提示(含 ReAct 指令)      │──►│ <function_calls>  │  │
│  │ - 用户消息                       │  │ 或 <final_response>│  │
│  │ - 转换后的工具定义               │  └────────────────────┘  │
│  └──────────────────────────────────┘           │              │
│                                                  ▼              │
│  ⑤ 执行工具                              ⑥ 结果回传            │
│  ┌─────────────────┐    ┌──────────────────────────────────┐  │
│  │ 解析 <function_ │    │ 将工具结果作为 tool 角色消息     │  │
│  │ calls> 提取参数 │───►│ 追加到对话历史,再次调用 LLM     │  │
│  │ 调用 MCP Client │    │ 直到 LLM 返回 <final_response>  │  │
│  └─────────────────┘    └──────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                                            ▼
                                     最终回复用户

2.2 步骤详解

步骤①:发现工具

Host 启动时,通过 MCP Client 向每个 Server 发送 tools/list,获取工具列表。每个 Tool 包含 namedescriptioninputSchema(JSON Schema 定义参数)。

步骤②:格式转换

Host 将 MCP Tool 定义转换为目标 LLM 的 tools 参数。以 OpenAI 为例:

python 复制代码
# MCP Tool 定义
{
    "name": "get_weather",
    "description": "获取指定城市的天气",
    "inputSchema": {"type": "object", "properties": {"city": {"type": "string"}}}
}

# 转换为 OpenAI 格式
{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "获取指定城市的天气",
        "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}
    }
}

步骤③:发起 LLM 推理

Host 构建 Prompt,包含:

  • 系统提示:明确要求模型按 ReAct 模式输出,使用 XML 标签(见第三章)
  • 对话历史:用户消息、之前的工具调用记录
  • 工具定义:转换后的 tools 参数

步骤④:解析模型响应

LLM 返回的响应通常有两种格式:

  • <function_calls>:要求调用工具
  • <final_response>:直接回答用户

Host 解析 XML,提取工具名称和参数。

步骤⑤:执行工具

Host 根据解析结果,通过 MCP Client 调用 tools/call,将参数传递给对应的 MCP Server。

步骤⑥:结果回传与循环

Host 将工具执行结果以 role: tool 的消息追加到对话历史,再次调用 LLM。重复③~⑥,直到 LLM 输出 <final_response>

第三章:ReAct 模式与 XML 交互格式

3.1 两条技术路线:原生 Function Call vs. XML Prompt

在开始深入之前,必须先澄清一个关键分歧。阅读 Agent 相关技术文章时,初学者最容易产生的困惑是:"为什么有的 Agent 用 JSON 返回工具调用,有的用 XML?"

这两种方式对应着两种不同的实现路线,且在实际的 API 调用中是互斥的

路线 实现方式 典型代表 优缺点
原生 Function Call 使用模型 API 内置的 tools 参数,模型在 tool_calls JSON 字段中返回结构化调用 OpenAI、Anthropic、Google 官方 API ✅ 稳定可靠,无需解析 ❌ 流式控制受限,难以获取思维链
XML Prompt 驱动 在 System Prompt 中内嵌工具定义,要求模型在纯文本中输出 XML 标签,Host 通过正则或流式解析器提取 Claude Code、Cursor、AutoGPT(早期) ✅ 流式可控,可获取 thinking,绕过模型限制 ❌ 依赖 Prompt 工程,解析容错成本高

虽然现代 LLM API 提供了原生的 Function Calling JSON 接口,但像 Claude Code、Cursor 等高级 Agent,为了获得更强的流式控制、思维链可见性、以及对长上下文的更好兼容性 ,往往选择绕过原生接口,在纯文本流中强制使用 XML 标签来输出决策。Host 接收到文本后,通过正则或流式 XML 解析器提取动作。

本文的其余部分聚焦于路线②(XML Prompt 驱动) ,这也是当前最先进 Agent 系统的共同选择。如果你使用原生 Function Calling,步骤④中你将从 response.tool_calls 读取结构化数据,而非解析 XML,但整体的"发现 → 决策 → 执行 → 观察"循环逻辑是相通的。

3.2 什么是 ReAct?

ReAct(Reasoning + Acting)是一种 Prompt 范式,要求 LLM 在每一步先输出推理过程,再输出行动决策。这种模式最早由 Google 在 2022 年提出,现已成为 Agent 系统的默认选择。

核心优势

  • 可解释性:开发者能追踪模型的决策路径,调试错误
  • 错误恢复:当工具返回意外结果时,模型可在下一轮思考中调整策略
  • 多步推理:复杂任务天然需要多轮思考-行动循环

3.3 XML 标签格式

在 XML Prompt 驱动路线下,LLM 的每次响应必须包含两个部分:

① 推理过程(<thinking>

xml 复制代码
<thinking>
用户询问北京天气。我看到工具列表中有 get_weather,正好可以完成这个任务。city 参数从问题中提取为"北京"。调用这个工具后,我就能获得准确信息。
</thinking>

② 行动决策(二选一)

  • 调用工具
xml 复制代码
<function_calls>
  <invoke name="get_weather">
    <parameter name="city">北京</parameter>
  </invoke>
</function_calls>
  • 直接回复
xml 复制代码
<final_response>
北京今天晴,气温 18°C ~ 26°C。
</final_response>

3.4 为什么选择 XML?

维度 XML 标签 JSON
流式解析 可增量解析(遇到开标签即可处理) 需完整 JSON 才能解析
自然语言嵌入 与自然文本融合良好 需要转义,干扰阅读
LLM 生成难度 更符合 LLM 的文本生成习惯 需要严格括号匹配,容易出错
可读性 清晰标记思考与行动 嵌套结构不易阅读

关键点:XML 标签是 Agent Host 与 LLM 之间的内部约定 ,不属于任何标准协议。不同 Agent 可能使用不同的标签名(如 <thought><action>),但本质都是"思考 + 行动"的二段式结构。

第四章:完整模拟交互------编程智能体查询天气

以下通过角色扮演,完整展示一个编程智能体(类似 Claude Code)与 LLM 的交互过程。

4.1 模拟设定

角色 职责
用户 提出查询请求
Agent Host 管理对话历史、解析 XML、执行工具、控制 ReAct 循环
LLM(小白) 输出 <thinking> + <function_calls><final_response>
MCP Server 提供工具(本例中包含 get_weather

工具列表(通过 MCP 发现):

工具名 描述 参数
read_file 读取文件 path
write_file 写入文件 path, content
run_command 执行命令 command
search_code 搜索代码 pattern, path
get_weather 获取天气(来自 MCP 天气 Server) city

4.2 LLM 的系统提示词(简化版)

text 复制代码
你是一个编程智能体,遵循 ReAct 模式。可用工具如下:
- get_weather(city): 获取城市天气

你的输出格式:
1. <thinking> 你的推理过程 </thinking>
2. 要么 <function_calls><invoke name="工具名"><parameter name="参数名">值</parameter></invoke></function_calls>
   要么 <final_response> 你的最终回答 </final_response>

只输出上述格式,不要添加其他文字。

4.3 交互日志

第 1 轮:用户提问,Host 发送给 LLM

复制代码
用户: 北京今天天气怎么样?

Host → LLM(小白):
<message>
  <conversation_history>[{"role":"user","content":"北京今天天气怎么样?"}]</conversation_history>
  <tools>
    <tool><name>get_weather</name><description>获取城市天气</description><parameters><parameter name="city" type="string"/></parameters></tool>
  </tools>
  <instruction>请按 ReAct 模式处理。</instruction>
</message>

LLM 响应:

xml 复制代码
<thinking>
用户询问北京天气。我看到 get_weather 工具正好可用,city 参数为"北京"。调用它即可获得数据。
</thinking>

<function_calls>
  <invoke name="get_weather">
    <parameter name="city">北京</parameter>
  </invoke>
</function_calls>

第 2 轮:Host 执行工具,回传结果

复制代码
Host(模拟 MCP 执行): get_weather 返回"北京今天晴,18°C~26°C,空气质量良好"

Host → LLM(小白):
<message>
  <conversation_history>
    [
      {"role":"user","content":"北京今天天气怎么样?"},
      {"role":"assistant","content":"<thinking>...</thinking>"},
      {"role":"tool","tool_call_id":"call_001","content":"北京今天晴,18°C~26°C,空气质量良好"}
    ]
  </conversation_history>
  <instruction>请根据工具结果生成最终回复。</instruction>
</message>

LLM 响应:

xml 复制代码
<thinking>
工具返回了北京天气详情:晴,18-26°C,空气质量良好。信息完整,可直接组织成自然语言回复用户。
</thinking>

<final_response>
北京今天晴,气温 18°C ~ 26°C,空气质量良好,非常适合户外活动!
</final_response>

第 3 轮:Host 返回给用户

复制代码
Host → 用户:
北京今天晴,气温 18°C ~ 26°C,空气质量良好,非常适合户外活动!

4.4 流程复盘

步骤 角色 动作 关键内容
用户 提问 自然语言
Host 打包请求 对话历史 + 工具定义 + ReAct 指令
LLM 思考 + 决策 <thinking> + <function_calls>
Host 执行工具 调用 MCP Server 的 get_weather
Host 回传结果 将工具结果追加到历史
LLM 再思考 + 最终回复 <thinking> + <final_response>
Host 返回给用户 最终回答

关键认知:LLM 从未直接接触 MCP 协议,它只看到 XML 格式的对话历史和工具定义。Host 完成了所有协议翻译和工具调度工作。

第五章:总结与认知

5.1 核心要点

  1. Agent Host 是唯一的协议翻译者

    • 向下(工具层):通过 MCP 发现和调用工具(JSON-RPC)
    • 向上(模型层):根据所选的实现路线(原生 Function Call 或 XML Prompt),将工具定义转换为 LLM 能理解的格式
  2. 两条路线,按需选择

    • 原生 Function Call:快速原型、标准应用、追求稳定性
    • XML Prompt 驱动:高级 Agent(Claude Code/Cursor)、追求流式控制和思维链可见性
  3. ReAct 模式是 Agent 推理的骨架

    • 每一步都包含"思考"(<thinking>)和"行动"(<function_calls><final_response>
    • 这种设计让 Agent 具备多步推理和错误恢复能力
  4. MCP 提供工具,ReAct 提供决策

    • MCP 解决了"如何调用工具"的问题(标准化接入层)
    • ReAct + XML 解决了"何时调用工具、如何决策"的问题(推理决策层)

5.2 从 MCP 到 Agent 的完整链路

复制代码
用户提问
    │
    ▼
┌──────────────────────────────────────────────────────────────┐
│                 Agent Host(如 Claude Code)                │
│                                                              │
│ ① MCP 发现工具       ② 构建 ReAct Prompt                   │
│  ┌────────────┐      ┌───────────────────────────────────┐ │
│  │ tools/list │      │ System: 工具列表 + XML 格式要求   │ │
│  │ ◄── Tool[] │      │ User: 用户问题                   │ │
│  └────────────┘      └───────────────────────────────────┘ │
│                                                              │
│ ③ 发送 Prompt 给 LLM(纯文本,是否使用原生 tools 参数可选)│
│ ④ LLM 返回文本(含 XML 标签 或 原生 tool_calls 字段)     │
│ ⑤ Host 解析决策(提取 XML 或反序列化 JSON)               │
│ ⑥ 执行工具(MCP Client → tools/call)                     │
│ ⑦ 将工具结果追加到历史,重复③~⑥,直到 LLM 输出 final    │
└──────────────────────────────────────────────────────────────┘
    │
    ▼
最终回答

5.3 Agent 与普通聊天的本质区别

维度 普通聊天 ReAct Agent
输出内容 直接回答 思考 + 行动(工具调用或回答)
交互轮次 单轮 多轮(思考-行动-观察循环)
能力边界 固定(模型训练时学到的知识) 可扩展(通过 MCP 接入任意工具)
可解释性 低(无法追踪决策路径) 高(<thinking> 暴露推理过程)
错误恢复 可基于工具错误信息重新决策

5.4 生产环境最佳实践

① 系统提示词设计

系统提示词应明确声明:

  • 模型的角色和职责
  • 可用的工具列表(名称、描述、参数)
  • 输出格式要求(XML 标签结构或 JSON 格式)
  • ReAct 模式的执行规则

② 工具描述优化

工具描述直接影响 LLM 调用的准确性,建议:

  • description 应包含"何时调用"的明确指引
  • 参数描述应说明格式和取值范围
  • 示例优于抽象描述

③ 错误处理

Agent Host 应处理:

  • 工具调用超时:设置合理超时,超时后向 LLM 返回错误消息
  • 解析失败:要求 LLM 重新输出或返回友好错误
  • 工具返回错误:将错误信息追加到对话历史,让 LLM 决定重试或降级

④ 对话历史管理

  • 长对话应截断或摘要,避免超出上下文窗口
  • 保留最近 N 轮推理-行动记录即可
  • 工具返回的大文件内容应考虑摘要后再追加

5.5 未来演进方向

根据最新的 MCP 规范演进方向,Agent-LLM 交互协议也在持续发展:

  • Tasks 扩展:支持长时间运行的工具调用,Agent 可在工具执行期间发送进度通知
  • 无状态核心:简化 Host 实现,降低维护成本
  • MCP Apps:为 Agent 带来 UI 交互能力,用户可在工具调用过程中提供实时反馈

这些变化将进一步增强 Agent 的自主性和交互性,但 ReAct 作为推理决策的核心模式,以及结构化输出(无论是 XML 还是 JSON)作为与 LLM 交互的主流方式,依然会保持其重要地位。

附录:Server-Side Sampling(已弃用)

A.1 什么是 Server-Side Sampling?

Server-Side Sampling 允许 MCP Server 通过 Client 向 Host 请求 LLM 采样。例如,一个代码分析 Server 可能需要 LLM 生成代码注释。这是 MCP 中为数不多的"反向"交互。

A.2 协议交互

Server 向 Client 发送 sampling/createMessage 请求:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "sampling/createMessage",
  "params": {
    "messages": [{"role": "user", "content": "请总结这段代码的功能"}],
    "maxTokens": 500
  }
}

Client(Host)将请求转发给 LLM,并将结果返回给 Server。

A.3 弃用说明

重要更新 :根据最新的 MCP 规范更新,Sampling 功能已被标记为 Deprecated(弃用)。其核心原因在于:

  1. 安全风险------恶意 Server 可能通过精心构造的提示词进行注入攻击,Host 难以完全防御
  2. 架构演进------MCP 趋向于更薄的协议层,让 Server 更独立,Server 应直接调用 LLM API,而非依赖 Host 中转

新实现不应采用此功能,现有实现应迁移到 Server 直接集成 LLM 提供商 API。

结语

Agent 与 LLM 的交互协议,决定了 Agent 能否高效、准确地完成复杂任务。理解并掌握这套协议,是构建可靠 AI Agent 系统的基础。

对于开发者而言,掌握这套协议意味着:

  • 你能选择正确的实现路线:原生 Function Call 适合快速原型,XML Prompt 驱动适合追求极致流式控制和可观测性的生产级 Agent
  • 你能更好地调试 Agent :通过 thinking 标签追踪模型的推理路径,定位错误决策的根源
  • 你能优化工具设计:精准的工具描述能显著提高模型调用的准确性,减少"幻觉调用"
  • 你能理解性能瓶颈:多次推理的延迟累积、上下文窗口的限制,都需要在系统设计时仔细考量

从 MCP 的标准化工具接入,到 ReAct 的结构化推理决策,再到 XML 或 JSON 的结构化输出控制------这三个层次共同构成了现代 AI Agent 的技术基座。无论技术如何演进,理解并掌握这套核心交互协议,都是深入 Agent 开发领域的必修课。


本文基于 MCP 规范及主流 Agent 实现(Claude Code、Cursor、Aider)的最佳实践总结而成。

相关推荐
小程故事多_8012 分钟前
从A2C、TRPO、PPO到GRPO,强化学习策略梯度算法完整演进与大模型落地实战解析
人工智能·算法
冬奇Lab18 分钟前
开源项目第176期:Better Harness — 不审查 diff,审查工作流本身,给 AI 编程 Agent 的五维评估框架
人工智能·开源·agent
冬奇Lab24 分钟前
代码库知识库系列(07):混合检索 BM25 + 向量——Q8 还是失败,而且总分退步了
人工智能
ajassi200039 分钟前
AI语音智能体开发日记(十一)为智能设备“声”临其境——详解音频资源自动化生成流程
人工智能·ai·ai编程
2601_949499941 小时前
400G组网低功耗优选!芯瑞科技400G VR4 QSFP112光模块赋能智算中心高速互联
大数据·人工智能·科技
GoAI1 小时前
# AI Agent 记忆框架横向对比报告总结
人工智能·大模型·llm·多模态
李昊哲小课2 小时前
fastapi sse websocket 奶茶店实时订单看板
人工智能·python·websocket·网络协议·fastapi·sse
万邦科技Lafite2 小时前
天猫商品评论API:评价内容中的用户情感倾向分析
人工智能·api·电商开放平台·淘宝开放平台·api开放接口
遇码2 小时前
认识 LakeMind:一款本地优先的开源 AI 数据探索工作台
人工智能·开源
格林威2 小时前
多相机微秒级对齐:硬件触发 vs PTP(IEEE 1588)方案实战对比
开发语言·人工智能·数码相机·机器学习·计算机视觉·视觉检测·机器视觉