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)的最佳实践总结而成。

相关推荐
BreezeJiang1 小时前
从零手写一个 AI 编程 Agent 之后,我终于理解了 Cursor 的核心原理
人工智能
进击切图仔1 小时前
基于千问的白盒蒸馏 SOP
运维·服务器·人工智能·python·效率
Token炼金师1 小时前
工程基础设施层:MLOps闭环断裂让模型上线即裸奔
人工智能·深度学习·llm
小雨青年1 小时前
【HarmonyOS 7开发者前瞻】06 HarmonyOS 7 AI 能力接入前,先用业务场景判断优先级
人工智能·华为·harmonyos
格子生意经2 小时前
GEO系统多引擎自适应算法实战解析
大数据·人工智能
咕泡科技2 小时前
AI 教培行业新标杆:咕泡科技以腾讯云 CDE× 湖师大校企 × 具身智能构建三重唯一性壁垒
人工智能·科技·腾讯云
俊哥V2 小时前
AI一周事件 · 2026-07-01 至 2026-07-07
人工智能·ai
Alan_6912 小时前
AI 时代的 API:大模型如何重塑接口设计
人工智能
四方云2 小时前
2026电销系统科普:直呼、回拨没有优劣之分,选对场景才高效
人工智能·机器人·销售成长·电销系统