返回AI笔记
AI Day 22

AI Day 22: Agent系统工程化(1):状态管理与错误恢复 — 让Agent在生产环境中"不丢活、不翻车"

Agent状态管理与错误恢复是让Agent从"Demo好看"到"生产能用"的关键工程能力——通过有限状态机(FSM)管理Agent的执行生命周期,通过Checkpoint/Resume实现长时任务的断点续传,通过幂等性+重试+回退+人工接管的四层防御体系应对不可预测的失败。没有状态管理的Agent,就像没有事务管理的交易系统——一断电就全丢。

2026-04-23
AgentErrorCheckpointIdempotencyLangGraphGracefulHuman-in-the-LoopRetryRollbackLong-Running

日期:2026-04-23 阶段:第二阶段 — 工程实践 (Day 16-30) 标签Agent State Machine Error Recovery Checkpoint Idempotency LangGraph Graceful Degradation Human-in-the-Loop Retry Rollback Long-Running Tasks


学习路径树

AI/LLM 深度技术学习 50天计划
├── 第一阶段:模型基础 (Day 1-15) ✅
│   ├── Day 1:  Transformer架构与LLM基础 ✅
│   ├── Day 2:  模型量化与本地部署 ✅
│   ├── Day 3:  训练过程深度:Pre-training / SFT / RLHF / DPO ✅
│   ├── Day 4:  Prompt Engineering与上下文学习(ICL)原理 ✅
│   ├── Day 5:  RAG架构:检索增强生成全链路 ✅
│   ├── Day 6:  向量数据库与Embedding模型 ✅
│   ├── Day 7:  Fine-tuning实战:LoRA / QLoRA / Adapter ✅
│   ├── Day 8:  推理优化:vLLM / TensorRT-LLM / SGLang ✅
│   ├── Day 9:  长上下文技术:RoPE扩展 / Ring Attention ✅
│   ├── Day 10: 多模态模型:Vision-Language架构 ✅
│   ├── Day 11: Reasoning模型:CoT / o1 / R1 / Extended Thinking ✅
│   ├── Day 12: Agent框架:ReAct / Tool Use / Planning ✅
│   ├── Day 13: MCP协议与Tool生态 ✅
│   ├── Day 14: 模型评估:Benchmark / Arena / 安全评估 ✅
│   └── Day 15: 阶段复习与架构总结 ✅
│
├── 第二阶段:工程实践 (Day 16-30)
│   ├── Day 16: LLM应用架构设计 — API Gateway/路由/缓存 ✅
│   ├── Day 17: LLM安全与Guardrails — 生产环境防护体系 ✅
│   ├── Day 18: LLM可观测性 — 日志/Tracing/指标/告警 ✅
│   ├── Day 19: 生产级RAG(1) — 文档解析与Chunking工程 ✅
│   ├── Day 20: 生产级RAG(2) — Retrieval优化与Reranking ✅
│   ├── Day 21: 生产级RAG(3) — 评估框架与持续迭代 ✅
│   ├── Day 22: Agent系统工程化(1) — 状态管理与错误恢复 ← 你在这里
│   ├── Day 23: Agent系统工程化(2) — 成本控制与性能优化
│   ├── Day 24: Agent系统工程化(3) — 多Agent协作架构
│   ├── Day 25: Agent系统工程化(4) — 测试与部署
│   └── Day 26-30: 多模型编排/部署策略/端到端项目
│
├── 第三阶段:金融零售AI应用 (Day 31-42)
│   ├── Day 31-35: 金融AI(风控模型/智能投顾/合规/反欺诈)
│   ├── Day 36-40: 零售AI(推荐系统/智能客服/供应链预测/营销)
│   └── Day 41-42: CeFi x DeFi x AI融合架构
│
└── 第四阶段:面试冲刺 (Day 43-50)
    ├── Day 43-46: 系统设计面试(LLM平台/RAG/Agent/推荐)
    ├── Day 47-49: 产品/架构面试模拟
    └── Day 50: 总结与作品集

核心概念

一句话定义

Agent状态管理与错误恢复是让Agent从"Demo好看"到"生产能用"的关键工程能力——通过有限状态机(FSM)管理Agent的执行生命周期,通过Checkpoint/Resume实现长时任务的断点续传,通过幂等性+重试+回退+人工接管的四层防御体系应对不可预测的失败。没有状态管理的Agent,就像没有事务管理的交易系统——一断电就全丢。

金融类比

Agent状态管理 = 交易系统的事务管理 —— 每步都要可追溯、可回滚

银行转账交易:                              Agent多步执行:
├── 事务开始                               ├── Task接收
│   ├── 扣减A账户余额                      │   ├── Step 1: 调用LLM分析意图
│   ├── 增加B账户余额                      │   ├── Step 2: 调用外部API获取数据
│   ├── 生成交易凭证                       │   ├── Step 3: 调用LLM生成报告
│   └── 发送通知                           │   └── Step 4: 发送邮件给用户
├── 事务提交 / 回滚                        ├── 任务完成 / 回退
│                                          │
├── 关键要求:                              ├── 关键要求:
│   ├── 原子性: 要么全做,要么全不做        │   ├── 可追溯: 每步状态都有记录
│   ├── 一致性: 转账前后总额不变            │   ├── 可恢复: 失败时可从断点继续
│   ├── 隔离性: 并发转账不互相干扰          │   ├── 可回退: 有副作用的步骤需要补偿
│   └── 持久性: 一旦提交就永久保存          │   └── 幂等性: 重试不会产生重复效果
│                                          │
├── 如果没有事务管理:                       ├── 如果没有状态管理:
│   扣了A的钱,B还没收到,系统崩了           │   调用了API下了单,LLM还没确认,系统崩了
│   → A少了100,B没多100 → 钱凭空消失       │   → 用户不知道发生了什么,可能重复下单
│   → 灾难                                 │   → 灾难
│                                          │
└── 银行的解决方案:                         └── Agent的解决方案:
    ├── 事务日志(Transaction Log)               ├── 状态持久化(State Persistence)
    ├── WAL(Write-Ahead Log)                   ├── Checkpoint机制
    ├── 补偿交易(Compensating Transaction)     ├── 补偿动作(Compensating Action)
    └── 人工处理(异常清算)                      └── 人工接管(Human-in-the-Loop)

核心思想: Agent做的每一步都像银行的每一笔记账
  → 有凭证、有流水、可查询、可回滚、可审计
  → "不丢活" 比 "更聪明" 重要得多

Day 12 → Day 22 的跃迁

Day 12学了Agent原理:
  → ReAct循环(思考→行动→观察)
  → Tool Use(Function Calling)
  → Planning(任务规划)
  → 本质是"Agent能做什么"

