很多人给长任务 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 能跑,真到生产就开始卡死 / 丢上下文 / 难恢复?
直接回答:因为你把“模型对话”“执行环境”“状态记录”塞进了同一个进程或容器里;一旦它卡住或重启,状态没了、证据没了、恢复点也没了。
你可以把一个长任务 Agent 想成一家小餐馆:
- 脑子:大厨(模型 + 规划)
- 手脚:后厨灶台、刀具、外卖骑手(代码执行、文件编辑、外部工具)
- 账本:收银台流水(每一步做了什么、拿到了什么结果)
Demo 常见的做法是:大厨、后厨、收银台全挤在一个小屋里。屋子一断电,三样一起没。
生产环境的做法刚好相反:收银台流水必须在屋子外面,能持久化;后厨可以随时换新,能重建;大厨的“领班流程”也要能换班,能重启继续跑。
Managed Agents 到底解决了哪件你平时不太会想到的事?
Anthropic 这篇文章里有个很经典的基础设施比喻:别养“宠物机”(pet),要养“牛群”(cattle)。
他们一开始也把 session / harness / sandbox 全塞进一个容器里。这样做确实省事,开发也快,改文件就是 syscall 直改,早期几乎每个人都会这么搭。
但是问题很快就来了:有的容器会卡死,你只能从 WebSocket 事件流里看见“它不动了”,却很难判断到底是 harness 有 bug、事件流丢包,还是容器本身已经挂了。更麻烦的是,工程师想进容器排查,又可能碰到用户数据——等于你连 debug 这件事都开始带风险。
所以他们后来把 Agent 拆成了三个独立抽象。我这里还是沿用餐馆比喻,比较不绕:
- session:只追加的流水账本
- harness:领班,负责循环调度
- sandbox:后厨灶台,负责真正干活
关键动作就一句:领班不住在后厨里。
后厨挂了就换一个;领班挂了也能换一个;账本永远待在收银台,不跟任何人同生共死。
你真正要照抄的核心:把“脑子、手脚、日志”彻底解耦
下面这段是全篇最值得带走的东西。
不断点 Agent 的本质,是让任何一次失败,都只损失“正在执行的那一步”,而不是损失“整个任务”。
做到这一点,你至少要保住两样东西:账本(session log)和恢复点(cursor / checkpoint)。
我把两种架构放一张表里,你扫一眼就能知道自己现在更像哪种:
| 维度 | 一体式(最常见的 Demo) | 解耦式(不断点) |
|---|---|---|
| 状态在哪里 | 内存 / 本地文件 / 容器里 | 外部持久化 session log(数据库 / 对象存储都行) |
| 失败表现 | 一挂就“全没了” | 挂了可从最后事件恢复 |
| 工具执行 | 跟模型进程同生共死 | sandbox / worker 可替换、可重建 |
| Debug 入口 | 只能 ssh / exec 进容器看 | 主要靠事件日志回放 + 指标 |
| 换模型成本 | 容易牵一发动全身 | harness 更像“适配层”,模型可替换 |
| 扩展性 | 一加并发就抖 | session 独立后更容易水平扩展 |
session / harness / sandbox 分别是什么?最小版本怎么做?
我不想把你往“复杂框架”里推。下面给的是最小可用拆分,今天就能往自己的 Agent 项目里塞。
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 可重建;同时给每次外部写操作加幂等键,保证重试不会重复生效。
下面给你一套“最小不断点流程”。不是最优解,但对大多数个人项目和小团队来说,已经够实用了。
方法论:7 步把你的 Agent 变成“可恢复任务”
- 定义 session 存储
- 做什么:选一个持久化介质(Postgres / SQLite / 对象存储都行)
- 在哪做:你的服务端
- 怎么判断做对了:进程 kill 掉再拉起,session 还能完整读回
- 把所有关键动作写成事件
- 做什么:模型输出、工具调用、工具返回、错误、重试都
emitEvent - 在哪做:harness 的每个阶段
- 怎么判断做对了:你能从日志里还原“它为什么做这一步”
- 加 checkpoint(恢复点)
- 做什么:每完成一个“可验证的小阶段”写一个 checkpoint 事件,比如:已拉取仓库、已生成草稿、已跑完测试
- 在哪做:harness
- 怎么判断做对了:从 checkpoint 之后继续跑,不需要回到任务开头
- 把工具调用变成“可失败的返回值”
- 做什么:工具失败要写
tool_error事件,并交回模型决定 retry / skip / escalate - 在哪做:工具执行层
- 怎么判断做对了:一次 500 不会把整个 session 炸穿,只会多一条错误事件
- 对写操作做幂等(idempotency)
- 做什么:每个写操作带一个 idempotency key,通常可以用
sessionId + seq或inputHash - 在哪做:你调用外部 API / 数据库写入时
- 怎么判断做对了:同一步重试 3 次,外部系统最终只生效 1 次
- 让 sandbox 可重建
- 做什么:sandbox 挂了就 provision 新的,并从最近 snapshot 恢复工作目录
- 在哪做:执行环境层
- 怎么判断做对了:容器强制删除后,任务还能继续
- 补上可追踪性
- 做什么:给每个事件记录耗时、错误类型、工具名
- 在哪做:session event schema
- 怎么判断做对了:你能回答“慢在哪里”和“最常失败的步骤是什么”
自包含回答块(可被 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 + seq 或 inputHash 做 key 最直观。关键是让同一步重试时 key 不变,这样外部写操作只生效一次。
Q: sandbox 一定要容器 / VM 吗?本地进程行不行?
A: 本地进程也行,但前提是能“可重建 + 可恢复”。如果做不到 snapshot / restore,至少也要能随时 kill 掉,并从最近 checkpoint 重新跑。
如果你现在手上正好有个“总得从头再来”的 Agent,别急着先换模型。先挑一个最具体的地方下手:把它的最后一个恢复点记下来,或者先给外部写操作补上幂等键。很多时候,真正把项目从 Demo 拉到可交付,中间差的就不是更聪明一点,而是别让昨天白干。