AI Agent 核心架构总览:从 ReAct 循环到分层设计
面向想系统构建 Agent 的开发者。本文先给速查表建立全景认知,再逐层深入原理,最后给出架构设计原则。读完你能画出完整的 Agent 架构图,并能为每个层级做技术选型。
一、概念速查
1.1 什么是 AI Agent
AI Agent(智能体)是一个能自主感知环境、做出决策、执行行动的 AI 系统。与普通 LLM 调用的"问一句答一句"不同,Agent 能主动拆解目标、调用工具、多步推理、直至完成任务。
| 维度 | 普通 LLM 调用 | Agent 系统 |
|---|---|---|
| 交互方式 | 一问一答 | 多轮推理 + 行动循环 |
| 工具使用 | 无(纯文本输出) | 调用 API / 执行代码 / 搜索 |
| 记忆能力 | 仅上下文窗口 | 短期 + 长期记忆 |
| 任务自主性 | 被动响应 | 主动拆解 + 规划 |
| 输出形式 | 文本 | 行动 + 结果 + 文本 |
1.2 核心术语速查
| 术语 | 定义 |
|---|---|
| ReAct | 推理(Reasoning)+ 行动(Acting)交替循环的模式 |
| Function Calling | LLM 输出结构化参数以触发外部函数执行的机制 |
| MCP | Model Context Protocol,统一 Agent 接入外部工具的协议标准 |
| Tool / Skill | Agent 可调用的外部能力单元(搜索、计算、API) |
| Memory | 记忆模块,分短期(对话窗口)和长期(向量检索) |
| 编排(Orchestration) | 控制 Agent 下一步做什么的逻辑(循环、分支、并行、持久化) |
| State | 编排层共享的"黑板",所有节点读写同一份状态数据 |
1.3 架构分层速查
一个生产级 Agent 系统从底到顶分 4 层:
#mermaid-svg-RNrCAu5GAGUTC3wj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RNrCAu5GAGUTC3wj .error-icon{fill:#552222;}#mermaid-svg-RNrCAu5GAGUTC3wj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RNrCAu5GAGUTC3wj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RNrCAu5GAGUTC3wj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RNrCAu5GAGUTC3wj .marker.cross{stroke:#333333;}#mermaid-svg-RNrCAu5GAGUTC3wj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RNrCAu5GAGUTC3wj p{margin:0;}#mermaid-svg-RNrCAu5GAGUTC3wj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RNrCAu5GAGUTC3wj .cluster-label text{fill:#333;}#mermaid-svg-RNrCAu5GAGUTC3wj .cluster-label span{color:#333;}#mermaid-svg-RNrCAu5GAGUTC3wj .cluster-label span p{background-color:transparent;}#mermaid-svg-RNrCAu5GAGUTC3wj .label text,#mermaid-svg-RNrCAu5GAGUTC3wj span{fill:#333;color:#333;}#mermaid-svg-RNrCAu5GAGUTC3wj .node rect,#mermaid-svg-RNrCAu5GAGUTC3wj .node circle,#mermaid-svg-RNrCAu5GAGUTC3wj .node ellipse,#mermaid-svg-RNrCAu5GAGUTC3wj .node polygon,#mermaid-svg-RNrCAu5GAGUTC3wj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RNrCAu5GAGUTC3wj .rough-node .label text,#mermaid-svg-RNrCAu5GAGUTC3wj .node .label text,#mermaid-svg-RNrCAu5GAGUTC3wj .image-shape .label,#mermaid-svg-RNrCAu5GAGUTC3wj .icon-shape .label{text-anchor:middle;}#mermaid-svg-RNrCAu5GAGUTC3wj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RNrCAu5GAGUTC3wj .rough-node .label,#mermaid-svg-RNrCAu5GAGUTC3wj .node .label,#mermaid-svg-RNrCAu5GAGUTC3wj .image-shape .label,#mermaid-svg-RNrCAu5GAGUTC3wj .icon-shape .label{text-align:center;}#mermaid-svg-RNrCAu5GAGUTC3wj .node.clickable{cursor:pointer;}#mermaid-svg-RNrCAu5GAGUTC3wj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RNrCAu5GAGUTC3wj .arrowheadPath{fill:#333333;}#mermaid-svg-RNrCAu5GAGUTC3wj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RNrCAu5GAGUTC3wj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RNrCAu5GAGUTC3wj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RNrCAu5GAGUTC3wj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RNrCAu5GAGUTC3wj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RNrCAu5GAGUTC3wj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RNrCAu5GAGUTC3wj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RNrCAu5GAGUTC3wj .cluster text{fill:#333;}#mermaid-svg-RNrCAu5GAGUTC3wj .cluster span{color:#333;}#mermaid-svg-RNrCAu5GAGUTC3wj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RNrCAu5GAGUTC3wj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RNrCAu5GAGUTC3wj rect.text{fill:none;stroke-width:0;}#mermaid-svg-RNrCAu5GAGUTC3wj .icon-shape,#mermaid-svg-RNrCAu5GAGUTC3wj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RNrCAu5GAGUTC3wj .icon-shape p,#mermaid-svg-RNrCAu5GAGUTC3wj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RNrCAu5GAGUTC3wj .icon-shape .label rect,#mermaid-svg-RNrCAu5GAGUTC3wj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RNrCAu5GAGUTC3wj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RNrCAu5GAGUTC3wj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RNrCAu5GAGUTC3wj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 编排层 (Orchestration)
ReAct 循环 · 状态机 · 多 Agent 协作
LangGraph / 百炼 / CrewAI
模型层 (Model)
推理 · 规划 · 工具选择 · 输出解析
Qwen-Max / GPT-4 / DeepSeek
工具层 (Tools)
搜索 · 代码执行 · 数据库 · API 调用
MCP / Function Calling / Tavily
记忆层 (Memory)
短期上下文 · 长期知识 · 用户画像
向量库 (Milvus / pgvector) + 对话缓存
| 层级 | 核心职责 | 技术选型 |
|---|---|---|
| 编排层 | 控制流:Agent 循环、状态持久化、人机协同 | LangGraph / 阿里云百炼 / CrewAI |
| 模型层 | 推理引擎:理解指令、拆解任务、选择工具 | Qwen-Max / Qwen-Plus / GPT-4o |
| 工具层 | 能力扩展:搜索、计算、代码执行、API 调用 | MCP / Function Calling / Tavily |
| 记忆层 | 信息持久化:跨会话上下文、知识检索 | 向量库(Milvus / pgvector)+ 对话缓存 |
1.4 快速开始:一个完整的 ReAct Agent
下面用 LangGraph 实现一个带搜索能力的 Agent。这段代码覆盖了全部 4 层的协作方式:
python
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
# ── 编排层:定义状态("黑板"结构) ──
class AgentState(TypedDict):
messages: List[str]
next_action: str
# ── 工具层:定义外部能力 ──
def search_web(query: str) -> str:
"""搜索 API(示例用,实际接入 Tavily/SerpAPI)"""
return f"搜索结果:{query} 的相关信息"
# ── 模型层:LLM 推理节点 ──
def agent_node(state: AgentState):
"""模拟 LLM 决策------实际应调用 Qwen API"""
last = state["messages"][-1]
if "天气" in last:
return {"next_action": "call_tool", "messages": ["让我查一下天气"]}
return {"next_action": "respond", "messages": ["已获取足够信息"]}
# ── 工具执行节点 ──
def tool_node(state: AgentState):
result = search_web(state["messages"][-1])
return {"next_action": "continue", "messages": [result]}
# ── 编排层:组装图为 ReAct 循环 ──
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tool", tool_node)
graph.set_entry_point("agent")
# 条件边------根据 next_action 决定走向
graph.add_conditional_edges(
"agent",
lambda s: s["next_action"],
{"call_tool": "tool", "respond": END}
)
graph.add_edge("tool", "agent") # 工具执行完回到 agent
app = graph.compile()
# ── 执行 ──
result = app.invoke({"messages": ["今天北京天气怎么样?"], "next_action": ""})
print(result["messages"])
# 输出: ["让我查一下天气", "搜索结果:今天北京天气的相关信息", ...]
关键设计点:
- State 是共享"黑板":agent_node 和 tool_node 读写同一份数据
- 条件边实现 ReAct 循环:agent 根据推理结果选择走向 tool 还是直接结束
- tool→agent 的回边:工具执行后回到 agent 做下一轮推理,构成闭环
二、底层原理
2.1 ReAct 循环:Agent 的"推理---行动"闭环
ReAct(Reasoning + Acting)是 2023 年 Google 提出的 Agent 范式,核心思想是让 LLM 交替输出推理轨迹和行动指令。
#mermaid-svg-HiEe8hI2ut58bm0O{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HiEe8hI2ut58bm0O .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HiEe8hI2ut58bm0O .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HiEe8hI2ut58bm0O .error-icon{fill:#552222;}#mermaid-svg-HiEe8hI2ut58bm0O .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HiEe8hI2ut58bm0O .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HiEe8hI2ut58bm0O .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HiEe8hI2ut58bm0O .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HiEe8hI2ut58bm0O .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HiEe8hI2ut58bm0O .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HiEe8hI2ut58bm0O .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HiEe8hI2ut58bm0O .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HiEe8hI2ut58bm0O .marker.cross{stroke:#333333;}#mermaid-svg-HiEe8hI2ut58bm0O svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HiEe8hI2ut58bm0O p{margin:0;}#mermaid-svg-HiEe8hI2ut58bm0O .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HiEe8hI2ut58bm0O .cluster-label text{fill:#333;}#mermaid-svg-HiEe8hI2ut58bm0O .cluster-label span{color:#333;}#mermaid-svg-HiEe8hI2ut58bm0O .cluster-label span p{background-color:transparent;}#mermaid-svg-HiEe8hI2ut58bm0O .label text,#mermaid-svg-HiEe8hI2ut58bm0O span{fill:#333;color:#333;}#mermaid-svg-HiEe8hI2ut58bm0O .node rect,#mermaid-svg-HiEe8hI2ut58bm0O .node circle,#mermaid-svg-HiEe8hI2ut58bm0O .node ellipse,#mermaid-svg-HiEe8hI2ut58bm0O .node polygon,#mermaid-svg-HiEe8hI2ut58bm0O .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HiEe8hI2ut58bm0O .rough-node .label text,#mermaid-svg-HiEe8hI2ut58bm0O .node .label text,#mermaid-svg-HiEe8hI2ut58bm0O .image-shape .label,#mermaid-svg-HiEe8hI2ut58bm0O .icon-shape .label{text-anchor:middle;}#mermaid-svg-HiEe8hI2ut58bm0O .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HiEe8hI2ut58bm0O .rough-node .label,#mermaid-svg-HiEe8hI2ut58bm0O .node .label,#mermaid-svg-HiEe8hI2ut58bm0O .image-shape .label,#mermaid-svg-HiEe8hI2ut58bm0O .icon-shape .label{text-align:center;}#mermaid-svg-HiEe8hI2ut58bm0O .node.clickable{cursor:pointer;}#mermaid-svg-HiEe8hI2ut58bm0O .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HiEe8hI2ut58bm0O .arrowheadPath{fill:#333333;}#mermaid-svg-HiEe8hI2ut58bm0O .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HiEe8hI2ut58bm0O .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HiEe8hI2ut58bm0O .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HiEe8hI2ut58bm0O .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HiEe8hI2ut58bm0O .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HiEe8hI2ut58bm0O .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HiEe8hI2ut58bm0O .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HiEe8hI2ut58bm0O .cluster text{fill:#333;}#mermaid-svg-HiEe8hI2ut58bm0O .cluster span{color:#333;}#mermaid-svg-HiEe8hI2ut58bm0O div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HiEe8hI2ut58bm0O .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HiEe8hI2ut58bm0O rect.text{fill:none;stroke-width:0;}#mermaid-svg-HiEe8hI2ut58bm0O .icon-shape,#mermaid-svg-HiEe8hI2ut58bm0O .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HiEe8hI2ut58bm0O .icon-shape p,#mermaid-svg-HiEe8hI2ut58bm0O .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HiEe8hI2ut58bm0O .icon-shape .label rect,#mermaid-svg-HiEe8hI2ut58bm0O .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HiEe8hI2ut58bm0O .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HiEe8hI2ut58bm0O .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HiEe8hI2ut58bm0O :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 循环直到完成
用户输入
Thought
分析用户意图
Action
调用搜索 API
Observe
搜索返回 25°C 晴天
三轮循环详解:
| 阶段 | 输入 | 处理 | 输出 |
|---|---|---|---|
| Thought | 系统提示 + 对话历史 + 工具结果 | LLM 推理当前状态,决定下一步 | 自然语言推理 + 行动指令(函数调用或最终回答) |
| Action | Thought 阶段输出的函数名和参数 | 框架解析函数调用,执行对应工具 | 原始工具返回结果(数据 / 错误 / 空) |
| Observation | Action 执行的原始结果 | 格式化为 LLM 可读的文本 | 结构化的观察结果,喂回下一轮 Thought |
为什么非要用循环? 因为现实任务很少一步完成:第一次搜索可能不够精确,代码执行可能报错,需要多次"尝试→观察→调整"。典型的科研 Agent 可能需要 5-10 轮循环才能写出一份可靠的文献综述。
2.2 编排层:Agent 的控制中枢
编排层回答的核心问题是:下一步做什么?
核心能力矩阵:
| 能力 | 说明 | LangGraph 实现 | 百炼 实现 |
|---|---|---|---|
| 状态管理 | 维护对话上下文和中间变量 | State TypedDict + add_node |
Session 变量 |
| 条件路由 | 根据 LLM 输出决定走向 | add_conditional_edges |
Switch 节点 |
| 循环控制 | Thought→Action→Observe 闭环 | 有向图的循环边 | 循环节点 |
| 持久化 | 中断后恢复执行,不丢失状态 | Checkpointer + Thread |
快照机制 |
| 人机协同 | 插入人工审批节点 | NodeInterrupt |
审批节点 |
| 多 Agent | 多个 Agent 分工协作 | Subgraph / 跨 graph 通信 |
多 Agent 编排 |
LangGraph 为什么取代了 LangChain Chain?
LangChain Chain 是线性 DAG------A→B→C 一次走完,不支持循环。但 Agent 天然需要循环(工具结果不理想要重试、信息不够要再查)。LangGraph 用有向图替代链式结构,天然支持:
- 循环边:tool→agent 构成闭环
- 条件边:agent→tool 或 agent→END 根据推理结果分支
- 并行边:fan-out 同时调用多个工具
LangGraph 核心数据结构:
python
# State:图的"黑板",所有节点共享读写
class AgentState(TypedDict):
messages: List[BaseMessage] # 对话历史
intermediate_steps: List[Step] # 工具调用的中间结果
remaining_tries: int # 最大重试次数,防止死循环
# Node:图中的一个处理单元
def agent_node(state: AgentState) -> AgentState:
# 读取 state → LLM 推理 → 写回更新
return {"messages": new_messages}
# Edge:节点间的连接
graph.add_edge("node_a", "node_b") # 普通边:固定顺序
graph.add_conditional_edges("agent", router, {...}) # 条件边:分支
状态持久化的接入非常简单:
python
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
app = graph.compile(checkpointer=checkpointer)
# 使用 thread_id 隔离不同会话
result = app.invoke(
{"messages": ["查询2024年GDP"]},
config={"configurable": {"thread_id": "session_001"}}
)
# 中断后可恢复:用相同 thread_id 继续
result2 = app.invoke(
{"messages": ["再帮我跟2023年对比"]},
config={"configurable": {"thread_id": "session_001"}}
)
2.3 模型层:Agent 的推理引擎
Agent 场景对 LLM 的要求比普通对话更高。不是所有模型都适合做 Agent。
Agent 对 LLM 的核心能力要求:
| 能力 | 为什么重要 | 衡量方式 |
|---|---|---|
| 工具选择准确率 | 选错工具 = 任务直接失败 | 给 10 个工具看能否选对 |
| 参数提取精度 | 参数填错 = API 返回 400 | 测试不同格式输入下的参数提取 |
| 指令遵循 | 输出格式必须严格一致 | JSON / 函数调用格式一致性测试 |
| 多步推理 | 复杂任务需要 3-5 步推理链 | 多步推理任务的完整率 |
| 幻觉控制 | 一次幻觉可能带偏整个决策链 | Unknown 场景下拒绝回答的准确率 |
Qwen 系列在 Agent 场景的定位:
| 模型 | 适用场景 | 上下文窗口 | 成本 | 延迟 |
|---|---|---|---|---|
| Qwen-Max | 复杂推理、多步 Agent 任务 | 128K | 高 | 中 |
| Qwen-Plus | 日常 Agent 调用,性价比最优 | 128K | 中 | 低 |
| Qwen-Turbo | 高并发、简单工具调用 | 32K | 低 | 极低 |
| Qwen-Flash | 边缘设备、批量处理 | 32K | 极低 | 极低 |
选型策略: 核心 Agent 链路用 Qwen-Plus 起步;复杂推理场景升级 Qwen-Max;预处理/分类等简单任务用 Qwen-Turbo。不要所有场景用一个模型------既浪费钱又牺牲延迟。
2.4 工具层:Agent 的能力边界
Agent 的能力边界由工具决定------没有搜索工具,Agent 不知道最新信息;没有代码执行器,Agent 算不了精确数学。
工具调用的完整链路:
#mermaid-svg-CpOeFItj26iS7I7r{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CpOeFItj26iS7I7r .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CpOeFItj26iS7I7r .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CpOeFItj26iS7I7r .error-icon{fill:#552222;}#mermaid-svg-CpOeFItj26iS7I7r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CpOeFItj26iS7I7r .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CpOeFItj26iS7I7r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CpOeFItj26iS7I7r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CpOeFItj26iS7I7r .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CpOeFItj26iS7I7r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CpOeFItj26iS7I7r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CpOeFItj26iS7I7r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CpOeFItj26iS7I7r .marker.cross{stroke:#333333;}#mermaid-svg-CpOeFItj26iS7I7r svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CpOeFItj26iS7I7r p{margin:0;}#mermaid-svg-CpOeFItj26iS7I7r .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CpOeFItj26iS7I7r .cluster-label text{fill:#333;}#mermaid-svg-CpOeFItj26iS7I7r .cluster-label span{color:#333;}#mermaid-svg-CpOeFItj26iS7I7r .cluster-label span p{background-color:transparent;}#mermaid-svg-CpOeFItj26iS7I7r .label text,#mermaid-svg-CpOeFItj26iS7I7r span{fill:#333;color:#333;}#mermaid-svg-CpOeFItj26iS7I7r .node rect,#mermaid-svg-CpOeFItj26iS7I7r .node circle,#mermaid-svg-CpOeFItj26iS7I7r .node ellipse,#mermaid-svg-CpOeFItj26iS7I7r .node polygon,#mermaid-svg-CpOeFItj26iS7I7r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CpOeFItj26iS7I7r .rough-node .label text,#mermaid-svg-CpOeFItj26iS7I7r .node .label text,#mermaid-svg-CpOeFItj26iS7I7r .image-shape .label,#mermaid-svg-CpOeFItj26iS7I7r .icon-shape .label{text-anchor:middle;}#mermaid-svg-CpOeFItj26iS7I7r .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CpOeFItj26iS7I7r .rough-node .label,#mermaid-svg-CpOeFItj26iS7I7r .node .label,#mermaid-svg-CpOeFItj26iS7I7r .image-shape .label,#mermaid-svg-CpOeFItj26iS7I7r .icon-shape .label{text-align:center;}#mermaid-svg-CpOeFItj26iS7I7r .node.clickable{cursor:pointer;}#mermaid-svg-CpOeFItj26iS7I7r .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CpOeFItj26iS7I7r .arrowheadPath{fill:#333333;}#mermaid-svg-CpOeFItj26iS7I7r .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CpOeFItj26iS7I7r .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CpOeFItj26iS7I7r .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CpOeFItj26iS7I7r .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CpOeFItj26iS7I7r .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CpOeFItj26iS7I7r .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CpOeFItj26iS7I7r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CpOeFItj26iS7I7r .cluster text{fill:#333;}#mermaid-svg-CpOeFItj26iS7I7r .cluster span{color:#333;}#mermaid-svg-CpOeFItj26iS7I7r div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CpOeFItj26iS7I7r .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CpOeFItj26iS7I7r rect.text{fill:none;stroke-width:0;}#mermaid-svg-CpOeFItj26iS7I7r .icon-shape,#mermaid-svg-CpOeFItj26iS7I7r .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CpOeFItj26iS7I7r .icon-shape p,#mermaid-svg-CpOeFItj26iS7I7r .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CpOeFItj26iS7I7r .icon-shape .label rect,#mermaid-svg-CpOeFItj26iS7I7r .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CpOeFItj26iS7I7r .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CpOeFItj26iS7I7r .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CpOeFItj26iS7I7r :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} LLM 输出
{function: search_web, args: {query: 2024年GDP}}
Function Calling 解析器
提取函数名 + 参数
工具注册表
校验函数是否存在
校验参数类型和范围
执行工具函数
搜索 API / 代码执行
结果格式化为
Observation
喂回 LLM 下一轮推理
Function Calling 与 MCP 的分工:
| 维度 | Function Calling | MCP |
|---|---|---|
| 本质 | LLM 输出结构化参数的机制 | 工具集成协议标准 |
| 谁定义 | LLM 厂商(OpenAI / 百炼) | 社区(Anthropic 发起) |
| 工具注册 | 写在 System Prompt 的函数描述中 | 通过 MCP Server 动态注册 |
| 松耦合度 | 低------工具变更需要改 Prompt | 高------Server 独立部署,Agent 无需重启 |
| 生态 | 各厂商各自一套 | 统一协议,截至 2026 年已有 3000+ 工具 |
两者不是替代关系。Function Calling 解决的是"怎么说人话→转参数",MCP 解决的是"怎么找到工具→调用工具"。生产系统中两者共存:Function Calling 做参数提取,MCP 做工具发现和调用。
2.5 记忆层:跨会话的知识持久化
没有记忆的 Agent 每轮对话都是"初次见面"。
短期记忆(Working Memory):
- 形式:当前对话的完整消息列表
- 容量上限:LLM 上下文窗口(Qwen-Max 128K tokens)
- 超限策略:
- 滑动窗口:丢弃最早的消息,保留最近的 N 轮
- 摘要压缩:将旧消息压缩为一段摘要,释放上下文空间
长期记忆(Long-term Memory):
- 形式:向量数据库中的嵌入向量 + 元数据
- 存储内容:用户偏好、历史事实、项目上下文
- 检索策略:
| 策略 | 原理 | 适用场景 |
|---|---|---|
| 相似度检索 | 计算语义相似度,返回 Top-K | 通用场景,默认选项 |
| 时间衰减 | 越近的记忆权重越高,随时间降低分数 | 偏好类记忆(用户近期的选择更重要) |
| 重要性排序 | 为每条记忆标记重要性分数,优先返回高价值内容 | 关键事实(如用户的项目信息) |
混合记忆架构:
#mermaid-svg-sGInzmJIFi3XWKKA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sGInzmJIFi3XWKKA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sGInzmJIFi3XWKKA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sGInzmJIFi3XWKKA .error-icon{fill:#552222;}#mermaid-svg-sGInzmJIFi3XWKKA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sGInzmJIFi3XWKKA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sGInzmJIFi3XWKKA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sGInzmJIFi3XWKKA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sGInzmJIFi3XWKKA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sGInzmJIFi3XWKKA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sGInzmJIFi3XWKKA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sGInzmJIFi3XWKKA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sGInzmJIFi3XWKKA .marker.cross{stroke:#333333;}#mermaid-svg-sGInzmJIFi3XWKKA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sGInzmJIFi3XWKKA p{margin:0;}#mermaid-svg-sGInzmJIFi3XWKKA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sGInzmJIFi3XWKKA .cluster-label text{fill:#333;}#mermaid-svg-sGInzmJIFi3XWKKA .cluster-label span{color:#333;}#mermaid-svg-sGInzmJIFi3XWKKA .cluster-label span p{background-color:transparent;}#mermaid-svg-sGInzmJIFi3XWKKA .label text,#mermaid-svg-sGInzmJIFi3XWKKA span{fill:#333;color:#333;}#mermaid-svg-sGInzmJIFi3XWKKA .node rect,#mermaid-svg-sGInzmJIFi3XWKKA .node circle,#mermaid-svg-sGInzmJIFi3XWKKA .node ellipse,#mermaid-svg-sGInzmJIFi3XWKKA .node polygon,#mermaid-svg-sGInzmJIFi3XWKKA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sGInzmJIFi3XWKKA .rough-node .label text,#mermaid-svg-sGInzmJIFi3XWKKA .node .label text,#mermaid-svg-sGInzmJIFi3XWKKA .image-shape .label,#mermaid-svg-sGInzmJIFi3XWKKA .icon-shape .label{text-anchor:middle;}#mermaid-svg-sGInzmJIFi3XWKKA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sGInzmJIFi3XWKKA .rough-node .label,#mermaid-svg-sGInzmJIFi3XWKKA .node .label,#mermaid-svg-sGInzmJIFi3XWKKA .image-shape .label,#mermaid-svg-sGInzmJIFi3XWKKA .icon-shape .label{text-align:center;}#mermaid-svg-sGInzmJIFi3XWKKA .node.clickable{cursor:pointer;}#mermaid-svg-sGInzmJIFi3XWKKA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sGInzmJIFi3XWKKA .arrowheadPath{fill:#333333;}#mermaid-svg-sGInzmJIFi3XWKKA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sGInzmJIFi3XWKKA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sGInzmJIFi3XWKKA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sGInzmJIFi3XWKKA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sGInzmJIFi3XWKKA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sGInzmJIFi3XWKKA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sGInzmJIFi3XWKKA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sGInzmJIFi3XWKKA .cluster text{fill:#333;}#mermaid-svg-sGInzmJIFi3XWKKA .cluster span{color:#333;}#mermaid-svg-sGInzmJIFi3XWKKA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sGInzmJIFi3XWKKA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sGInzmJIFi3XWKKA rect.text{fill:none;stroke-width:0;}#mermaid-svg-sGInzmJIFi3XWKKA .icon-shape,#mermaid-svg-sGInzmJIFi3XWKKA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sGInzmJIFi3XWKKA .icon-shape p,#mermaid-svg-sGInzmJIFi3XWKKA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sGInzmJIFi3XWKKA .icon-shape .label rect,#mermaid-svg-sGInzmJIFi3XWKKA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sGInzmJIFi3XWKKA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sGInzmJIFi3XWKKA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sGInzmJIFi3XWKKA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 当前轮上下文
相关历史记忆
用户输入
短期记忆
对话窗口 + 摘要
长期记忆
向量库相似度搜索
时间衰减排序
重要性筛选
合并输入
短期 + 长期 + 当前问题
→ LLM
2.6 Agent vs Workflow:选型决策
这是架构设计的第一选择,定义清楚了才能往下走。
| 决策维度 | Workflow | Agent |
|---|---|---|
| 控制流定义方式 | 代码预定义路径 | LLM 动态决策 |
| 确定性 | 高------相同输入 = 相同执行路径 | 低------每次执行可能走不同路径 |
| 维护成本 | 低------逻辑固化在代码中 | 高------需要监控 LLM 决策质量 |
| 调试难度 | 低------逐行跟踪即可 | 高------需要 tracing 和日志 |
| 适用场景 | 已知路径的稳定流程 | 需要灵活应变的开放任务 |
| 典型例子 | 客服工单处理、数据 ETL 流水线 | 科研文献分析、代码生成 |
选型原则:能 Workflow 别 Agent。 把确定的部分固化到 Workflow 里,只把需要灵活决策的部分交给 Agent。这也是 Anthropic 官方推荐的最佳实践。一个常见模式是"外围 Workflow + 核心 Agent"------任务的编排骨架是固定的 Workflow,骨架上的关键节点由 Agent 动态填充。
三、架构设计原则
3.1 四层分离原则
每一层只关心自己的职责,不要跨层耦合:
- 编排层不写业务逻辑,只负责"下一步去哪里"
- 模型层不做工具调用,只负责推理和输出结构
- 工具层不参与决策,只负责执行和返回结果
- 记忆层不关心推理细节,只负责存储和检索
3.2 状态可追溯原则
Agent 的不确定性决定了必须做完整的执行追踪:
- 每一轮 Thought 的内容要记录
- 每一次 Tool 调用的输入输出要记录
- 支持按照 session_id 回放整个执行过程
LangGraph 的 Checkpointer + thread_id 天然支持这个模式。
3.3 防御性设计原则
Agent 系统的故障模式比传统软件多:
- 工具调用设超时:每个工具调用都要有 timeout,防止卡死
- 关键步骤设检查点:重要决策前插入人工审批
- 最大循环次数:防止 Agent 陷入死循环
- 输出校验:工具调用的参数做类型和范围校验
3.4 渐进式复杂度原则
不要一开始就上全功能 Agent:
- 先用 Workflow 跑通流程
- 把需要灵活决策的节点换成 Agent
- 给 Agent 加 Memory
- 加多 Agent 协作
- 加持久化和恢复
每一步都要验证"这一步真的需要吗"。