Day 22开始学Agent工程化:
  → 状态管理(每步在哪、做了什么、结果是什么)
  → 错误恢复(失败了怎么办)
  → 长时任务(跑几分钟甚至几小时的任务)
  → 本质是"Agent如何可靠地做"

类比:
  Day 12 = 学开车(方向盘、油门、刹车)
  Day 22 = 学交通安全(红灯停、遇障碍物、车抛锚了怎么办)
  → 不学Day 22的内容,Agent只能在Demo里跑
  → 学了Day 22,Agent才能在"生产道路"上安全行驶

知识点1: Agent状态机设计

为什么Agent需要状态机

Agent vs 传统API调用:

传统API:
  Request → Process → Response
  → 无状态(Stateless)
  → 每次调用独立
  → 失败了重新调用即可

Agent:
  Task → Step1 → Step2 → ... → StepN → Result
  → 有状态(Stateful)
  → 步骤之间有依赖关系
  → Step3失败了不能从Step1重来(Step1可能已有副作用)

Agent有状态的原因:
├── 1. 多步骤: 一个任务需要多步完成,步骤间有上下文传递
├── 2. 工具调用: 工具调用可能有副作用(发邮件/下单/转账)
├── 3. 长时间: 某些任务可能运行数分钟甚至数小时
├── 4. 外部依赖: API可能超时、限流、返回错误
└── 5. 用户交互: 可能需要等待用户确认才能继续

→ 必须显式管理Agent的"执行状态"
→ 不能依赖"内存中的变量"(进程一死就全丢)

Agent状态定义

核心状态集(Finite State Machine):

┌──────────┐     接收任务     ┌──────────┐
│  IDLE    │──────────────→ │ PLANNING │
│  空闲    │                 │  规划中   │
└──────────┘                 └────┬─────┘
      ↑                          │ 规划完成
      │                          ↓
      │                    ┌──────────┐     执行步骤     ┌──────────┐
      │                    │ READY    │──────────────→ │ EXECUTING│
      │                    │  就绪    │                 │  执行中   │
      │                    └──────────┘                 └────┬─────┘
      │                          ↑                          │
      │                          │ 步骤完成                  │ 步骤完成
      │                          │ (还有下一步)               │ (全部完成)
      │                          │                          │
      │    ┌──────────┐          │                          │
      │    │ WAITING  │←─────────┤                          │
      │    │  等待中   │          │                          │
      │    └──────────┘          │                          ↓
      │          ↑               │                    ┌──────────┐
      │          │ 需要人工确认    │                    │ COMPLETED│
      │          │               │                    │  已完成   │
      │          └───────────────┘                    └──────────┘
      │                                                    │
      │    ┌──────────┐                                    │
      │    │  ERROR   │←─── 任何步骤失败                    │
      │    │  错误    │                                    │
      │    └────┬─────┘                                    │
      │         │                                          │
      │         ├── 可重试 → 回到EXECUTING                  │
      │         ├── 需回退 → ROLLING_BACK → ROLLED_BACK    │
      │         └── 放弃   → FAILED                        │
      │                                                    │
      └────────────────────────────────────────────────────┘

每个状态需要记录:
├── state: 当前状态枚举
├── current_step: 当前执行到第几步
├── step_results: 每步的输入/输出/耗时
├── error_info: 错误详情(如果有)
├── retry_count: 当前步骤已重试次数
├── created_at / updated_at: 时间戳
└── metadata: 任务级别的元数据(用户ID/优先级等)

状态转换规则

状态转换表(State Transition Table):

┌──────────────┬───────────────────┬──────────────┬───────────────────┐
│ 当前状态      │ 触发事件           │ 目标状态      │ 动作               │
├──────────────┼───────────────────┼──────────────┼───────────────────┤
│ IDLE         │ 收到新任务         │ PLANNING     │ 解析任务/分配资源   │
│ PLANNING     │ 规划完成           │ READY        │ 生成执行计划        │
│ PLANNING     │ 规划失败           │ ERROR        │ 记录错误            │
│ READY        │ 开始执行           │ EXECUTING    │ 执行第一个步骤      │
│ EXECUTING    │ 步骤完成(有下一步)  │ READY        │ 保存结果/准备下一步  │
│ EXECUTING    │ 步骤完成(已全部完成)│ COMPLETED    │ 汇总结果/清理资源   │
│ EXECUTING    │ 需要人工确认       │ WAITING      │ 发送确认请求        │
│ EXECUTING    │ 步骤失败           │ ERROR        │ 记录错误/评估重试   │
│ WAITING      │ 人工确认通过       │ EXECUTING    │ 继续执行            │
│ WAITING      │ 人工拒绝           │ FAILED       │ 终止任务            │
│ WAITING      │ 等待超时           │ ERROR        │ 超时处理            │
│ ERROR        │ 重试(未超限)       │ EXECUTING    │ 重试当前步骤        │
│ ERROR        │ 重试超限           │ FAILED       │ 标记永久失败        │
│ ERROR        │ 需要回退           │ ROLLING_BACK │ 执行补偿动作        │
│ ROLLING_BACK │ 回退完成           │ ROLLED_BACK  │ 记录回退结果        │
└──────────────┴───────────────────┴──────────────┴───────────────────┘

金融类比:
  EXECUTING → ERROR → ROLLING_BACK → ROLLED_BACK
  = 转账 → 超时 → 冲正 → 冲正完成
  银行系统不允许"不知道转没转成功"的中间态,Agent也不应该

状态持久化方案

为什么不能只用内存?

Agent运行在进程中:
├── 进程崩溃 → 内存状态全丢
├── 服务重启 → 所有执行中的任务丢失
├── 节点迁移 → 无法继续执行
└── 水平扩展 → 状态在哪个节点?

持久化方案选型:

方案1: 关系型数据库(PostgreSQL)
┌──────────────────────────────────────────────────┐
│ 适用: 需要事务保证、复杂查询、审计追溯的场景       │
│                                                  │
│ agent_tasks 表:                                  │
│   task_id      UUID PRIMARY KEY                  │
│   state        ENUM(IDLE/PLANNING/.../FAILED)    │
│   plan         JSONB       -- 执行计划            │
│   current_step INT         -- 当前步骤号          │
│   step_results JSONB       -- 每步结果数组         │
│   error_info   JSONB       -- 错误详情            │
│   retry_count  INT DEFAULT 0                     │
│   created_at   TIMESTAMP                         │
│   updated_at   TIMESTAMP                         │
│   completed_at TIMESTAMP                         │
│   user_id      VARCHAR     -- 发起用户            │
│   metadata     JSONB       -- 扩展字段            │
│                                                  │
│ 优势: ACID事务、SQL查询、成熟生态                  │
│ 劣势: 高频写入性能瓶颈、JSONB查询不如文档数据库     │
│ 金融场景推荐: ✅ (合规审计要求)                    │
└──────────────────────────────────────────────────┘

