很多团队已经把 LLM 接进业务,但一到“多步任务 + 调工具 + 失败重试”就开始失控:日志看不懂、状态回不去、成本还飙升。

这篇给你一个能直接落地到 Go 服务里的最小可用方案:工具调用闭环、会话记忆分层、错误恢复可回放

1) 架构先定死:三层解耦,别让 Agent 直接碰数据库

推荐把链路拆成 3 层:

  • Orchestrator:接收用户请求,推进步骤状态机
  • Agent Runtime:和 OpenAI Agents SDK 交互,只负责推理与 tool call
  • Tool Adapter:真正执行业务动作(查单、写库、发通知),并返回结构化结果

关键原则:

  • Agent 只拿“工具契约”,不拿底层资源权限
  • 工具返回必须是可序列化 JSON(便于重放/审计)
  • 每一步都带 trace_id + idempotency_key

2) Tool Calling:先把 Schema 设计好,成功率直接翻倍

常见失败不是模型笨,而是 Schema 含糊。

建议:

  • 参数都标注类型和枚举范围
  • 时间统一 ISO8601
  • 金额统一最小货币单位(分)
  • 每个工具都返回 ok/data/error_code/error_message/retryable

Go 侧工具返回示例:

{
  "ok": false,
  "error_code": "ORDER_LOCKED",
  "error_message": "order is locked by settlement process",
  "retryable": true,
  "data": null
}

这样模型就能判断是“改参数重试”还是“升级人工处理”。

3) 会话记忆:短期上下文 + 长期摘要,不要无脑塞历史

生产环境里,记忆建议分两层:

  • 短期窗口(最近 N 轮):保证当前任务连续性
  • 长期摘要(任务级):保存关键信息,不保存冗余对话

实操策略:

  1. 每轮后做一次摘要更新(限制 300~500 tokens)
  2. 命中敏感字段前先脱敏
  3. 只把“与当前目标相关”的记忆回注给模型

否则你会遇到三连击:慢、贵、偏题。

4) 错误恢复:用状态机,不要靠 if-else 地狱

把一次请求定义成可恢复状态机:

  • RECEIVED
  • PLANNED
  • TOOL_RUNNING
  • TOOL_FAILED_RETRYABLE
  • TOOL_FAILED_FATAL
  • COMPLETED

恢复规则:

  • retryable=true:指数退避 + 最大重试次数
  • 连续失败超阈值:降级到人工队列
  • 任一步骤超时:回滚到最近可重放 checkpoint

Go 伪代码:

if step.Retryable && step.RetryCount < 3 {
    backoff := time.Second * time.Duration(1<<step.RetryCount)
    scheduleRetry(step, backoff)
} else if step.Retryable {
    moveToManualQueue(step)
} else {
    markFatal(step)
}

5) 观测与成本:上线第一天就该有的 6 个指标

最少要打这 6 个指标:

  • tool_call_success_rate
  • tool_call_p95_latency
  • agent_step_retry_rate
  • token_input/output_per_request
  • cost_per_successful_task
  • manual_handoff_ratio

再加 2 个告警:

  • 5 分钟内 retry_rate 突增
  • 单任务 token 消耗超过阈值

6) 最小上线清单(可直接抄)

  • 所有工具有 JSON Schema 与错误码字典
  • 每步状态持久化(含输入输出快照)
  • 幂等键贯穿请求与工具层
  • 重试/熔断/人工降级路径已演练
  • 关键指标接入 Prometheus/Grafana
  • 灰度发布(10% 流量)+ 回滚开关

总结

OpenAI Agents SDK + Go 真正难点不在“调通一次”,而在失败时还能稳定恢复

按本文这套分层 + 状态机 + 观测方案,你可以先把成功率和可维护性拉起来,再逐步优化效果与成本。别追求一步到位,先保证系统不会在凌晨 3 点把你叫醒。