经历了 2024 年的概念炒作,2025 年的 AI Agent 正在从 Demo 走向生产。本文结合多个实战项目的血泪教训,总结 Agent 架构设计中必须面对的 5 个核心决策。
一、为什么你的 Agent 只能做 Demo?
去年这个时候,我也曾兴奋地展示一个能自动订机票的 Agent Demo------直到它在生产环境连续 3 次订错日期。
问题不在于 LLM 的能力,而在于架构设计。大多数 "Agent 教程" 只教你调用 API,却避开了真正决定成败的工程决策:
- 什么时候该让 LLM 做决策,什么时候该用代码兜底?
- 工具调用失败,Agent 应该如何优雅降级?
- 多 Agent 协作,状态如何同步而不陷入死锁?
这些问题没有标准答案,但有经过验证的权衡框架。
二、关键决策 1:ReAct vs Plan-and-Execute
两种范式,两种命运
ReAct(推理+行动交替) 就像边想边做的人:
python
# 典型 ReAct 循环
observation = env.get_state()
while not done:
thought = llm.think(observation, goal)
action = llm.decide_action(thought)
observation = env.execute(action)
优点:灵活、容错性强、适合开放域任务
缺点:容易陷入局部最优、token 消耗高、难以预测执行路径
Plan-and-Execute(先规划后执行) 像先写 TODO 清单的人:
python
# 先制定完整计划
plan = llm.create_plan(goal)
# 按计划逐步执行(可用代码或 LLM)
for step in plan.steps:
result = executor.run(step)
优点:可预测、token 效率高、易于审计
缺点:面对意外情况需要重新规划、初期规划错误代价高
实战建议
我们的项目采用了 分层架构:
| 层级 | 范式 | 适用场景 |
|---|---|---|
| 战略层 | Plan-and-Execute | 用户意图理解、任务分解 |
| 战术层 | ReAct | 工具调用、异常处理 |
| 执行层 | 纯代码 | 确定性操作(数据库查询、API 调用) |
血泪教训:不要让 LLM 决定 SQL 怎么写,让它决定"要不要查数据库"。
三、关键决策 2:工具设计的粒度边界
工具太粗:LLM 失控
python
# 反面教材:过于粗粒度的工具
@tool
def process_user_request(query: str) -> str:
"""处理用户请求"""
# 内部逻辑黑盒,LLM 无法干预
...
LLM 拿到这种工具就像让厨师用"做菜"这一个按钮完成满汉全席------没有控制感,出错也无法定位。
工具太细:上下文爆炸
python
# 反面教材:过于细粒度的工具
@tool
def open_file(path: str): ...
@tool
def read_line(file_handle): ...
@tool
def close_file(file_handle): ...
LLM 的上下文窗口被工具定义占满,真正重要的业务逻辑反而没空间。
黄金分割点
一个工具应该对应 一个业务意图,而非一个系统调用:
python
@tool
def search_customer_orders(
customer_id: str,
date_range: Optional[Tuple[date, date]] = None,
status_filter: Optional[List[OrderStatus]] = None
) -> SearchResult:
"""
查询客户订单历史。
当用户问"我最近买了什么"或"我的订单状态"时使用。
支持按日期范围和订单状态筛选。
"""
...
关键原则:工具描述应该让产品经理能看懂,而不只是程序员。
四、关键决策 3:记忆系统的设计
记忆不是简单的历史记录
很多教程教你把对话历史塞进 prompt,但这只是 工作记忆。
生产级 Agent 需要三层记忆架构:
scss
┌─────────────────────────────────────┐
│ 工作记忆 (Working Memory) │ ← 当前对话,在 prompt 中
│ - 最近 5-10 轮对话 │
│ - 当前任务上下文 │
├─────────────────────────────────────┤
│ 短期记忆 (Short-term Memory) │ ← 当前 session,在向量库中
│ - 本轮任务中的关键事实 │
│ - 用户的临时偏好 │
├─────────────────────────────────────┤
│ 长期记忆 (Long-term Memory) │ ← 跨 session,在知识图谱中
│ - 用户画像、历史偏好 │
│ - 业务规则、领域知识 │
└─────────────────────────────────────┘
记忆的写入策略
不是所有信息都值得记住:
python
class MemoryFilter:
"""决定什么值得写入长期记忆"""
def should_remember(self, fact: Fact) -> bool:
# 1. 用户明确表达的偏好
if fact.is_explicit_preference:
return True
# 2. 对完成任务有关键影响的信息
if fact.task_criticality > 0.8:
return True
# 3. 重复出现的模式(用摘要而非原始记录)
if self.pattern_recognizer.is_recurring(fact):
return True
return False
血泪教训:我们曾经把用户的每一句"谢谢"都存进了向量库,结果检索时全是噪声。
五、关键决策 4:人机协作的边界
完全自主 vs 完全人工
这是一个光谱,而非二选一:
markdown
完全人工 ←────────────────────────→ 完全自主
│ │ │
人工确认 异常上报 自主执行
关键步骤 人工介入 全程自动
决策框架
我们用 风险矩阵 决定每个操作的自动化程度:
| 操作可逆性 \ 错误成本 | 低 | 中 | 高 |
|---|---|---|---|
| 可逆 | 自动执行 | 自动+通知 | 确认后执行 |
| 不可逆 | 自动+通知 | 确认后执行 | 人工审批 |
实战案例:
- 查询库存 → 自动执行(可逆、低成本)
- 生成报价单 → 确认后执行(可逆但影响客户关系)
- 下单扣款 → 人工审批(不可逆、高成本)
优雅降级
当 Agent 不确定时,不应该瞎猜,而应该:
python
class UncertaintyHandler:
def handle(self, confidence: float, context: Context):
if confidence > 0.9:
return Action.AUTO_EXECUTE
elif confidence > 0.7:
return Action.EXECUTE_WITH_NOTIFICATION
elif confidence > 0.5:
return Action.ASK_FOR_CONFIRMATION
else:
return Action.ESCALATE_TO_HUMAN
六、关键决策 5:多 Agent 协作的拓扑
三种协作模式
1. 层级式(Manager-Worker)
css
[Manager Agent]
/ | \
[Agent1] [Agent2] [Agent3]
适合:任务可清晰分解,子任务相对独立
2. 流水线式(Pipeline)
css
[Input] → [Agent A] → [Agent B] → [Agent C] → [Output]
适合:业务流程标准化,如"需求分析→技术方案→代码生成→测试"
3. 网状式(Mesh)
css
[Agent A] ←──→ [Agent B]
↑ \ / ↑
└────→[Agent C]←──┘
适合:复杂决策场景,需要多维度信息交叉验证
状态同步的坑
多 Agent 最大的噩梦是状态不一致。我们的解决方案:
python
# 共享状态总线,而非点对点通信
class AgentStateBus:
def publish(self, event: StateEvent):
# 1. 写入事件溯源日志
self.event_log.append(event)
# 2. 更新物化视图(各 Agent 的本地缓存)
for agent_id in self.subscribers[event.type]:
self.update_materialized_view(agent_id, event)
def get_consistent_state(self, agent_id: str, as_of: Timestamp) -> State:
# 基于事件日志重建任意时间点的状态
return self.event_log.replay_until(agent_id, as_of)
血泪教训:我们曾经用消息队列做 Agent 通信,结果在消息重试时产生了重复订单。
七、从架构到落地:一个最小可运行的框架
理论说完了,这里是一个经过生产验证的最小框架:
python
from dataclasses import dataclass
from typing import List, Callable, Optional
from enum import Enum
class RiskLevel(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
@dataclass
class Tool:
name: str
description: str
handler: Callable
risk_level: RiskLevel
requires_confirmation: bool = False
@dataclass
class AgentConfig:
# 范式选择
planning_strategy: str = "hierarchical" # or "react", "plan_then_execute"
# 记忆配置
working_memory_size: int = 10
enable_vector_memory: bool = True
# 人机协作
auto_execute_threshold: float = 0.9
confirmation_threshold: float = 0.7
# 工具
tools: List[Tool] = None
# 多 Agent
sub_agents: Optional[List['AgentConfig']] = None
class ProductionAgent:
def __init__(self, config: AgentConfig):
self.config = config
self.memory = MultiTierMemorySystem()
self.uncertainty_handler = UncertaintyHandler(config)
async def run(self, user_input: str) -> AgentResponse:
# 1. 理解意图 + 制定计划
plan = await self.planner.create_plan(user_input)
# 2. 执行计划
results = []
for step in plan.steps:
# 风险评估
risk = self.assess_risk(step)
# 决策:自动执行 or 人工确认
decision = self.uncertainty_handler.decide(risk, step)
if decision == Decision.AUTO_EXECUTE:
result = await self.execute_step(step)
elif decision == Decision.CONFIRM:
result = await self.execute_with_confirmation(step)
else:
result = await self.escalate(step)
results.append(result)
# 更新记忆
self.memory.update(step, result)
# 3. 生成回复
return await self.synthesize_response(results)
八、结语:Agent 工程的本质
AI Agent 不是 LLM 的包装,而是一个 决策系统。好的 Agent 架构应该像好的软件架构一样:
- 关注点分离:LLM 负责意图理解,代码负责确定性逻辑
- 失败隔离:单点故障不会级联
- 可观测:每一步决策都可追踪、可审计
- 渐进式自动化:从人工确认开始,逐步扩大自主范围
2025 年,Agent 领域的竞争不再是"谁的模型更强",而是"谁的架构更能把模型能力稳定地交付给用户"。
参考与延伸
如果你正在构建生产级 Agent,欢迎在评论区分享你的架构决策------我们一起踩坑,一起成长。