方案2: Redis (内存+持久化)
┌──────────────────────────────────────────────────┐
│ 适用: 高频读写、短时任务、需要TTL自动清理          │
│                                                  │
│ Key设计:                                         │
│   agent:task:{task_id}        → Hash (状态数据)   │
│   agent:task:{task_id}:steps  → List (步骤结果)   │
│   agent:queue:pending         → Sorted Set(按优先级)│
│                                                  │
│ 优势: 极快读写、原生TTL、Pub/Sub通知              │
│ 劣势: 数据持久化不如PG可靠、查询能力弱            │
│ 推荐: 高并发+短时任务 或 作为PG前的缓存层          │
└──────────────────────────────────────────────────┘

方案3: 混合方案(推荐)
┌──────────────────────────────────────────────────┐
│ Redis (热数据)  +  PostgreSQL (持久化+审计)        │
│                                                  │
│ 流程:                                            │
│   1. Agent执行时,状态写入Redis(低延迟)            │
│   2. 每个状态转换同步写入PG(持久化)                │
│   3. 任务完成后,Redis数据设TTL(7天后自动删除)     │
│   4. PG数据永久保留(审计+分析)                    │
│                                                  │
│ → 兼顾性能和持久化                                │
│ → 类似银行的"联机系统+流水台账"双写架构            │
└──────────────────────────────────────────────────┘

实际代码模式(伪代码):

class AgentStateStore:
    def save_state(task_id, state_data):
        # 1. 写Redis(热存储)
        redis.hset(f"agent:task:{task_id}", state_data)
        # 2. 写PG(持久化+审计)
        db.execute("""
            INSERT INTO agent_tasks (task_id, state, ...)
            VALUES (%s, %s, ...)
            ON CONFLICT (task_id) DO UPDATE SET ...
        """, [task_id, state_data])

    def load_state(task_id):
        # 先查Redis(快)
        state = redis.hgetall(f"agent:task:{task_id}")
        if not state:
            # Redis没有(过期/重启)则查PG
            state = db.query("SELECT * FROM agent_tasks WHERE task_id=%s", task_id)
        return state

知识点2: 错误处理策略 — 四层防御体系

Agent为什么特别容易出错

Agent出错的概率 远高于 传统软件:

传统API服务:
  错误来源 = 代码Bug + 网络抖动 + 数据库宕机
  → 大部分可预测、可测试
  → 给定相同输入,产出相同输出(确定性)

Agent:
  错误来源 = 以上所有 + LLM不确定性 + 工具调用失败 + 规划错误
  → LLM可能返回无法解析的格式
  → LLM可能"幻觉"出不存在的工具名
  → LLM可能陷入无限循环(反复调用同一工具)
  → 外部工具可能超时/限流/返回意外结果
  → LLM的"推理"可能走进死胡同
  → 给定相同输入,可能产出不同输出(非确定性)

一个6步Agent的成功概率估算:
  假设每步成功率 = 95% (已经很高了)
  6步全部成功 = 0.95^6 = 73.5%
  → 超过1/4的任务会在某一步失败

  假设每步成功率 = 90%
  6步全部成功 = 0.90^6 = 53.1%
  → 接近一半会失败!

→ 健壮的错误处理不是"加分项",而是Agent能用的"基本要求"

第一层: 重试策略(Retry)

重试是最简单也最有效的错误处理:

基础重试:
  if step_failed:
      for i in range(max_retries):
          wait(delay)
          result = retry_step()
          if result.success:
              break

重试策略选型:
┌──────────────┬──────────────────┬──────────────────┬──────────────────┐
│ 策略          │ 固定间隔          │ 指数退避          │ 指数退避+抖动     │
├──────────────┼──────────────────┼──────────────────┼──────────────────┤
│ 间隔          │ 1s, 1s, 1s, 1s  │ 1s, 2s, 4s, 8s  │ 1±0.5s, 2±1s... │
│ 适用          │ 偶发性错误        │ 限流/过载         │ 多Agent并发      │
│ 优势          │ 简单              │ 给服务恢复时间    │ 避免重试风暴     │
│ 劣势          │ 可能加重过载      │ 多个Client同步重试│ 实现略复杂       │
│ Agent推荐    │ ❌               │ ✅               │ ✅✅(多实例时)    │
└──────────────┴──────────────────┴──────────────────┴──────────────────┘

不同错误类型的重试策略:
┌──────────────────┬──────────────┬──────────────┬──────────────┐
│ 错误类型          │ 是否重试      │ 最大重试次数  │ 间隔策略      │
├──────────────────┼──────────────┼──────────────┼──────────────┤
│ LLM返回格式错误   │ ✅ 重试      │ 3次          │ 固定1s        │
│ LLM限流(429)     │ ✅ 重试      │ 5次          │ 指数退避      │
│ 工具API超时       │ ✅ 重试      │ 3次          │ 指数退避      │
│ 工具API返回5xx   │ ✅ 重试      │ 3次          │ 指数退避+抖动 │
│ 工具API返回4xx   │ ❌ 不重试     │ -            │ -            │
│ LLM幻觉工具名    │ ✅ 重试(换Prompt)│ 2次       │ 固定1s        │
│ 认证过期          │ ✅ 刷新后重试 │ 1次          │ -            │
│ 余额不足          │ ❌ 不重试     │ -            │ -            │
│ 业务逻辑错误      │ ❌ 不重试     │ -            │ -            │
└──────────────────┴──────────────┴──────────────┴──────────────┘

关键原则: 只重试"瞬态错误"(Transient Error),不重试"永久错误"(Permanent Error)
  瞬态: 网络超时、限流、临时不可用 → 过一会可能好了
  永久: 参数错误、权限不足、业务规则不允许 → 重试100次也不会好

金融类比:
  银行转账超时 → 查询交易状态 → 未成功则重试
  银行转账余额不足 → 直接返回错误,不重试

第二层: 回退策略(Fallback)

重试解决不了时,降级到备选方案:

回退层次:

Layer 1: 模型回退
  GPT-4o失败 → 尝试Claude → 尝试GPT-4o-mini
  → 用更小/更便宜的模型,可能质量低一点但至少有结果
  → 类似银行主系统故障切备用系统

Layer 2: 工具回退
  主API失败 → 备用API → 本地缓存
  → 获取实时股价: Yahoo Finance API → Alpha Vantage → 本地缓存最后已知价格
  → 类似银行跨行查询CNAPS不通走"手工查询"

