1. Managed Agents 会话卡死的现场:WebSocket 事件流里只有猜,没有答案
Managed Agents 会话卡死,最怕的是 WebSocket 事件流全是表象。TaoToken 的做法:到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 拿 Key,把 Claude Code 的 Base URL 指到 https://taotoken.net/api(不要加 /v1),再回来查 session log。Anthropic 工程博客在介绍这套架构时承认得很直接:他们最初把 session、harness、sandbox 全塞进同一个容器。文件编辑直接走系统调用,不用设计服务边界,省了很多事;代价是容器变成了一只"宠物"。宠物是有名字、不能丢、要手动救治的个体;容器一失败,会话就没了;容器无响应,所有排查都得靠 WebSocket 事件流。可事件流有个致命问题:harness 里的一个 bug、网络里的一次丢包、容器的一次离线,三种故障的表现一模一样——会话不再产生新事件。想真正定位,得进容器开 shell,但容器里还存着用户数据,等于没有调试能力。
原文里最值得反复读的是这句话:harness 会编码关于"Claude 自己做不到什么"的假设,而这些假设会随模型变强而过时。排障也一样——你总把"模型通道可能出错"这个假设背在身上,直到某次会话卡死时把锅甩给 harness。TaoToken 在这里只做一件事:把 Claude Code 的模型通道换成统一入口,让排查时"调用模型"本身不再背锅,卡死原因才能真正落到容器或事件流上。这就是原文 decoupling the brain from the hands 的本地简化版。
1.1 三种故障,一种表象
耦合架构最尴尬的地方就在这里:没有服务边界,就没有故障边界。WebSocket 事件流只能告诉你"流停了",不能告诉你"为什么停"。pets-vs-cattle 的比喻点破了本质:牲畜可以互相替换,死一头补一头;宠物死了就是灾难。你养的容器是宠物还是牲畜,直接决定了会话卡死时你是能快速换新,还是要通宵进 shell 手工救治。
1.2 本地复现时,模型通道是最大的干扰项
把同样的场景搬到本地 Claude Code,真正的干扰项往往不是容器,而是模型通道。多把 Key 来回切换、Base URL 末尾多拼一个 /v1、token 过期,都会让 Claude Code 在调用模型的瞬间报错,界面看起来却像会话卡死。正确的做法是先排除变量:模型通道固定成一把 Key、一个 Base URL、一个明确的模型 ID,然后再去看容器和事件流。一段一段查,而不是混在一起猜。
2. 拿 Key 这一步:TaoToken 把模型通道换成统一入口
排障链条要拆成两段:前一段是模型通道,用 TaoToken 处理;后一段是容器与事件流,用 Managed Agents 的接口处理。两段之间只隔一个 Base URL,但很多人把顺序搞反了——先钻进事件流翻半天,最后发现是 Key 或地址的问题。
2.1 创建 Key,认准模型广场的 ID
打开 TaoToken,注册后进入控制台,在 API Keys 页面创建一把 Key,复制下来当作 YOUR_API_KEY 占位符填入后续配置。模型 ID 不要凭记忆写,以模型广场当时列出的 ID 为准——同一个模型在不同网关上的写法可能差一个横线或日期后缀,填错就是 404 或 model not found,排障时又会多一个干扰项。
2.2 把 settings.json 的 Base URL 指到 /api
Claude Code 通过 Anthropic 兼容协议调用模型,配置写在 ~/.claude/settings.json 的 env 块里:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "<模型 ID 以模型广场为准>" } }Base URL 一定是 https://taotoken.net/api,末尾不要加 /v1。Claude Code 的请求路径本身带版本号,你再拼一个 /v1 就变成双路径,返回 401 或 404。保存后重启 Claude Code,让环境变量真正加载。这把 Key 只放在本机配置里,不要写进待调试容器的环境变量——排障归排障,凭证隔离的底线不能破。
3. session log 不在容器里:让 Claude Code 去读 getSession/getEvents
模型通道就绪,回到 Managed Agents 设计本身。原文最核心的一条是:session 是记录所有事件的追加型日志,它既不在容器里,也不在 harness 里。harness 崩溃后,新实例用 wake(sessionId) 重启,再用 getSession(id) 取回事件日志,从最后一个事件继续跑;agent 循环里每个事件都通过 emitEvent(id, event) 写进日志,保证可恢复。这就是"大脑"和"手"分离后,会话不再依赖某个具体容器的原因。
原文举的例子是客户想把 Claude 接进自己的 VPC:耦合设计下,客户要么把网络对等过来,要么把整套 harness 搬到自己的环境里跑。解耦之后,harness 只是通过接口访问外部资源,这个假设就消失了。排障视角下同理——你不必为了读 session log 去打开一个可能还存着用户数据的容器。
3.1 用 Claude Code 把事件流拉出来看
配好通道后,Claude Code 就是读取 session log 的入口。用自然语言描述任务,让它调 getSession(id) 拉事件流,标出最后一条成功事件和第一条异常事件。模型通道稳定后,Claude Code 返回的内容只和 session log 有关,不会混入"模型调用失败"的噪声。如果事件流最后停在某次 execute 调用发出之后,说明问题在"手";如果事件根本没有写入日志,问题就在 harness 或网络这一段。
3.2 按位置切片,绕开上下文窗口
原文专门用一节讲"session 不是 Claude 的上下文窗口"。长任务一定会超出上下文长度,压缩和裁剪都是不可逆决策——你永远不知道未来哪一步需要哪几个 token。Managed Agents 的 getEvents() 允许按事件流的位置切片来读:从上次停下的地方继续,回退到某个事件前看前因,或者在某个动作前重读一遍。排障时 Claude Code 不需要把整个 session 塞进上下文,只拉关键片段就能定位,干净利落。
4. execute(name, input) → string:容器从宠物变牲畜
读完 session log,下一步判断容器状态。原文的转折点是:harness 不再住在容器里,它调用容器的方式和调用任何工具一样,execute(name, input) → string。容器从此变成可替换的牲畜,不再需要工程师进 shell 去"救治"。
4.1 容器失败就当工具调用错误
原文的处理方式值得抄:容器死了,harness 把这次失败当作一次工具调用错误返回给 Claude;Claude 决定重试时,用 provision({resources}) 按标准配方初始化一个新容器。排障时对照这个逻辑——session log 里最后一条是 execute 发出、没有返回,那多半是容器问题,直接换新容器,而不是在 WebSocket 流里继续猜。另一个细节是启动成本:耦合设计里每个会话都要预先付完整的容器启动代价,哪怕这个会话根本用不到沙箱;解耦之后容器只在工具被调用时才创建。读 session log 本身不需要容器,需要容器的是 execute 对应的那一步——这也是为什么排障时先读日志、再动容器。
4.2 多执行环境,一套接口
原文还提到 many brains, many hands——一个大脑可以连多个手,每个手都是 execute 接口,不管是容器、手机还是模拟器。这套抽象让故障粒度变小:排障时确认具体是哪一次 execute 调用失败,看那一次返回结果就够了,不用把整个容器的状态搞明白。定位粒度从"整个容器"降到"一次工具调用",这正是规模化管理的代理里 decoupling 的意义,也是排障效率提升的来源。
5. 验证与排障:回 TaoToken 控制台对账
配置保存、session 拉取成功之后,别急着关终端。先验证这次的调用真的走对了通道,再去怀疑沙箱和事件流。
5.1 模型对话先试一发
用同一把 Key 在 TaoToken 模型对话 里发一条测试消息,确认模型 ID 和 Base URL 都没问题。然后回到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 的控制台,看刚才 Claude Code 的调用有没有记上账。如果模型对话成功但 Claude Code 仍然报错,问题大概率不在模型通道,继续查 session log 和容器状态。
5.2 401 和 /v1:两个最常出现的假故障
排障时最常见的两个报错都出在模型通道配置上。一个是 ANTHROPIC_AUTH_TOKEN 没被 Claude Code 加载,它还在用旧 Key,表现是 401;另一个是 Base URL 写成了 https://taotoken.net/api/v1,Claude Code 拿这个地址再拼 /v1/messages,变成双 /v1,表现是 404。这两个错先排除,再回头看容器和事件流,顺序不能反。
6. 下次再卡死:固定一套排障顺序
6.1 从 Base URL 到 session log 的检查链
再遇到会话卡死,固定套这套动作能省掉大半的猜疑链:先确认 Claude Code 的 ANTHROPIC_BASE_URL 指向 https://taotoken.net/api,Key 有效;再让 Claude Code 读 Managed Agents 的 session log,把最后一条成功事件和第一条异常事件标出来;如果 execute 调用发出后没有返回,按 provision 的标准配方换新容器;最后回控制台核对用量记录,确认卡死发生在哪一段。
6.2 相关入口
Key 在控制台 API Keys创建;不确定套餐够不够就打开Coding Plan看余额;Claude Code 环境变量对照见接入文档。模型对话先测一发最稳妥,入口在上面 5.1。卡死的瞬间别急着翻日志,先确认通道,再读 session——把"大脑"和"手"分开,故障就藏不住。