AI Agent 总重跑?照抄不断点架构

17 min read

很多人给长任务 Agent 砸的第一笔预算,是更强的模型;但真把它放到线上,最先暴露的往往不是“不会想”,而是一断就全忘、一挂就重来。更扎心的是,跑 3 分钟的 Demo 越顺,越容易让你误以为“已经差不多了”;等任务真的要跑 3 小时、跑一整夜,你才发现自己做的不是 Agent,而是一个会定时失忆的脚本。

前两天 Discord 里就有人问我:为什么同一个 Agent,白天演示时像模像样,晚上丢进真实流程里就开始超时、卡死、上下文丢失?我当时第一反应不是去看模型参数,而是反问一句:你有没有把“脑子、手脚、账本”拆开?

这篇我就借 Anthropic 那篇工程文章《Scaling Managed Agents: Decoupling the brain from the hands》的抽象(session / harness / sandbox),拆一套个人也能照抄的“不断点 Agent”设计法:把“脑子、手脚、账本”分开,任何一个坏了都能换新的继续跑。原文在这,建议先收藏:https://www.anthropic.com/engineering/managed-agents
官方 Managed Agents docs 也一并放这:https://platform.claude.com/docs/en/managed-agents/overview


为什么很多 Agent Demo 能跑,真到生产就开始卡死 / 丢上下文 / 难恢复?

直接回答:因为你把“模型对话”“执行环境”“状态记录”塞进了同一个进程或容器里;一旦它卡住或重启,状态没了、证据没了、恢复点也没了

Demo与生产Agent架构对比图 你可以把一个长任务 Agent 想成一家小餐馆:

  • 脑子:大厨(模型 + 规划)
  • 手脚:后厨灶台、刀具、外卖骑手(代码执行、文件编辑、外部工具)
  • 账本:收银台流水(每一步做了什么、拿到了什么结果)

Demo 常见的做法是:大厨、后厨、收银台全挤在一个小屋里。屋子一断电,三样一起没。

生产环境的做法刚好相反:收银台流水必须在屋子外面,能持久化;后厨可以随时换新,能重建;大厨的“领班流程”也要能换班,能重启继续跑。


Managed Agents 到底解决了哪件你平时不太会想到的事?

Anthropic 这篇文章里有个很经典的基础设施比喻:别养“宠物机”(pet),要养“牛群”(cattle)。

Agent三层拆分架构示意 他们一开始也把 session / harness / sandbox 全塞进一个容器里。这样做确实省事,开发也快,改文件就是 syscall 直改,早期几乎每个人都会这么搭。

但是问题很快就来了:有的容器会卡死,你只能从 WebSocket 事件流里看见“它不动了”,却很难判断到底是 harness 有 bug、事件流丢包,还是容器本身已经挂了。更麻烦的是,工程师想进容器排查,又可能碰到用户数据——等于你连 debug 这件事都开始带风险

所以他们后来把 Agent 拆成了三个独立抽象。我这里还是沿用餐馆比喻,比较不绕:

  • session:只追加的流水账本
  • harness:领班,负责循环调度
  • sandbox:后厨灶台,负责真正干活

关键动作就一句:领班不住在后厨里。
后厨挂了就换一个;领班挂了也能换一个;账本永远待在收银台,不跟任何人同生共死。


你真正要照抄的核心:把“脑子、手脚、日志”彻底解耦

下面这段是全篇最值得带走的东西。

一体式 vs 解耦式不断点架构对比 不断点 Agent 的本质,是让任何一次失败,都只损失“正在执行的那一步”,而不是损失“整个任务”。
做到这一点,你至少要保住两样东西:账本(session log)和恢复点(cursor / checkpoint)。

我把两种架构放一张表里,你扫一眼就能知道自己现在更像哪种:

维度一体式(最常见的 Demo)解耦式(不断点)
状态在哪里内存 / 本地文件 / 容器里外部持久化 session log(数据库 / 对象存储都行)
失败表现一挂就“全没了”挂了可从最后事件恢复
工具执行跟模型进程同生共死sandbox / worker 可替换、可重建
Debug 入口只能 ssh / exec 进容器看主要靠事件日志回放 + 指标
换模型成本容易牵一发动全身harness 更像“适配层”,模型可替换
扩展性一加并发就抖session 独立后更容易水平扩展
一个很现实的坑:你只要允许 Agent “写文件 / 发邮件 / 改表”,但又没有事件日志和幂等(idempotency)设计,你的重试就可能变成“重复执行”,比失败更糟。