Layer 3: 策略回退
  复杂多步方案失败 → 退化为简单方案
  → 原计划: 多工具协作分析→生成报告→发送邮件
  → 回退: 仅用LLM根据已有信息生成简要回答
  → 类似银行系统降级: 全量功能→核心功能→只读模式

Layer 4: 人工回退
  自动化全部失败 → 转人工处理
  → 记录已完成的步骤和当前状态
  → 通知人工处理,附带完整上下文
  → 类似银行柜面"系统故障,请稍后"

回退决策树:
  ┌─ 错误发生
  ├─ 是否可重试?
  │   ├─ YES → 重试(最多N次)
  │   │   ├─ 重试成功 → 继续
  │   │   └─ 重试失败 → 进入回退
  │   └─ NO → 直接进入回退
  ├─ 是否有备选模型/工具?
  │   ├─ YES → 尝试备选方案
  │   │   ├─ 备选成功 → 继续(标记为降级)
  │   │   └─ 备选失败 → 进入下一层回退
  │   └─ NO → 进入下一层回退
  ├─ 是否可简化策略?
  │   ├─ YES → 执行简化版
  │   └─ NO → 进入人工接管
  └─ 人工接管(最后防线)

第三层: 人工接管(Human-in-the-Loop)

Agent不能"自作主张"的场景:

强制人工确认的场景(金融领域):
├── 金额超过阈值: Agent要转账>$10,000 → 必须人工确认
├── 不可逆操作: 发送邮件/提交订单/签署合同 → 必须人工确认
├── 低置信度: LLM输出confidence<0.7 → 请求人工判断
├── 敏感数据: 涉及PII/客户数据操作 → 必须人工授权
└── 异常检测: Agent行为偏离预期模式 → 暂停等待人工审查

Human-in-the-Loop模式:

模式1: 审批门(Approval Gate)
  Agent执行到关键步骤 → 暂停 → 发送审批请求 → 等待 → 人工审批 → 继续/终止
  实现:
    状态: EXECUTING → WAITING_APPROVAL
    通知: 通过Slack/邮件/App推送发送审批请求
    超时: 设置审批超时时间(如24小时),超时自动按保守策略处理
    记录: 审批人、审批时间、审批意见全部记录

模式2: 建议+确认(Suggest & Confirm)
  Agent生成建议方案 → 展示给用户 → 用户选择/修改 → Agent执行
  → 适用于: 投资建议、报告生成、方案设计
  → 类似: 理财经理给客户展示方案,客户确认后执行

模式3: 异常升级(Exception Escalation)
  Agent正常运行 → 检测到异常 → 升级给人工 → 人工处理后Agent继续
  → 适用于: 大部分任务自动完成,少数异常需人工干预
  → 类似: 银行自动审批系统遇到可疑申请→转人工审核

超时处理:
  人工不可能24小时在线,必须有超时策略:
  ├── 低风险: 超时后自动按保守方案执行
  ├── 中风险: 超时后暂停任务,等待下次人工上线处理
  ├── 高风险: 超时后自动回退所有已执行步骤
  └── 通知: 超时前发送提醒(1小时/30分钟/5分钟)

第四层: 优雅降级(Graceful Degradation)

当Agent完全无法完成任务时,要"优雅地失败":

优雅降级 vs 硬失败:

硬失败:
  用户请求: "帮我分析特斯拉最新财报并发送报告"
  结果: Error 500 — Internal Server Error
  → 用户一脸懵逼,不知道发生了什么

优雅降级:
  用户请求: "帮我分析特斯拉最新财报并发送报告"
  结果: "我已经获取了特斯拉最新财报的关键数据,但由于邮件服务暂时不可用,
        无法自动发送报告。以下是分析摘要:[...]
        完整报告已保存在您的工作区,邮件服务恢复后将自动发送。"
  → 用户知道发生了什么,已完成的部分没丢,有明确的后续预期

优雅降级的层次:

Level 1: 完成主要任务,跳过次要任务
  目标: 分析财报 + 生成图表 + 发送邮件
  实际: 分析财报(✅) + 生成图表(❌图表服务挂了) + 发送邮件(✅)
  → 告知用户图表生成失败,但文字分析和邮件发送已完成

Level 2: 部分结果 + 解释
  目标: 对比5个ETF的表现
  实际: 成功获取3个(✅),2个API超时(❌)
  → 返回已获取的3个ETF对比结果,说明另外2个暂时无法获取

Level 3: 无法执行 + 替代建议
  目标: 用xx工具分析数据
  实际: 该工具不可用
  → "xx工具目前不可用。您可以: (1)稍后重试 (2)使用yy工具替代 (3)我直接基于已有信息给出初步分析"

金融场景的降级策略:
  理财推荐Agent:
    Level 1: 实时行情不可用 → 使用延迟15分钟的行情
    Level 2: 行情全部不可用 → 使用昨日收盘价
    Level 3: 行情+持仓数据都不可用 → 返回通用投资建议
    Level 4: LLM也挂了 → 返回预设的FAQ回答

  → 永远不要让用户看到一个空白页或500错误
  → 有多少数据就做多少事,告诉用户"做了什么/没做什么/为什么"

知识点3: 长时任务管理

Agent长时任务的挑战

Agent任务的执行时间可以很长:

短任务 (<10秒):
  用户问: "ETH当前价格是多少?"
  Agent: 调用价格API → 返回结果
  → 同步等待即可

中等任务 (10秒-5分钟):
  用户问: "分析这份50页的PDF财报"
  Agent: 解析PDF → 分段分析 → 汇总结论
  → 需要进度反馈(Streaming)

长任务 (5分钟-数小时):
  用户问: "监控这10个Token的价格,每小时报告一次"
  Agent: 持续监控 → 定时汇报 → 异常告警
  → 需要Checkpoint + 异步通知

超长任务 (数天):
  用户: "跟踪这个Proposal的投票进展,有结果通知我"
  Agent: 监听链上事件 → 等待投票结束 → 汇报结果
  → 需要持久化调度 + 定时唤醒

挑战:
├── 超时: HTTP请求有超时限制(30s/60s),长任务不能同步等待
├── 进程生命周期: 服务可能重启/扩缩容,任务不能绑定在单个进程
├── 资源占用: 长时间占着内存/连接,浪费资源
├── 用户体验: 用户不能傻等,需要知道进度
└── 故障恢复: 长任务中间断了,必须能从断点继续

Checkpoint/Resume机制

Checkpoint = Agent版本的"游戏存档"

核心思想:
  在每个关键步骤完成后保存状态(Checkpoint)
  如果失败,从最近的Checkpoint恢复(Resume)
  不需要从头开始

设计模式:

