跳到主要内容
SUN / 笔记
← 全部文章

Agent 运行时:状态、重试与幂等

本文关注任务状态、预算、循环检测、错误分类、重试、幂等与恢复。

多轮工具调用如何始终记住核心任务

模型没有永久运行的内在记忆。每次推理时,Harness 都要重新构造有效上下文。

建议分四层维护。

固定任务契约

每轮保留:

text
核心目标
验收标准
用户约束
禁止事项
审批边界

近期工作记忆

保留最近的:

  • Tool Call;
  • Tool Result;
  • 错误信息;
  • 当前计划步骤;
  • 最新假设和观察。

模型外结构化状态

json
{
  "goal": "修复登录接口偶发 500",
  "status": "testing",
  "completed": [
    "定位 AuthService",
    "确认空指针根因",
    "完成代码修改"
  ],
  "pending": [
    "修复测试夹具",
    "运行完整测试",
    "检查 git diff"
  ],
  "changed_files": [
    "src/AuthService.java"
  ],
  "last_test": {
    "command": "mvn test -Dtest=AuthServiceTest",
    "result": "failed"
  }
}

环境状态作为外部记忆

文件系统、Git Diff、测试报告和日志比模型总结更接近事实来源。需要时重新读取,而不是把所有历史永久塞进 Prompt。

上下文过长时,压缩旧历史,但必须保留:

  • 核心目标和约束;
  • 已完成和待完成步骤;
  • 重要设计决策;
  • 当前错误和未解决问题;
  • 修改文件和测试状态。

长任务不能只依赖对话历史,还要通过 Task State、Checkpoint、进度记录和 Git 恢复真实状态。Anthropic 的长时运行 Agent Harness 实践也采用结构化功能列表、进度文件和 Git 历史帮助新上下文恢复任务。

如何防止无限循环和重复调用

不能只靠 Prompt 告诉模型“不要重复”,必须由 Harness 硬性兜底。

硬性预算

python
limits = {
    "max_turns": 30,
    "max_tool_calls": 50,
    "max_same_tool_errors": 3,
    "max_runtime_seconds": 600,
    "max_tokens": 100_000,
    "max_cost": 2.0
}

这些数字只是示例,应根据任务复杂度和真实评测确定。

重复调用指纹

不能只按工具名判断重复,而要加入参数和环境版本:

python
signature = stable_hash({
    "tool": call.name,
    "arguments": canonicalize(call.arguments),
    "environment_version": git_diff_hash,
    "task_state": current_step
})

这里的 stable_hash 与 canonicalize 是伪代码,需要使用稳定序列化后的摘要实现;Python 的字典不能直接传给内置 hash()。

合理重复:

text
修改文件前 read_file
→ apply_patch
→ 修改后再次 read_file

异常重复:

text
环境没有变化
→ 相同参数调用相同工具
→ 获得相同结果
→ 连续重复多次

无进展检测

即使工具名不同,也可能在兜圈子。因此还要检测:

  • 是否获得新证据;
  • 是否改变文件或任务状态;
  • 是否完成计划步骤;
  • 测试失败数量是否减少;
  • 是否排除一个假设;
  • 是否只是重复相同错误。

干预可以逐级升级:

text
第一次重复 → 记录
第二次重复 → 返回 LOOP_WARNING
第三次重复 → 要求重新规划或暂时禁用工具
仍无进展 → 终止并报告阻塞原因

推荐的终态:

text
success
failed
budget_exceeded
loop_detected
paused_for_approval

当前 OpenAI 模型指南也建议明确并发、重试和停止限制,并要求不要重复已完成调用。OpenAI Docs:Model guidance


工具调用出错如何处理

不能把所有错误统一成“再试一次”,应先分类。

错误类型 示例 处理策略
参数错误 缺字段、类型错误 不执行,返回结构化错误让模型修正
瞬时错误 429、5xx、短暂网络超时 Harness 有限退避重试
业务错误 文件不存在、搜索无结果 返回模型,换路径、参数或工具
状态冲突 Patch 失效、文件已变化 重新观察最新状态,再生成操作
权限错误 沙箱拒绝、无权写入 不重试,审批或报告
副作用不确定 请求超时但可能已退款 查询状态或使用幂等键,禁止盲重试
不可恢复错误 凭证缺失、环境不可用 保存状态并明确终止

结构化错误示例:

json
{
  "ok": false,
  "error": {
    "code": "PATCH_CONFLICT",
    "message": "目标文件内容已经变化,Patch 无法应用。",
    "retryable": false,
    "suggested_action": "重新读取文件,再根据最新内容生成 Patch。"
  }
}

参数错误

使用严格 JSON Schema,在执行前拒绝非法参数,并把可修正错误回填给模型。OpenAI Function Calling 文档建议启用 strict: true,使函数参数严格符合 Schema。OpenAI Docs:Strict mode

瞬时错误

由 Harness 内部采用有限指数退避和随机抖动:

text
1s → 2s → 4s → 失败并返回模型

模型无法修复短暂网络波动,因此通常不必每次重试都重新推理。

业务错误

例如文件不存在:

json
{
  "code": "FILE_NOT_FOUND",
  "retryable": false,
  "suggested_action": "先使用 search_code 或 list_files 查找真实路径。"
}

模型根据 Observation 更换策略。

有副作用的工具

read_file、search_code 等只读工具通常可以安全重试;send_email、create_refund、deploy_production 等可能产生副作用,必须:

  • 使用 idempotency_key;
  • 查询上次操作状态;
  • 记录唯一业务请求 ID;
  • 在危险操作前 Checkpoint;
  • 必要时人工审批。

对于敏感工具,模型可以提出调用,但 Harness 应暂停执行并等待审批。官方 Agent 文档将 Guardrail 用于自动校验,将 Human Review 用于敏感工具调用的批准或拒绝。OpenAI Docs:Guardrails and human review


相关阅读

相关文章

结构化输出与 Schema 校验 →