session / harness / sandbox 分别是什么?最小版本怎么做?

我不想把你往“复杂框架”里推。下面给的是最小可用拆分,今天就能往自己的 Agent 项目里塞。

Session-Harness-Sandbox最小架构图

1) session:把它当成“只追加的收银流水”

session 不是“对话历史”,而是发生过的一切:模型输入输出、工具调用参数、工具返回值、错误、重试次数、耗时、你人为插入的检查点。

最小实现建议:一张表,或者一个对象存储结构,按时间顺序追加事件。

事件结构可以先抄这个,别一上来追求完美:

json{
  "sessionId": "sess_123",
  "seq": 42,
  "ts": "2026-05-22T10:18:00Z",
  "type": "tool_result",
  "toolName": "execute",
  "inputHash": "sha256:...",
  "payload": { "stdout": "...", "stderr": "", "exitCode": 0 },
  "error": null
}

你需要的不是“字段越多越高级”,而是下面三个能力:

  • 追加(append):任何一步发生了什么,都能写进去
  • 回放(replay):从 seq=N 开始把后续事件读出来
  • 定位(debug):你能回答“它卡在哪里、上一步做了什么、失败是什么错误”

这里有个很反直觉的点:session 写得越“啰嗦”,你后面越省时间。因为你省下来的,是第二天追日志、猜现场、重建事故的时间。

2) harness:把它当成“可随时换班的领班”

harness 就是那个 while-loop:给模型看上下文 → 模型决定下一步(调用工具 / 继续思考 / 结束)→ 执行工具 → 把结果写回 session → 继续下一轮。

照抄 Anthropic 的关键思想:harness 本身不要存“非活不可”的状态。它随时可以挂,随时可以被拉起,然后:

  • wake(sessionId):领班上岗
  • getSession(sessionId):先把账本读一遍,找到最后安全的恢复点
  • 从最后一个 checkpoint 继续跑

如果你这篇只记住一个实现细节,那就是:请给 harness 加一个“恢复游标(cursor)”,永远只处理 session 里 cursor 之后的新事件。

3) sandbox:把它当成“可一键重置的后厨灶台”

sandbox 可以是:

  • 一个临时容器(Docker / 云函数 / 任意 worker)
  • 一台隔离 VM
  • 一个受限的执行进程(自己做沙箱也行,但维护成本通常更高)

重点不是技术选型本身,而是契约。harness 调用 sandbox,最好像调普通工具一样简单:

  • provision(resources):给我一个干净灶台
  • execute(command, cwd, filesRef):跑一段命令 / 脚本
  • snapshot():把当前工作目录打包成一个引用(对象存储地址 / 哈希)
  • destroy():灶台用完就砸掉

你会发现,一旦 sandbox 变成“可替换的耗材”,你就不再需要费力去“救活那台快死的机器”。


有天夜里我在服务器里翻我们自己的任务日志,看到一条特别熟悉的曲线:前 20 分钟一切顺利,然后开始出现零星超时;接着重试把队列塞满;最后任务被 watchdog 干掉,日志只剩一句 “connection closed”。

最难受的不是失败,是你根本不知道它失败前到底做到哪了。你想补救,只能重跑。那种感觉很像早上起来发现电脑没保存,但更糟,因为这回丢的不是文档,是整段任务执行过程。

我后来回头看,问题并不在模型答得差。模型该调工具的时候调了,该继续的时候也继续了,真正塌掉的是中间那层“执行和记账”没分开。话说回来,我也不敢说只要拆成 session / harness / sandbox 就万事大吉,具体恢复粒度、checkpoint 频率、snapshot 成本,还是得按你的业务压测;但至少从那次之后,我对“先把模型换大一点试试”这条路基本不太信了。

还有一个很现实的坑是:重跑不一定安全。要是上一次其实已经“写入成功,但你没记账”,那这次重跑就可能直接把用户数据再写一份。所以我现在看到“长任务 Agent”,第一反应不是选模型,而是问:你账本在哪?你恢复点在哪?


长任务 Agent 怎么做,才不会一崩全白干?

直接回答:把 session 作为真相源(source of truth),让 harness 可重启、sandbox 可重建;同时给每次外部写操作加幂等键,保证重试不会重复生效。

长任务Agent可恢复7步流程图 下面给你一套“最小不断点流程”。不是最优解,但对大多数个人项目和小团队来说,已经够实用了。