class AgentCheckpoint:
    task_id: str
    checkpoint_id: str
    step_index: int           # 完成到第几步
    step_results: List[dict]  # 前面所有步骤的结果
    agent_memory: dict        # Agent的"记忆"(对话历史/中间思考)
    tool_states: dict         # 工具的状态(如已查询的数据、已创建的临时文件)
    timestamp: datetime

    def save(self):
        """每步完成后调用"""
        store.save_checkpoint(self)

    def restore(self) -> AgentState:
        """从Checkpoint恢复Agent状态"""
        return AgentState(
            step_index=self.step_index,
            context=self.step_results,
            memory=self.agent_memory
        )

Checkpoint粒度选择:

粒度太细(每次LLM调用都存):
  优势: 恢复时损失最小
  劣势: 大量IO开销,影响性能
  适用: 高价值任务(金融交易类)

粒度适中(每个工具调用后存):
  优势: 平衡性能和恢复粒度
  劣势: 可能需要重新执行部分LLM推理
  适用: 大多数场景(推荐默认)

粒度粗(每个阶段完成后存):
  优势: 最小IO开销
  劣势: 恢复时可能需要重做较多工作
  适用: 快速任务/对性能极其敏感的场景

金融类比:
  交易系统的WAL(Write-Ahead Log):
    每笔交易执行前,先写日志
    系统崩溃后,根据WAL重放恢复

  Agent的Checkpoint:
    每步执行后,保存状态
    进程崩溃后,根据Checkpoint恢复继续

  → 本质相同: 都是"先记录再执行"的可靠性模式

超时管理

多级超时控制:

Level 1: 单步超时 (Step Timeout)
  每个工具调用/LLM调用的超时时间
  LLM调用: 30-120秒 (取决于模型和任务复杂度)
  API调用: 10-30秒 (外部服务)
  数据库查询: 5-15秒

Level 2: 任务总超时 (Task Timeout)
  整个Agent任务的最长执行时间
  简单查询任务: 60秒
  分析报告任务: 5分钟
  监控类任务: 按Schedule运行,每次不超过10分钟

Level 3: 等待超时 (Wait Timeout)
  等待外部事件(人工审批/链上确认)的超时
  人工审批: 24-48小时
  链上交易确认: 5-30分钟(取决于链)

超时处理流程:
  ┌─ 超时发生
  ├─ 记录: 记录超时发生的步骤、已耗时、已完成的工作
  ├─ 评估: 是否可以继续(只是某个API慢了)?
  │   ├─ YES → 延长超时/切换备选方案
  │   └─ NO → 进入错误处理流程
  ├─ 保存: 保存Checkpoint(已完成的部分不丢)
  └─ 通知: 通知用户任务超时,提供已完成部分的结果

实际经验:
  超时设置不是越长越好:
  ├── 太短: 正常任务被误杀 → 用户体验差
  ├── 太长: 失败的任务占着资源不释放 → 资源浪费
  ├── 建议: P95延迟的3-5倍作为超时阈值
  └── 监控: 持续收集各步骤的延迟分布,动态调整超时阈值

知识点4: LangGraph状态管理实战

LangGraph是什么

LangGraph (2025-2026最主流的Agent工程框架):

定位:
  LangChain = Agent开发的"瑞士军刀"(什么都能做,但不够结构化)
  LangGraph = Agent开发的"状态机引擎"(专注于状态管理和流程编排)

核心概念:
  Graph: Agent的执行流程用有向图表示
  Node:  图中的节点 = 一个处理步骤(LLM调用/工具调用/逻辑判断)
  Edge:  图中的边 = 步骤间的转换规则(条件分支/顺序/并行)
  State: 在图的节点间传递的状态对象

为什么LangGraph适合状态管理:
├── 内置状态持久化(支持SQLite/PostgreSQL/自定义存储)
├── 内置Checkpoint机制(每个节点执行后自动保存)
├── 内置Human-in-the-Loop(interrupt_before/interrupt_after)
├── 内置并行执行(多个节点可并行运行)
├── 内置子图(Sub-graph)(大任务拆分为子任务)
└── 支持流式输出(Streaming)

LangGraph状态管理代码模式

# LangGraph Agent状态管理示例(伪代码)

from langgraph.graph import StateGraph, END
from langgraph.checkpoint.postgres import PostgresSaver
from typing import TypedDict, Annotated, List

# 1. 定义状态结构
class AgentState(TypedDict):
    task: str                          # 用户任务描述
    plan: List[str]                    # 执行计划
    current_step: int                  # 当前步骤
    step_results: List[dict]           # 每步结果
    final_answer: str                  # 最终答案
    error: str                         # 错误信息
    retry_count: int                   # 重试次数

# 2. 定义节点函数
def plan_node(state: AgentState) -> AgentState:
    """规划节点: LLM生成执行计划"""
    plan = llm.invoke(f"为以下任务制定执行计划: {state['task']}")
    return {"plan": parse_plan(plan), "current_step": 0}

def execute_node(state: AgentState) -> AgentState:
    """执行节点: 执行当前步骤"""
    step = state["plan"][state["current_step"]]
    try:
        result = execute_step(step)  # 调用工具/LLM
        return {
            "step_results": state["step_results"] + [result],
            "current_step": state["current_step"] + 1,
            "error": "",
            "retry_count": 0
        }
    except Exception as e:
        return {"error": str(e)}

def error_handler(state: AgentState) -> AgentState:
    """错误处理节点"""
    if state["retry_count"] < 3:
        return {"retry_count": state["retry_count"] + 1}
    return {"final_answer": f"任务执行失败: {state['error']}"}

def summarize_node(state: AgentState) -> AgentState:
    """总结节点: 汇总所有步骤结果"""
    summary = llm.invoke(f"汇总以下结果: {state['step_results']}")
    return {"final_answer": summary}

# 3. 定义路由函数
def should_continue(state: AgentState) -> str:
    if state.get("error"):
        return "error_handler"
    if state["current_step"] >= len(state["plan"]):
        return "summarize"
    return "execute"

# 4. 构建图
graph = StateGraph(AgentState)
graph.add_node("plan", plan_node)
graph.add_node("execute", execute_node)
graph.add_node("error_handler", error_handler)
graph.add_node("summarize", summarize_node)

graph.add_edge("plan", "execute")
graph.add_conditional_edges("execute", should_continue)
graph.add_edge("error_handler", "execute")  # 重试
graph.add_edge("summarize", END)

graph.set_entry_point("plan")

# 5. 配置持久化(关键!)
checkpointer = PostgresSaver.from_conn_string("postgresql://...")
app = graph.compile(checkpointer=checkpointer)

