Agent 交互协议全景调研:从模型输入到框架执行的完整解剖
深入六大主流 Agent 交互范式的实际消息格式、系统提示词设计、动作空间与观测空间定义,逐一展示模型真正看到什么、输出什么、框架如何执行、结果如何回传
概览
构建 Agent 系统时,最核心的设计决策不是选哪个模型,而是模型与外部世界之间的交互协议——模型收到什么格式的输入、输出什么格式的动作、框架如何解析执行、执行结果如何回传给下一轮。
本报告从协议层面深入解剖六大主流 Agent 交互范式,每一种都给出:
- 系统提示词(System Prompt)的实际结构
- 模型输入(Observation)的具体格式
- 模型输出(Action)的具体格式
- 框架执行的解析与调度机制
- 结果回传(Observation → 下一轮输入)的格式
- 完整交互 trace 示例
第一章 · ReAct:文本交织的思考-行动-观察循环
1.1 起源与定位
ReAct(Reasoning + Acting)是 2022 年由 Yao et al. 提出的 Agent 交互范式,核心思想是让模型在同一个生成过程中交替进行推理(Thought)和行动(Action),每次行动后接收环境返回的观察(Observation),形成闭环。
ReAct 是所有现代 Agent 框架的思想起源——即使是 Function Calling、CodeAct 等后续方案,本质上仍遵循”思考 → 行动 → 观察 → 思考”的循环结构。
1.2 系统提示词结构
You solve problems by interleaving reasoning and actions.
Available tools:
- search(query: str) -> list of snippets
- calc(expression: str) -> number
- lookup(term: str) -> definition
- finish(answer: str) -> terminate the loop
Format each step exactly as:
Thought: <one or two sentences about what to do next>
Action: <tool_name>(<arguments>)
Observation: <result — you will be given this>
Repeat Thought/Action/Observation until done.
When confident, call finish(answer) and stop.
关键设计要素:
- 明确列出可用工具的签名(名称 + 参数类型 + 返回类型)
- 严格定义三段式输出格式
- 必须定义终止动作(
finish),否则模型可能死循环 - 循环指令明确
1.3 单轮交互的消息流
模型输入(第 N 轮):
Thought: The user asked about the population of Tokyo. Let me search.
Action: search("Tokyo population 2026")
Observation: Tokyo's population is approximately 13.96 million (2026 estimate).
Thought: I have the answer. Let me verify the metropolitan area figure.
Action: search("Tokyo metropolitan area population")
Observation: The Greater Tokyo Area has about 37.4 million people.
Thought: [模型在此生成下一步推理]
模型输出:
Thought: I now have both figures. The city proper has ~14M, metro area ~37M.
Action: finish("Tokyo city proper: ~14 million; Greater Tokyo Area: ~37.4 million (2026)")
1.4 框架执行机制
┌─────────────────────────────────────────────┐
│ ReAct Harness │
│ │
│ 1. 将 system prompt + 历史 trace 拼接 │
│ 作为完整 prompt 发送给 LLM │
│ │
│ 2. 解析 LLM 输出: │
│ - 用正则匹配 "Action: xxx(yyy)" │
│ - 提取工具名和参数 │
│ │
│ 3. 路由到对应工具函数执行 │
│ │
│ 4. 将执行结果格式化为 │
│ "Observation: ..." 追加到 trace │
│ │
│ 5. 检查是否为终止动作(finish) │
│ - 是:返回最终答案 │
│ - 否:回到步骤 1 │
│ │
│ 6. 安全检查:步数超限则强制终止 │
└─────────────────────────────────────────────┘
1.5 优缺点分析
| 维度 | 评价 |
|---|---|
| 优点 | 实现简单、对模型无特殊要求(纯文本生成即可)、推理过程透明可解释 |
| 缺点 | 纯文本解析脆弱(模型可能输出格式不规范)、无法并行调用工具、工具参数无 schema 验证 |
| 适用场景 | 多跳搜索问题、探索性研究、环境不确定的任务 |
| 不适用 | 需要精确参数的 API 调用、高并发工具调用场景 |
第二章 · OpenAI Function Calling:结构化工具调用协议
2.1 核心机制
Function Calling 是当前工业界最主流的 Agent 交互协议。与 ReAct 的纯文本方式不同,Function Calling 在 API 层面定义了结构化的工具调用协议——模型输出的不是自由文本,而是严格符合 JSON Schema 的函数调用对象。
2.2 工具定义格式
{
"type": "function",
"name": "search_database",
"description": "Search the product database by keyword",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search keyword"
},
"limit": {
"type": "integer",
"description": "Max results to return"
}
},
"required": ["query"],
"additionalProperties": false
}
}
关键参数:
strict: true:启用严格模式,保证模型输出 100% 符合 schema(token 生成级别的约束,非后验校验)additionalProperties: false:禁止输出未定义的字段description:模型根据描述而非名称来决定调用哪个工具
2.3 完整五步交互流程
步骤一:用户发送请求
messages: [
{ role: "user", content: "帮我查一下库存中有多少台 MacBook Pro" }
]
tools: [search_database 定义, update_inventory 定义, ...]
步骤二:模型返回 function_call(非文本)
{
"stop_reason": "tool_calls",
"output": [
{
"type": "function_call",
"call_id": "call_abc123",
"name": "search_database",
"arguments": "{\"query\": \"MacBook Pro\", \"limit\": 10}"
}
]
}
注意:stop_reason 是 tool_calls 而非 stop,表示模型认为需要调用工具才能回答。
步骤三:框架解析并执行
tool_call = response.output[0]
args = json.loads(tool_call.arguments)
result = search_database(query=args["query"], limit=args["limit"])
步骤四:将结果回传给模型
messages: [
{ role: "user", content: "帮我查一下库存中有多少台 MacBook Pro" },
// 模型的 function_call 原样放入
{ type: "function_call", call_id: "call_abc123", name: "search_database", arguments: "..." },
// 执行结果
{
type: "function_call_output",
call_id: "call_abc123",
output: "[{\"name\": \"MacBook Pro 16\", \"stock\": 42}, {\"name\": \"MacBook Pro 14\", \"stock\": 67}]"
}
]
步骤五:模型生成最终回复(或继续调用工具)
{
"stop_reason": "stop",
"output": [
{
"type": "text",
"text": "库存中有两款 MacBook Pro:16 寸有 42 台,14 寸有 67 台,共 109 台。"
}
]
}
2.4 并行工具调用
模型可以在单次响应中返回多个 function_call:
{
"output": [
{ "type": "function_call", "call_id": "call_1", "name": "get_weather", "arguments": "{\"city\": \"北京\"}" },
{ "type": "function_call", "call_id": "call_2", "name": "get_weather", "arguments": "{\"city\": \"上海\"}" },
{ "type": "function_call", "call_id": "call_3", "name": "get_weather", "arguments": "{\"city\": \"深圳\"}" }
]
}
框架并行执行三个查询,一次性回传所有结果,模型在下一轮统一处理。这是 ReAct 无法做到的。
2.5 框架执行机制
用户消息 + 工具定义 → API 请求
↓
模型响应(stop_reason 判断)
├─ stop_reason = "stop" → 返回文本给用户,结束
└─ stop_reason = "tool_calls" → 解析 function_call
↓
按 call_id 路由到工具函数 → 执行
↓
构造 function_call_output(call_id 必须对应)
↓
拼接到 messages 数组 → 再次请求 API
↓
... 循环直到 stop_reason = "stop"
2.6 优缺点分析
| 维度 | 评价 |
|---|---|
| 优点 | 结构化输出(严格 JSON)、支持并行调用、schema 验证保证参数合法、工业标准 |
| 缺点 | 工具集必须预定义、无法动态组合工具逻辑(如条件判断)、每次调用需要完整 API 往返 |
| 适用场景 | 大多数生产环境 Agent、API 集成、工具数量已知的场景 |
| 不适用 | 需要灵活编程逻辑的场景(此时 CodeAct 更优) |
第三章 · CodeAct:代码即动作的统一范式
3.1 核心洞察
CodeAct(ICML 2024)的核心洞察是:Python 代码本身就是最好的 action 语言。它既有严格的语法(易于执行),又有无限的表达力(图灵完备),还天然支持工具组合和调试。
与 Function Calling 相比,CodeAct 不需要预定义工具的 JSON schema——任何 Python 函数都是可用工具,任何 Python 逻辑都是可用动作。
3.2 系统提示词
You are a helpful assistant that can interact with a computer to solve tasks.
Available Actions:
You can perform actions by writing Python code enclosed in:
<execute>
your_python_code_here
</execute>
Guidelines:
- You can use any Python libraries available in the environment.
- Each code block will be executed in a stateful Python interpreter
(like a Jupyter notebook), meaning variables and imports persist
across turns.
- You will receive the execution output (stdout/stderr) as observations.
- Based on the observations, you can revise your code or take new actions.
- When the task is complete, communicate the final result in natural language.
Interaction Protocol:
- Use <execute>...</execute> for code actions
- Use natural language for communicating with the user
- You can mix code actions and natural language in your responses
关键设计:
- 有状态解释器(变量跨轮次保持,类似 Jupyter Notebook)
<execute>标签界定代码边界- 双通道输出:既能执行代码,也能自然语言交流
3.3 完整交互 trace 示例
═══ 用户 ═══
查询波士顿天气,如果低于 50°F 就在日历添加"带外套"提醒。
═══ Agent Turn 1 ═══
我来查询天气并根据条件设置提醒。
<execute>
weather = get_weather("Boston")
print(f"Temperature: {weather['temp']}°F")
if weather['temp'] < 50:
result = add_calendar_event(title="带外套", date="today")
print(f"Reminder set: {result}")
else:
print("No jacket needed!")
</execute>
═══ Observation ═══
Temperature: 42°F
Reminder set: Event '带外套' added for 2026-04-22
═══ Agent Turn 2 ═══
波士顿今天只有 42°F,我已经在日历中添加了"带外套"提醒。
对比 Function Calling:Function Calling 需要分两次 API 往返(先查天气、再根据结果决定是否加提醒)。CodeAct 在一次代码执行中通过 if 语句完成了条件判断和组合调用。
3.4 自动调试(错误恢复)
CodeAct 的有状态解释器使得自动调试成为可能:
═══ Agent Turn 1 ═══
<execute>
model = SVC(kernal='rbf') # 拼写错误
model.fit(X_train, y_train)
</execute>
═══ Observation ═══
TypeError: __init__() got an unexpected keyword argument 'kernal'
═══ Agent Turn 2 ═══
参数名拼写错误,应该是 'kernel'。
<execute>
model = SVC(kernel='rbf') # 修正
model.fit(X_train, y_train)
acc = accuracy_score(y_test, model.predict(X_test))
print(f"Accuracy: {acc:.4f}")
</execute>
═══ Observation ═══
Accuracy: 0.9667
注意 Turn 2 不需要重新导入库或加载数据——有状态解释器保留了 Turn 1 中定义的所有变量。
3.5 框架执行机制
用户请求
↓
LLM 生成文本(可能包含 <execute> 代码块)
↓
Harness 解析:
├─ 自然语言部分 → 直接展示给用户
└─ <execute> 代码块 → 发送到 Python 解释器
↓
Python 解释器执行代码(有状态,变量持久化)
↓
捕获 stdout + stderr → 作为 Observation
↓
Observation 追加到对话历史 → 下一轮 LLM 调用
3.6 CodeAct vs Function Calling vs ReAct
| 维度 | ReAct | Function Calling | CodeAct |
|---|---|---|---|
| Action 格式 | 自由文本 | 结构化 JSON | Python 代码 |
| 工具组合 | 不支持(每轮一个工具) | 并行但无逻辑组合 | 任意组合(if/for/变量传递) |
| 参数验证 | 无 | JSON Schema 严格验证 | Python 类型系统 |
| 调试能力 | 无 | 无 | 根据 stderr 自动修正 |
| 状态管理 | 无(每轮独立) | 无 | 有状态(变量持久化) |
| 灵活性 | 低 | 中 | 最高(图灵完备) |
| 解析可靠性 | 低(正则匹配) | 高(API 原生) | 中(标签解析) |
第四章 · SWE-agent ACI:为 LLM 定制的编程界面
4.1 设计哲学
SWE-agent(Princeton, 2024)提出了 Agent-Computer Interface(ACI)的概念:正如 HCI 为人类设计交互界面,ACI 为 LLM 设计交互界面。核心原则是——操作简洁、反馈信息化、错误可恢复。
4.2 系统提示词
SYSTEM MESSAGE:
You are an autonomous programmer working directly in the command line
with a special interface.
The special interface consists of a file editor that shows you 100 lines
at a time. In addition to typical bash commands, you can also use:
COMMANDS:
open <path> [<line_number>] opens file at given line
goto <line_number> moves window to show line
scroll_down moves window down 100 lines
scroll_up moves window up 100 lines
create <filename> creates and opens new file
search_dir <term> [<dir>] searches in all files in dir
search_file <term> [<file>] searches in file
find_file <name> [<dir>] finds files with given name
edit <start>:<end>
<replacement_text>
end_of_edit replaces lines start to end
submit submits solution and terminates
RESPONSE FORMAT:
Every response must include exactly ONE thought and ONE command.
DISCUSSION
<Your reasoning here>
COMMAND
<your command here>
IMPORTANT TIPS:
1. Always start by trying to replicate the bug.
2. If a command doesn't work, try a different command.
3. Use goto instead of repeated scroll_down.
4. Always check indentation when editing.
5. Make single, focused changes at a time.
4.3 Observation 格式
文件查看器(窗口化浏览,核心创新):
[File: /repo/src/parser.py (250 lines total)]
(148 more lines above)
149: class InputParser:
150: def __init__(self, config):
151: self.config = config
152: self.buffer = []
153:
154: def _parse_input(self, raw_data):
155: # BUG: doesn't handle None input
156: tokens = raw_data.split(',')
157: return [t.strip() for t in tokens]
(93 more lines below)
关键设计:固定 100 行窗口防止输出过长、行号标注便于定位、上下文提示告知还有多少行。
搜索结果:
Found 3 matches for "parse_input" in /repo/src:
/repo/src/parser.py (Line 154): def _parse_input(self, raw_data):
/repo/src/parser.py (Line 160): result = self._parse_input(data)
/repo/src/tests/test_parser.py (Line 23): parser._parse_input(test_data)
编辑反馈(含自动语法检查):
File updated. Please review the changes and make sure they are correct.
或失败时:
Your edit has introduced syntax errors:
File "/repo/src/parser.py", line 156
return []
^
IndentationError: unexpected indent
The file has been reverted to its original state.
Please fix the error and try again.
这是 ACI 的关键安全机制——编辑引入语法错误时自动回滚并提示。
4.4 完整交互 trace
╔══ TURN 1 ══╗
OBSERVATION (System):
We're solving: InputParser crashes when input is None
ENVIRONMENT REMINDER: You have 30 steps remaining.
DISCUSSION:
Let me find the relevant file first.
COMMAND:
find_file "parser.py" src
╔══ TURN 2 ══╗
OBSERVATION:
Found 1 matches: /repo/src/parser.py
DISCUSSION:
Let me open the file and look at the parse_input method.
COMMAND:
open /repo/src/parser.py 150
╔══ TURN 3 ══╗
OBSERVATION:
[File: /repo/src/parser.py (250 lines total)]
(148 more lines above)
149: class InputParser:
...
156: tokens = raw_data.split(',')
(93 more lines below)
DISCUSSION:
Line 156 calls raw_data.split() without checking for None.
COMMAND:
edit 154:157
def _parse_input(self, raw_data):
if raw_data is None:
return []
tokens = raw_data.split(',')
return [t.strip() for t in tokens]
end_of_edit
╔══ TURN 4 ══╗
OBSERVATION:
File updated. Please review the changes...
DISCUSSION:
Fix looks correct. Let me run the tests.
COMMAND:
python -m pytest tests/test_parser.py -v
╔══ TURN 5 ══╗
OBSERVATION:
tests/test_parser.py::test_none_input PASSED
tests/test_parser.py::test_normal_input PASSED
All 5 tests passed.
DISCUSSION:
All tests pass. Submitting.
COMMAND:
submit
4.5 ACI 消融实验结果
| 组件 | SWE-bench Lite 提升 |
|---|---|
| 原始 Bash(无 ACI) | ~6% baseline |
| + 文件查看器(窗口化) | +3% |
| + edit 命令 | +5% |
| + 语法检查 + 回滚 | +2% |
| + 搜索命令 | +2% |
每个 ACI 组件都有可测量的贡献,证明了界面设计对 Agent 性能的实质影响。
第五章 · Computer Use:截图驱动的 GUI 交互
5.1 核心机制
Computer Use(Anthropic, 2024)是最接近”像人一样操作电脑”的 Agent 交互方式。模型通过看截图来理解当前屏幕状态,通过输出鼠标/键盘指令来操作电脑。
5.2 工具定义(API 层面)
tools = [
{
"type": "computer_20251124",
"name": "computer",
"display_width_px": 1024,
"display_height_px": 768,
"display_number": 1,
},
{
"type": "text_editor_20250728",
"name": "str_replace_based_edit_tool"
},
{
"type": "bash_20250124",
"name": "bash"
}
]
注意:Computer Use 通常与 text_editor 和 bash 工具组合使用。模型可以自主选择用截图操作 GUI 还是用 bash 命令行。
5.3 交互流程
第一轮:模型请求截图
模型输出:
{
"type": "tool_use",
"id": "toolu_001",
"name": "computer",
"input": { "action": "screenshot" }
}
框架执行:截取当前屏幕 → 缩放到 API 限制(长边 1568px)→ base64 编码
结果回传:
{
"type": "tool_result",
"tool_use_id": "toolu_001",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "<base64 编码的截图>"
}
}
]
}
第二轮:模型发出操作指令
{
"type": "tool_use",
"id": "toolu_002",
"name": "computer",
"input": { "action": "left_click", "coordinate": [500, 300] }
}
框架执行:将 API 坐标反向缩放到实际屏幕坐标 → 执行点击
5.4 完整动作集
| 动作 | 格式 | 说明 |
|---|---|---|
| screenshot | {"action": "screenshot"} | 截取当前屏幕 |
| left_click | {"action": "left_click", "coordinate": [x, y]} | 左键点击 |
| type | {"action": "type", "text": "..."} | 输入文本 |
| key | {"action": "key", "key": "ctrl+s"} | 按键/组合键 |
| scroll | {"action": "scroll", "coordinate": [x,y], "direction": "down", "amount": 3} | 滚动 |
| drag | {"action": "left_click_drag", "start_coordinate": [x1,y1], "coordinate": [x2,y2]} | 拖拽 |
| double_click | {"action": "double_click", "coordinate": [x, y]} | 双击 |
| zoom | {"action": "zoom", "region": [x1, y1, x2, y2]} | 查看区域原始分辨率 |
| wait | {"action": "wait", "duration": 3} | 等待 N 秒 |
5.5 坐标缩放处理
高分辨率屏幕的截图会被缩放到 API 限制,框架需要处理坐标映射:
# 计算缩放因子
scale = min(1.0, 1568 / max(width, height))
# 发送截图前:缩放图片
scaled_img = resize(screenshot, scale)
# 模型返回坐标后:反向缩放到实际屏幕坐标
actual_x = model_x / scale
actual_y = model_y / scale
5.6 完整交互 trace
═══ 用户 ═══
Save a picture of a cat to my desktop.
═══ Turn 1 ═══
模型: {"action": "screenshot"}
框架: [截图] → base64 PNG 回传
模型看到: 桌面截图
═══ Turn 2 ═══
模型: {"action": "key", "key": "super"}
框架: 按下 Super 键打开应用启动器
模型: {"action": "screenshot"}
框架: [截图]
═══ Turn 3 ═══
模型: {"action": "type", "text": "firefox"}
框架: 输入 "firefox"
模型: {"action": "key", "key": "Return"}
框架: 按回车
═══ Turn 4 ═══
模型: {"action": "screenshot"}
框架: [截图] → Firefox 已打开
═══ Turn 5 ═══
模型: {"action": "left_click", "coordinate": [400, 50]} // 地址栏
模型: {"action": "type", "text": "cute cat picture"}
模型: {"action": "key", "key": "Return"}
... (搜索、右键保存、选择桌面路径等后续操作)
═══ 最终 ═══
模型: "I've saved a picture of a cat to your desktop."
5.7 Token 消耗
| 项目 | Token 消耗 |
|---|---|
| 系统 prompt 额外开销 | ~470 tokens |
| 每个工具定义 | ~735 tokens |
| 每张截图 | 按 Vision 定价(分辨率相关) |
| 一个典型任务(10 步) | 数万 tokens |
第六章 · OSWorld / BrowserGym:环境标准化协议
6.1 OSWorld 观测-动作空间
OSWorld(NeurIPS 2024)为 Agent 与操作系统的交互定义了标准化的接口。
Agent 必须实现的核心方法:
class Agent:
def predict(self, instruction: str, observation: dict) -> (str, list):
"""
输入:
instruction: 任务描述
observation: {
"screenshot": bytes, # PNG 编码截图
"accessibility_tree": str # XML 格式无障碍树
}
输出:
response: str # LLM 原始响应
actions: list # 解析后的动作列表
"""
def reset(self):
"""新任务时清除内部状态"""
四种观测类型:
| 类型 | 模态 | 格式 |
|---|---|---|
| screenshot | 纯视觉 | base64 PNG |
| a11y_tree | 纯结构化 | TSV(制表符分隔) |
| screenshot_a11y_tree | 视觉+文本 | PNG + TSV(性能最佳) |
| som | 标注视觉 | 带数字标签的 PNG |
无障碍树(a11y_tree)格式:
tag name text class position size
button OK "" GtkButton (100,200) (80,30)
text search "Enter query" GtkEntry (50,100) (200,25)
两种动作空间:
| 空间 | 格式 | 示例 |
|---|---|---|
| pyautogui | Python 代码 | pyautogui.click(500, 300) |
| computer_13 | JSON 字典 | {"action": "left_click", "coordinate": [500, 300]} |
6.2 BrowserGym 动作原语
BrowserGym 为 Web Agent 定义了一套基于 bid(Browser element ID) 的操作原语:
# 鼠标操作
click("btn_submit")
dblclick("item_row_3")
hover("menu_dropdown")
drag_and_drop("card_1", "column_2")
# 键盘操作
fill("input_search", "hello world")
clear("input_search")
press("textarea_code", "Control+Enter")
type("input_name", "Maxwell")
# 页面操作
scroll(0, 300)
goto("https://example.com")
go_back()
tab_focus(2)
new_tab()
# 任务完成
send_msg_to_user("The answer is 42")
report_infeasible("Cannot access the required page")
noop(wait_ms=2000)
bid 机制:框架对页面 DOM 元素自动标注唯一 ID,Agent 通过 bid 引用元素而非坐标——比坐标更稳定、更语义化。
6.3 系统提示词选择矩阵
OSWorld 根据观测类型和动作空间的组合自动选择系统提示词:
| 观测 | 动作 | 对应提示词 |
|---|---|---|
| screenshot | pyautogui | 视觉输入 + 代码输出 |
| screenshot | computer_13 | 视觉输入 + JSON 输出 |
| a11y_tree | pyautogui | 文本输入 + 代码输出 |
| screenshot + a11y_tree | pyautogui | 多模态输入 + 代码输出(效果最佳) |
| som | pyautogui | 标注视觉 + tag 引用输出 |
第七章 · MCP:标准化工具接入协议
7.1 定位
Model Context Protocol(MCP, Anthropic, 2024)不是一种 Agent 交互范式,而是一种工具接入标准化协议。它解决的是”如何让任意工具以统一方式对接到任意 LLM”的问题。
7.2 消息格式(JSON-RPC 2.0)
工具列表查询:
// 请求
{"jsonrpc": "2.0", "id": "1", "method": "tools/list", "params": {}}
// 响应
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"tools": [
{
"name": "search",
"description": "Search the web",
"inputSchema": {
"type": "object",
"properties": {
"query": {"type": "string"}
},
"required": ["query"]
}
}
]
}
}
工具调用:
// 请求
{
"jsonrpc": "2.0", "id": "2",
"method": "tools/call",
"params": {
"name": "search",
"arguments": {"query": "MCP protocol"}
}
}
// 响应
{
"jsonrpc": "2.0", "id": "2",
"result": {
"content": [
{"type": "text", "text": "MCP is an open protocol..."}
]
}
}
7.3 MCP 在 Agent 交互中的位置
LLM ←→ Agent Framework ←→ MCP Client ←→ MCP Server ←→ 外部工具
(交互协议层) (标准化接入层) (实际工具)
MCP 位于交互协议和实际工具之间——Agent 框架(无论用 ReAct 还是 Function Calling)通过 MCP 客户端发现和调用工具,MCP 服务器负责翻译和执行。
第八章 · 对比分析与选型指南
8.1 六大范式核心对比
| 维度 | ReAct | Function Calling | CodeAct | SWE-agent ACI | Computer Use | BrowserGym |
|---|---|---|---|---|---|---|
| Action 格式 | 自由文本 | JSON | Python 代码 | 自定义命令 | JSON + 坐标 | bid 函数调用 |
| Observation 格式 | 文本 | JSON/文本 | stdout/stderr | 窗口化文本 | 截图(base64) | DOM/截图 |
| 工具定义 | prompt 内文本 | JSON Schema | Python 环境 | 预定义命令集 | 固定三件套 | 预定义原语 |
| 状态管理 | 无 | 无 | 有状态解释器 | Shell 环境 | 屏幕状态 | 浏览器 session |
| 并行调用 | 不支持 | 支持 | 代码内并行 | 不支持 | 不支持 | 不支持 |
| 错误恢复 | 手动 | 手动 | 自动调试 | 自动回滚 | 重新截图 | 页面回退 |
| 解析可靠性 | 低 | 最高 | 中 | 中 | 高 | 中 |
| 表达力 | 低 | 中 | 最高 | 中 | 最高(任意 GUI) | 高(Web) |
| Token 效率 | 高 | 高 | 高 | 中 | 低(截图大) | 中 |
8.2 选型决策树
你的 Agent 需要操作什么?
├─ 调用 API / 查询数据库
│ ├─ 工具集固定、参数明确 → Function Calling
│ └─ 需要灵活组合多个工具 → CodeAct
├─ 编写/修改代码
│ ├─ 修复 GitHub Issue → SWE-agent ACI
│ └─ 通用编程任务 → CodeAct
├─ 操作网页
│ ├─ 可访问 DOM → BrowserGym
│ └─ 只能看截图 → Computer Use
├─ 操作桌面软件
│ └─ Computer Use
└─ 多跳搜索 / 知识推理
└─ ReAct
8.3 从数据合成角度的启示
对于构建 Agent 训练数据,每种交互协议对应不同的数据格式需求:
| 训练目标 | 推荐数据格式 | 数据源 |
|---|---|---|
| Function Calling 能力 | messages + tool_calls + tool_results 三元组 | API 文档 → 自动化生成 |
| ReAct 推理 | Thought-Action-Observation 轨迹 | 人工标注 + 模型蒸馏 |
| CodeAct 编程 | execute 代码块 + stdout 观测对 | Jupyter Notebook 执行记录 |
| SWE-agent 代码修复 | issue → 修复轨迹 → 测试验证 | GitHub Issue + PR |
| Computer Use GUI 操作 | 截图序列 + 坐标动作 | 屏幕录制 + 动作标注 |
| Web Agent | DOM/bid + 浏览器动作 | 网站操作录制 |
第九章 · 演进趋势与展望
9.1 短期趋势(2026-2027)
Function Calling 标准化加速:OpenAI Responses API 统一了 tool calling 格式,MCP 协议提供了工具接入标准。两者结合正在形成事实上的工业标准。
CodeAct 渗透 SWE 领域:OpenHands CodeAct 2.1 已在 SWE-bench Verified 上达到 53%,Function Calling 格式化后可靠性进一步提升。代码执行作为 action space 的优势在软件工程领域已经得到验证。
9.2 中期趋势(2027-2028)
GUI + Code 混合模式:推测 Agent 会发展出自适应的动作空间选择——能用代码直接操作的用代码,必须看界面的用 GUI 操作。Computer Use 和 CodeAct 的融合将成为通用 Agent 的标配。
Observation 压缩技术:截图类 Agent 的 token 消耗是核心瓶颈。视觉 token 压缩(VisionTrim、VisionSelector 等)和选择性截图(只截变化区域)将大幅降低成本。
9.3 长期展望
从交互协议到自适应协议:未来的 Agent 可能不需要固定在某一种交互范式中。模型自己判断当前任务适合用哪种 action space(打字比点击高效就打命令,GUI 比命令直观就点击),动态切换交互方式。
从工具调用到环境理解:当前所有范式的共同假设是”工具是预定义的”。但 Gym-Anything 的方向暗示,未来 Agent 可能具备”理解任意新环境”的能力——不需要预先定义 action space,而是通过观察自行推断可用操作。
核心论文与参考索引
| 论文/项目 | 年份 | 核心贡献 |
|---|---|---|
| ReAct (Yao et al.) | 2022 | 提出 Thought-Action-Observation 交织范式 |
| Toolformer | 2023 | 模型自主学习何时调用工具 |
| GAIA Benchmark | 2023 | 通用 AI 助手基准,450 道现实任务 |
| OpenAI Function Calling | 2023 | 结构化工具调用 API 标准 |
| SWE-agent ACI | 2024 | 为 LLM 定制的编程交互界面 |
| CodeAct (ICML 2024) | 2024 | 代码作为统一动作空间 |
| Computer Use (Anthropic) | 2024 | 截图驱动的 GUI Agent |
| OSWorld (NeurIPS 2024) | 2024 | 操作系统级标准化 Agent 接口 |
| BrowserGym | 2024 | Web Agent 标准化环境 |
| WebArena | 2024 | 自托管 Web 环境基准 |
| MCP (Anthropic) | 2024 | 标准化工具接入协议 |
| OpenHands CodeAct 2.1 | 2025 | 代码 Agent SOTA(SWE-bench 53%) |
| Gym-Anything (CMU) | 2026 | 自动化环境构建框架 |