这是《LLM 应用开发 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Agent 是在目标、工具、状态和停止条件约束下循环决策的系统。它比单次调用更强,也更容易失控。本章讲 Agent 的核心组件、状态机、安全边界和工程实现。
15.1 Agent 定义
while not finished:
observe(state)
plan_or_select_action()
execute_tool_with_permission()
update_state()
check_budget_and_stop_condition()
核心组件:
| 组件 | 职责 |
|---|---|
| Goal | 任务目标和成功条件 |
| Planner | 拆解任务或选择下一步 |
| Tools | 受限外部能力 |
| State | 任务状态、发现、中间结果 |
| Memory | 短期上下文与长期记忆 |
| Policy | 权限、风险、确认策略 |
| Budget | 轮数、token、金额、时间 |
| Auditor | 日志和追踪 |
15.2 常见架构
| 架构 | 适用 | 特点 |
|---|---|---|
| Single-shot | 分类、抽取 | 无循环 |
| Router | 客服分发 | 先路由再执行 |
| ReAct | 诊断、查询 | 推理与行动交替 |
| Plan-and-Execute | 长任务 | 先计划再执行 |
| Multi-Agent | 复杂协作 | 角色分工,成本高 |
| Workflow Agent | 企业流程 | 受控状态机 |
生产系统常从受控 Workflow Agent 开始,而不是完全自由自主 Agent。
15.3 状态设计
from dataclasses import dataclass, field
@dataclass
class AgentState:
goal: str
user_id: str
tenant_id: str
steps: list[dict] = field(default_factory=list)
observations: list[str] = field(default_factory=list)
artifacts: dict[str, str] = field(default_factory=dict)
tool_calls: dict[str, int] = field(default_factory=dict)
iteration: int = 0
status: str = "running"
状态必须持久化,否则任务失败后无法恢复和审计。
15.4 循环控制
MAX_ITERATIONS = 8
MAX_TOKENS = 30_000
MAX_TOOL_CALLS = 20
def should_stop(state) -> bool:
return any([
state.status in {"done", "failed", "cancelled"},
state.iteration >= MAX_ITERATIONS,
state.total_tokens >= MAX_TOKENS,
state.total_tool_calls >= MAX_TOOL_CALLS,
duplicate_tool_pattern(state),
])
停止条件:
- 目标完成;
- 信息不足;
- 用户取消;
- 预算耗尽;
- 连续失败;
- 重复动作;
- 风险升级人工;
- 超时。
15.5 工具策略
| 风险 | 示例 | 策略 |
|---|---|---|
| 只读低风险 | 查文档 | 白名单后自动 |
| 只读敏感 | 查订单 | 权限过滤 |
| 可逆写 | 保存草稿 | 确认后执行 |
| 不可逆写 | 删除数据 | 强审批 |
| 外部发送 | 发邮件、付款 | 双人或多因素确认 |
| 代码执行 | 数据分析 | 沙箱和资源限制 |
工具策略应独立于 Prompt,由代码强制执行。
15.6 Planner
Plan-and-Execute 输出:
{
"plan": [
{"step": 1, "action": "query_order", "reason": "获取订单状态"},
{"step": 2, "action": "check_refund_policy", "reason": "确认资格"},
{"step": 3, "action": "draft_refund", "reason": "生成草稿"}
],
"missing_info": ["订单号"]
}
工程要求:
- 步骤可校验;
- 动作必须来自白名单;
- 允许计划失败后重规划;
- 限制步骤数;
- 关键节点检查状态;
- 每步保存结果。
15.7 失败恢复
Tool timeout
-> retry bounded
-> fallback tool
-> ask user
-> mark blocked
恢复策略:
- 工具幂等;
- 保存检查点;
- 支持从失败步骤重试;
- 区分业务失败和技术失败;
- 不把内部错误暴露给用户;
- 失败任务可回放;
- 高风险动作前检查前置状态。
15.8 可观测性
Trace 结构:
agent_run
|-- llm_call
|-- retrieval
|-- tool_call
|-- policy_decision
+-- final_answer
指标:
| 指标 | 说明 |
|---|---|
| task success rate | 任务成功率 |
| average iterations | 平均轮数 |
| tool error rate | 工具错误率 |
| budget exceeded rate | 预算超限率 |
| human takeover rate | 人工接管率 |
| cost per task | 单任务成本 |
| p95 duration | 总耗时 |
15.9 安全边界
- Agent 只代表用户执行授权范围内动作;
- 检索内容不能提升权限;
- 工具返回内容不能覆盖系统策略;
- 模型不能修改工具白名单;
- 会话隔离,禁止跨用户共享记忆;
- 对删除、支付、外发设置审批;
- 记录完整决策链;
- 生产环境默认最小权限。
15.10 何时不用 Agent
| 场景 | 更合适方案 |
|---|---|
| 固定流程 | 工作流引擎 |
| 单一分类 | 分类模型或规则 |
| 精确查询 | SQL / API |
| 简单知识问答 | RAG |
| 强一致事务 | 数据库事务 |
| 低延迟路由 | 规则 + 小模型 |
Agent 适合步骤不确定、需要组合信息、允许多轮交互且有明确边界的任务。
本章小结
Agent 的核心是受控循环:明确目标、维护状态、选择工具、执行策略、检查预算和停止条件。生产环境应优先采用受控工作流和清晰权限模型,把自主性限制在可审计、可恢复、可回滚的范围内。
思考题
- Agent 和单次 LLM 调用的本质区别是什么?
- 为什么要为 Agent 设置预算和重复检测?
- 哪些动作不应允许 Agent 自动执行?
- 如何设计 Agent 的失败恢复?
- 哪些固定流程不适合交给自由 Agent?