# 6. 运行Agent(带Checkpoint)
config = {"configurable": {"thread_id": "task-001"}}
result = app.invoke(
    {"task": "分析特斯拉最新财报", "step_results": [], "retry_count": 0},
    config=config
)

# 7. 中断恢复: 如果进程崩溃,使用同一个thread_id恢复
# LangGraph会自动从最后一个Checkpoint继续
result = app.invoke(None, config=config)  # 传入None = 从Checkpoint继续

LangGraph Human-in-the-Loop

# LangGraph内置的人工审批机制

# 在编译时指定需要人工审批的节点
app = graph.compile(
    checkpointer=checkpointer,
    interrupt_before=["execute_trade"]  # 执行交易前暂停
)

# 运行到interrupt_before节点时会自动暂停
result = app.invoke(initial_state, config)
# result.status = "interrupted"

# 人工审核Agent的计划
pending_trade = app.get_state(config).values["pending_trade"]
print(f"Agent计划执行: {pending_trade}")

# 人工确认后,发送继续执行的指令
if human_approves(pending_trade):
    # 方式1: 直接继续
    app.invoke(None, config)  # 继续执行

    # 方式2: 修改状态后继续
    app.update_state(config, {"pending_trade": modified_trade})
    app.invoke(None, config)
else:
    # 人工拒绝: 更新状态为取消
    app.update_state(config, {"status": "cancelled_by_human"})

→ 整个过程状态自动持久化
→ 即使在等待人工审批期间服务重启,也能恢复
→ 金融场景的"双重确认"可以用这个模式实现

知识点5: 幂等性设计

为什么Agent需要幂等性

幂等性(Idempotency): 同一操作执行多次的效果 = 执行一次的效果

Agent为什么需要幂等:
├── 重试: 步骤失败后重试,不能产生重复效果
├── 恢复: 从Checkpoint恢复后重新执行,不能重复执行已完成的操作
├── 并发: 多个Agent实例可能收到同一个任务
└── 网络: 网络超时导致"不知道是否成功"的情况

没有幂等性的灾难场景:

场景1: 转账Agent
  Step 1: 查询余额 ✅
  Step 2: 发起转账100元 → 网络超时(不知道是否成功)
  重试 Step 2: 又转了100元
  → 用户被扣了200元!

场景2: 邮件Agent
  Step 1: 生成报告 ✅
  Step 2: 发送邮件 → 超时
  重试 Step 2: 又发了一封
  → 用户收到两封一样的邮件

场景3: 下单Agent
  Step 1: 查询产品 ✅
  Step 2: 创建订单 → 服务重启
  恢复后重新执行 Step 2: 又创建了一个订单
  → 用户有了两个相同的订单

幂等性设计模式

模式1: 幂等Key (Idempotency Key)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  每个操作分配一个唯一的Key
  执行前检查Key是否已经执行过
  如果已执行 → 返回之前的结果(不重复执行)
  如果未执行 → 执行并记录结果

  # 伪代码
  def execute_with_idempotency(key, operation):
      existing = db.get(f"idempotency:{key}")
      if existing:
          return existing.result  # 已执行过,直接返回
      result = operation()
      db.set(f"idempotency:{key}", result, ttl=7days)
      return result

  # Agent使用
  idempotency_key = f"{task_id}:{step_index}:{step_hash}"
  result = execute_with_idempotency(idempotency_key, lambda: call_api(...))

  金融类比: 银行转账的交易流水号
    每笔转账有唯一流水号
    重复提交同一流水号 → 查询已有结果而非重复执行
    → 这就是为什么银行要求"幂等提交"


模式2: 状态检查 (Check-then-Act)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  执行前先检查目标状态,已达到目标则跳过

  # 伪代码
  def idempotent_send_email(task_id, email_content):
      if db.query(f"SELECT sent FROM task_steps WHERE task_id={task_id} AND step='send_email'"):
          return "already sent"  # 已发送,跳过
      send_email(email_content)
      db.update(f"UPDATE task_steps SET sent=true WHERE task_id={task_id} AND step='send_email'")

  注意: Check和Act之间可能有并发问题
  → 需要数据库锁或乐观锁保证原子性


模式3: 补偿操作 (Compensating Action)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  有些操作天然不幂等(如发邮件)
  → 不追求幂等,而是在失败时执行"补偿操作"

  正向操作: 发送报告邮件
  补偿操作: 发送撤回/更正邮件

  正向操作: 创建订单
  补偿操作: 取消订单

  正向操作: 转账到对方账户
  补偿操作: 冲正(反向转账)

  → 类似银行的冲正交易(Reversal Transaction)
  → Saga模式的核心思想

Agent幂等性最佳实践:
├── 每个步骤生成唯一的idempotency_key
├── 有副作用的工具调用必须支持幂等
├── Checkpoint保存已完成步骤的标记
├── 恢复时跳过已完成的步骤
├── 对外部API调用传递idempotency_key(如Stripe的Idempotency-Key头)
└── 不可幂等的操作必须有补偿方案

知识点6: 错误恢复的完整流程

端到端错误恢复架构

完整的Agent错误恢复流程:

┌─────────────────────────────────────────────────────────────────┐
│                    Agent Runtime Engine                          │
│                                                                 │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐ │
│  │ Step 1   │───→│ Step 2   │───→│ Step 3   │───→│ Step 4   │ │
│  │ (LLM)    │    │ (API)    │    │ (LLM)    │    │ (Email)  │ │
│  └────┬─────┘    └────┬─────┘    └────┬─────┘    └────┬─────┘ │
│       │               │               │               │       │
│  ┌────▼─────┐    ┌────▼─────┐    ┌────▼─────┐    ┌────▼─────┐ │
│  │Checkpoint│    │Checkpoint│    │Checkpoint│    │Checkpoint│ │
│  │    #1    │    │    #2    │    │    #3    │    │    #4    │ │
│  └────┬─────┘    └────┬─────┘    └────┬─────┘    └────┬─────┘ │
│       │               │               │               │       │
│  ─────┴───────────────┴───────────────┴───────────────┴────── │
│                    State Store (PG + Redis)                     │
│                                                                 │
│  错误处理层:                                                     │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐      │
│  │  重试器   │  │  回退器   │  │ 人工接管  │  │ 降级处理  │      │
│  │ Retryer  │  │ Fallback │  │   HITL   │  │ Degrader │      │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘      │
│                                                                 │
│  监控层:                                                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                     │
│  │  日志    │  │  指标    │  │  告警    │                      │
│  │ Logging  │  │ Metrics  │  │ Alerts   │                      │
│  └──────────┘  └──────────┘  └──────────┘                     │
└─────────────────────────────────────────────────────────────────┘