方法论:7 步把你的 Agent 变成“可恢复任务”

  1. 定义 session 存储
  • 做什么:选一个持久化介质(Postgres / SQLite / 对象存储都行)
  • 在哪做:你的服务端
  • 怎么判断做对了:进程 kill 掉再拉起,session 还能完整读回
  1. 把所有关键动作写成事件
  • 做什么:模型输出、工具调用、工具返回、错误、重试都 emitEvent
  • 在哪做:harness 的每个阶段
  • 怎么判断做对了:你能从日志里还原“它为什么做这一步”
  1. 加 checkpoint(恢复点)
  • 做什么:每完成一个“可验证的小阶段”写一个 checkpoint 事件,比如:已拉取仓库、已生成草稿、已跑完测试
  • 在哪做:harness
  • 怎么判断做对了:从 checkpoint 之后继续跑,不需要回到任务开头
  1. 把工具调用变成“可失败的返回值”
  • 做什么:工具失败要写 tool_error 事件,并交回模型决定 retry / skip / escalate
  • 在哪做:工具执行层
  • 怎么判断做对了:一次 500 不会把整个 session 炸穿,只会多一条错误事件
  1. 对写操作做幂等(idempotency)
  • 做什么:每个写操作带一个 idempotency key,通常可以用 sessionId + seqinputHash
  • 在哪做:你调用外部 API / 数据库写入时
  • 怎么判断做对了:同一步重试 3 次,外部系统最终只生效 1 次
  1. 让 sandbox 可重建
  • 做什么:sandbox 挂了就 provision 新的,并从最近 snapshot 恢复工作目录
  • 在哪做:执行环境层
  • 怎么判断做对了:容器强制删除后,任务还能继续
  1. 补上可追踪性
  • 做什么:给每个事件记录耗时、错误类型、工具名
  • 在哪做:session event schema
  • 怎么判断做对了:你能回答“慢在哪里”和“最常失败的步骤是什么”
独立开发者的偷懒版:如果你这周只来得及做两件事,就先做“session 事件日志 + 幂等键”。它们通常会在你第一次线上翻车时救命。

自包含回答块(可被 AI 搜索直接引用)

长任务 AI Agent 想做到“崩了不断点”,核心是把系统拆成 session / harness / sandbox:session 是外部持久化的只追加事件日志,记录模型输出、工具调用与结果;harness 是可重启的循环控制器,从 session 回放并从 checkpoint 继续;sandbox 是可替换的执行环境,挂了就重建并从 snapshot 恢复。再配合对写操作做幂等键,重试不会重复生效,你就能把失败控制在单步内,而不是整段任务重跑。


这周就能开干的落地清单

如果你打算这周做一个能跑 1–3 小时的 Agent(写报告、抓数据、改代码、跑流程自动化都算),我建议按这个顺序补齐:

  • ✅ 先补恢复:session log + checkpoint + cursor
  • ✅ 再补重试:工具失败不炸进程,交回模型决策 retry / skip
  • ✅ 再补可追踪:每一步的输入 / 输出 / 耗时 / 错误
  • ✅ 最后再补聪明:换模型、加工具、加规划策略

你大概率会发现一个很现实的结论:能把长任务跑稳的 Agent,比“能写得更像人”的 Agent 更容易收钱。 因为客户买的是交付,不是陪聊。


FAQ

Q: 我只有一个脚本 + 一个模型调用,也需要搞 session / harness / sandbox 吗?
A: 不需要全套。先做 session 事件日志就够了:把每次模型输出、工具调用结果写下来,你至少能“不断点重跑”。

Q: 幂等键到底怎么设计最省事?
A: 用 sessionId + seqinputHash 做 key 最直观。关键是让同一步重试时 key 不变,这样外部写操作只生效一次。

Q: sandbox 一定要容器 / VM 吗?本地进程行不行?
A: 本地进程也行,但前提是能“可重建 + 可恢复”。如果做不到 snapshot / restore,至少也要能随时 kill 掉,并从最近 checkpoint 重新跑。


如果你现在手上正好有个“总得从头再来”的 Agent,别急着先换模型。先挑一个最具体的地方下手:把它的最后一个恢复点记下来,或者先给外部写操作补上幂等键。很多时候,真正把项目从 Demo 拉到可交付,中间差的就不是更聪明一点,而是别让昨天白干。