错误恢复的决策流程:

  1. 检测错误类型
     ├── 瞬态错误(Transient): 网络超时、限流、临时不可用
     ├── 永久错误(Permanent): 参数错误、权限不足、资源不存在
     └── 未知错误(Unknown): 异常结构无法识别

  2. 瞬态错误 → 重试
     ├── 指数退避重试(1s → 2s → 4s → 8s)
     ├── 最多重试3次
     ├── 每次重试前检查idempotency
     └── 重试成功 → 继续; 重试失败 → 进入回退

  3. 永久错误 → 回退/降级
     ├── 有备选方案 → 执行回退
     ├── 可简化 → 执行降级版本
     ├── 不可执行 → 记录错误
     └── 是否有副作用需要补偿? → 执行补偿

  4. 无法自动处理 → 人工接管
     ├── 保存完整上下文(Checkpoint + 错误信息)
     ├── 通知人工(Slack/邮件/系统通知)
     ├── 等待人工决策
     └── 人工决策后 → 继续执行 / 回退 / 终止

  5. 任何结果 → 记录审计日志
     ├── 任务ID、步骤、错误类型、处理方式、最终结果
     ├── 耗时统计
     └── 用于后续分析和改进

错误恢复指标

监控Agent错误恢复效果的关键指标:

┌──────────────────┬──────────────────┬──────────────────┐
│ 指标              │ 计算方式          │ 健康阈值          │
├──────────────────┼──────────────────┼──────────────────┤
│ 任务成功率        │ 成功任务/总任务    │ >95%             │
│ 首次成功率        │ 无需重试的任务/总  │ >85%             │
│ 重试成功率        │ 重试后成功/总重试  │ >70%             │
│ 回退触发率        │ 触发回退/总任务    │ <10%             │
│ 人工接管率        │ 需人工介入/总任务  │ <5%              │
│ 平均恢复时间      │ 从错误到恢复的时间 │ <30s(自动)       │
│ 数据丢失率        │ Checkpoint恢复失败 │ 0% (零容忍)      │
│ 补偿操作成功率    │ 补偿成功/需补偿    │ >99%             │
└──────────────────┴──────────────────┴──────────────────┘

告警阈值:
  任务成功率 < 90% → P1告警(立即处理)
  人工接管率 > 10% → P2告警(4小时内处理)
  数据丢失 > 0 → P0告警(立即升级)

金融类比:
  银行交易系统的SLA通常要求:
    交易成功率 > 99.9%
    异常交易补偿成功率 > 99.99%
    → Agent的要求可以低一些,但思路一致

知识点7: 金融场景Agent状态管理特殊要求

审计追溯性

金融监管要求所有操作可追溯:

Agent审计日志要求:
├── Who: 谁触发了这个Agent任务(用户ID/系统自动)
├── What: Agent做了什么(每步的输入/输出/工具调用)
├── When: 什么时候做的(精确到毫秒的时间戳)
├── Why: 为什么这么做(LLM的推理过程/决策依据)
├── Result: 最终结果是什么
└── Context: 相关的上下文信息(市场数据/客户信息快照)

审计日志格式:
{
  "audit_id": "uuid",
  "task_id": "agent-task-001",
  "user_id": "user-123",
  "timestamp": "2026-04-23T10:30:15.123Z",
  "step_number": 3,
  "step_type": "tool_call",
  "tool_name": "check_account_balance",
  "input": {"account_id": "ACC-001"},
  "output": {"balance": 50000.00, "currency": "USD"},
  "llm_reasoning": "用户要求转账,先检查余额是否充足",
  "duration_ms": 235,
  "status": "success",
  "idempotency_key": "task-001-step-3-balance-check"
}

保留期限(金融合规):
├── 交易类操作: 至少保留7年
├── 客户咨询类: 至少保留3年
├── 系统操作日志: 至少保留1年
└── → 需要选择合适的存储方案(冷热分离)

这些要求也是为什么金融Agent选PostgreSQL做状态存储:
  → SQL查询能力强(审计查询)
  → ACID事务保证(数据一致性)
  → 成熟的备份恢复方案(数据安全)
  → 合规审计工具生态(SOC2/PCI DSS)

资金安全约束

Agent处理金融操作的特殊约束:

1. 双重确认(Maker-Checker):
   Agent生成交易指令 → Agent自检 → 人工确认 → 执行
   → 不允许Agent直接执行大额交易
   → 类似银行的"制单-审核-执行"三级控制

2. 限额控制:
   ├── 单笔限额: Agent单次操作的最大金额
   ├── 日累计限额: Agent一天内操作的总金额上限
   ├── 频率限制: Agent每分钟/每小时的最大操作次数
   └── 超限自动触发人工审核

3. 熔断机制:
   ├── 连续N次失败 → 暂停Agent(防止失控)
   ├── 异常金额检测 → 暂停Agent(防止错误)
   ├── 异常频率检测 → 限流Agent(防止滥用)
   └── 手动熔断: 管理员可随时暂停所有Agent

4. 不可逆操作保护:
   ├── 转账: 必须人工确认,提供"撤回"窗口期
   ├── 合同签署: 必须多级审批
   ├── 数据删除: 软删除+审批,而非物理删除
   └── 对外通信: 审核后发送,支持撤回

→ 这些约束应该设计在Agent状态机的转换规则中
→ 不是"Agent决定是否检查",而是"状态机强制Agent必须检查"

今日思考

思考1: Agent状态管理的成本与收益

搭建Agent状态管理系统是有成本的:

成本:
├── 开发成本: 状态机设计+持久化+Checkpoint ≈ 2-4周开发
├── 运行成本: 每步都要写状态存储 ≈ 增加10-20%延迟
├── 存储成本: 每个任务的状态+日志 ≈ 1-10KB/任务
├── 维护成本: 状态存储的运维+备份+清理
└── 复杂度: 代码复杂度增加约30-50%

收益:
├── 可靠性: 任务成功率从~75%提升到~95%
├── 可审计: 满足金融合规要求(必需,不是可选)
├── 可恢复: 服务重启不丢任务
├── 可监控: 知道Agent在做什么、做得怎么样
├── 用户信任: 用户知道任务不会"静默失败"
└── 调试效率: 出问题时能快速定位(有完整日志)

决策框架:
  内部PoC/Demo → 可以不做(速度优先)
  面向用户的产品 → 必须做(基本的可靠性保证)
  金融场景 → 必须做且要做到最完善(合规要求)

金融类比:
  银行系统不会因为"开发成本高"就不做交易日志
  → 交易日志是金融系统的"地基"
  → Agent状态管理是Agent系统的"地基"

思考2: 从银行事务管理到Agent状态管理的迁移

10年金融系统经验在Agent领域的直接迁移:

银行学到的               →  Agent可以用的
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ACID事务                  →  Checkpoint + 幂等Key
WAL日志                   →  State Store + 审计日志
补偿交易(冲正)            →  Compensating Action
制单-审核-执行             →  Plan-Review-Execute (HITL)
限额管控                  →  Agent Rate Limiting + Budget
熔断/降级                 →  Circuit Breaker + Fallback
对账                      →  状态一致性校验
批处理                    →  Agent批量任务调度

直接可用的方法论:
├── 幂等提交: 银行的交易流水号 = Agent的idempotency_key
├── 超时查证: 银行转账超时后查询状态 = Agent步骤超时后查Checkpoint
├── 异常处理: 银行的异常清算流程 = Agent的错误恢复流程
└── 审计要求: 银行的交易审计 = Agent的审计日志

→ 做过银行系统的人,天然理解Agent状态管理的重要性
→ 这是10年金融经验在AI领域的核心差异化优势之一

思考3: Agent状态管理的未来趋势

2026-2027的趋势:

1. Agent Runtime标准化:
   目前每个框架(LangGraph/CrewAI/AutoGen)各有一套状态管理
   → 未来可能出现统一的Agent Runtime标准(类似Container Runtime)
   → Open Agent Protocol/Agent Protocol等标准正在形成

2. Agent作为"长期运行的服务":
   目前Agent多是"一次性任务"(收到请求→执行→返回)
   → 未来Agent会像"后台服务"一样长期运行(持续监控/定期执行)
   → 需要更成熟的生命周期管理(启动/运行/休眠/唤醒/终止)

3. Agent的"事务"概念:
   目前没有跨Agent的事务管理
   → 未来多Agent协作时,需要"分布式事务"
   → Saga模式/两阶段提交可能被引入Agent领域

4. 声明式状态管理:
   目前: 开发者手动编写状态转换逻辑(命令式)
   → 未来: 用DSL/配置文件声明状态机(声明式)
   → 类似Kubernetes用YAML声明期望状态

面试表达

面试题: Agent在生产环境中如何保证可靠性?

结构化回答 (2-3分钟):

"Agent可靠性我会从四个层次来设计:

第一层是状态管理。用有限状态机定义Agent的执行生命周期,
每个状态转换都持久化到数据库。这样即使服务重启,
也能从最后一个Checkpoint恢复继续执行,不丢任务。
类似银行系统的WAL日志。

第二层是错误处理。分为重试、回退、人工接管三级:
瞬态错误用指数退避重试;
重试不行就回退到备选方案——比如主模型不可用切备用模型;
自动化都失败了就触发人工接管,保存完整上下文给人工处理。

第三层是幂等性设计。每个步骤分配唯一的idempotency key,
重试和恢复时不会产生重复效果。这在涉及资金操作的场景尤为关键——
银行转账用交易流水号保证不重复扣款,Agent用idempotency key保证不重复操作。

第四层是优雅降级。当Agent完全无法完成任务时,
不是返回500错误,而是返回已完成的部分结果加上清晰的解释,
告诉用户做了什么、没做什么、为什么没做到。

在金融场景,我还会加上审计日志和限额控制——
所有操作可追溯,大额操作必须人工确认。"

面试题: 如何设计Agent的错误恢复机制?

结构化回答:

"首先区分错误类型——这决定了恢复策略:

瞬态错误(网络超时、限流)→ 可重试,用指数退避+抖动避免重试风暴。
永久错误(参数错误、权限不足)→ 不重试,直接进入回退或人工处理。
未知错误 → 先重试一次,仍然失败则按永久错误处理。

恢复流程是:
1. 检测到错误 → 记录详情到State Store
2. 判断错误类型 → 决定重试/回退/升级
3. 重试: 最多3次,指数退避,每次重试前检查幂等
4. 回退: 有备选方案就切换(如换模型、换API)
5. 人工: 保存Checkpoint和完整上下文,通知人工处理
6. 任何结果: 写审计日志

关键工程细节:
- Checkpoint在每个工具调用后保存(不只是每步)
- 有副作用的操作必须有补偿方案(类似银行的冲正交易)
- 错误恢复本身也可能失败——需要对'恢复失败'也有兜底策略
- 监控错误恢复指标: 首次成功率、重试成功率、人工接管率

我的金融系统经验中,交易超时后的'查证-冲正-重发'三步法
可以直接迁移到Agent场景。"

实操练习建议

1. 用LangGraph实现一个带Checkpoint的Agent:
   → 定义3步任务(查询→分析→总结)
   → 加入PostgreSQL持久化
   → 模拟Step 2失败,验证从Checkpoint恢复
   → 观察State Store中的状态变化

2. 实现幂等性工具调用:
   → 写一个带idempotency_key的工具调用包装器
   → 模拟重复调用,验证幂等效果
   → 用Redis存储幂等记录

3. 实现Human-in-the-Loop:
   → 用LangGraph的interrupt_before功能
   → 模拟Agent到达关键步骤时暂停等待审批
   → 人工确认后继续执行

4. 设计一个金融Agent的状态机:
   → 画出完整的状态转换图(至少8个状态)
   → 定义每个状态转换的触发条件和动作
   → 考虑审计日志和限额控制
   → 写出错误恢复的决策树

资源推荐

资源说明链接
LangGraph文档Agent状态管理核心框架langchain-ai.github.io/langgraph
LangGraph PersistenceCheckpoint持久化详解LangGraph官方文档/Persistence
LangGraph Human-in-the-Loop人工接管模式LangGraph官方文档/HITL
Enterprise Patterns for Agents企业级Agent设计模式各大云厂商博客
Saga Pattern分布式事务补偿模式(微服务)microservices.io/patterns/saga
Temporal.io持久化工作流引擎(Agent的替代方案)temporal.io
Microsoft AutoGen微软Agent框架(含状态管理)github.com/microsoft/autogen
Anthropic Agent SDKClaude官方Agent开发工具docs.anthropic.com

明日预告

Day 23: Agent系统工程化(2) — 成本控制与性能优化

预习问题:
1. 一个Agent任务的LLM调用成本如何估算?如果Agent陷入循环,成本会怎样?
2. 如何在不牺牲质量的前提下降低Agent成本?有哪些"既省钱又好用"的策略?
3. Agent的延迟瓶颈在哪里?如何优化到用户可接受的范围?

连接点:
  Day 22(今天): Agent的"可靠性"问题 — 状态管理/错误恢复/幂等性
  Day 23(明天): Agent的"经济性"问题 — 成本分析/优化/性能
  → 可靠和经济是Agent生产化的两大支柱
  → 类比: 银行系统不仅要"不出错",还要"成本可控"