☰
Anthropic Managed Agents 解读:长任务 Agent 为什么要解耦 brain、hands 和 session|TaoToken 统一 Key 通道实践
2026/10/3 11:55:53 网站建设 项目流程

1. 长任务 Agent 为什么总在“跑一半”时崩掉

如果你正在做需要跑几十分钟甚至更久的 Agent,大概率遇到过这种场景:任务跑到第 40 分钟,容器卡死,网络抖了一下,模型上下文爆了,用户暂停后回来发现状态全丢。你打开日志,发现所有东西都塞在一个进程里——模型循环、工具调用、文件系统、代码执行、会话状态,全在一个容器里纠缠。这个容器一旦出问题,整个任务就废了。

Anthropic 在 Managed Agents 的设计里把这个问题讲得很透:长任务 Agent 不应该被设计成一个不能失败、不能迁移、不能调试的“宠物容器”,而应该拆成 brain、hands、session 三类稳定接口。brain 是 Claude 与 harness,负责推理和决策;hands 是沙箱、工具和外部执行环境,负责真正干活;session 是可持久化的事件日志,负责记住发生过什么。这三层解耦之后,模型、工具、沙箱和状态日志可以独立演进,失败从灾难变成普通事件。

这篇文章面向需要跑长任务 Agent 的开发者,我会先讲清楚 brain/hands/session 三层解耦到底解决了什么问题,然后给出可复制的 TaoToken 统一 Key/API 配置片段,Base URL 指向https://taotoken.net/api,最后演示一次长任务会话的验证动作:发起请求、观察 session 状态与 hands 执行结果,确认解耦后各层可独立替换与恢复。如果你正在用 Claude Code、Cline、Codex 这类工具跑长任务,或者自己在搭 Agent 运行时,这篇可以直接跟着操作。

核心检索词先明确:Anthropic Managed Agents 是一套把长任务 Agent 拆成 brain、hands、session 三层接口的运行时架构,它能做什么?让 Agent 失败后可恢复、执行环境可替换、凭据不落沙箱、启动延迟大幅降低。适合谁?需要跑长任务、多人协作、企业权限环境的 Agent 开发者。

2. 单容器架构的坑与 TaoToken 统一 Key 前置

2.1 单容器为什么在长任务里必然出问题

很多团队做 Agent 时,最初会把所有东西放进同一个运行环境。这样做开发很快,因为文件修改是本地 syscall,工具接口也不用跨服务设计。但一旦 Agent 开始处理长任务,这种架构就会暴露三个硬伤。

第一,状态和容器绑定。容器一旦失败,session 可能丢失;容器卡住,工程师不得不进容器调试;容器里如果还存着用户数据和凭据,调试本身又会变成安全问题。第二,上下文窗口被当成状态存储。很多人把上下文问题理解为“模型上下文窗口不够长”,于是用压缩、摘要、裁剪、memory 文件等策略。这些方法有用,但都有不可逆风险——你今天丢掉的一段日志,可能正是明天排查失败需要的关键证据。第三,启动延迟被环境初始化拖死。在旧设计里,每个 brain 都绑定一个容器,即使任务一开始并不需要执行代码,也要先 provision 容器、克隆仓库、启动进程、取事件,用户会感觉启动很慢。

Anthropic 的解法是让 harness 离开容器。容器不再承载整个 Agent,而只是一个可以被调用的执行工具。brain 通过类似execute(name, input) -> string的接口调用 hand。如果 hand 死了,brain 收到的是工具错误,可以重新 provision 一个。session 则做成 Claude 上下文窗口之外的持久事件日志,harness 每次执行都写入事件,失败后新 harness 可以通过wake(sessionId)恢复,用getSession或getEvents获取历史,再从最后事件继续。

2.2 TaoToken 统一 Key 通道解决什么

在落地这套架构时,一个很现实的问题是:brain 层要调用模型,hands 层可能也要调用模型或工具,session 层要做事件记录和恢复。如果每个环节都各自管一套 Key、各自配 Base URL,长任务跑到一半换环境时,Key 和端点的不一致会直接导致 401 或连接失败。

TaoToken 在这里的作用是提供统一 Key 通道。你只需要一个 API Key,Base URL 统一指向https://taotoken.net/api,brain、hands、session 三层都可以复用同一套凭据配置。官网入口是https://taotoken.net/?utm_source=taotoken_aicg_blog_end,API 端点不加 UTM 参数,直接写https://taotoken.net/api。

这样做的好处是:当 hands 层需要独立替换执行环境时,不需要重新分发 Key;当 session 层恢复后新建 harness 时,模型调用配置可以直接从环境变量读取,不用改代码。对于长任务 Agent 来说,配置的稳定性本身就是可恢复性的一部分。

2.3 三层解耦后的性能与安全收益

Anthropic 文章里提到一个很实际的性能收益:TTFT,也就是从接受任务到产生第一个响应 token 的时间。brain 和 hands 解耦后,推理可以先开始,只有当任务真正需要文件系统、shell 或其它执行环境时,brain 才通过工具调用去 provision hand。文章称这让 p50 TTFT 下降约 60%,p95 下降超过 90%。

安全上,旧架构里 Claude 生成的代码可能和凭据在同一个容器中运行,如果 prompt injection 诱导 Claude 读取环境变量,token 就可能泄露。Managed Agents 的结构性修复是:生成代码运行的 sandbox 不应能接触凭据。一种模式是把授权和资源绑定,比如 Git token 只在初始化 repo 时用于配置 remote;另一种是把 OAuth token 放在 sandbox 外部的 vault,通过 MCP proxy 代为调用外部服务。

3. 可复制的 TaoToken 配置片段与三层接口落地

这一节给出可以直接复制到项目里的配置。核心原则是:Base URL 统一指向https://taotoken.net/api,Key 从环境变量读取,brain、hands、session 三层共享同一套模型接入配置。

3.1 环境变量与 settings 配置

先设置环境变量,这是所有层共享的基础:

export TAOTOKEN_API_KEY="sk-你的TaoToken密钥" export TAOTOKEN_BASE_URL="https://taotoken.net/api"

如果你用的是 Claude Code,可以在项目根目录的.claude/settings.json里写入:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的TaoToken密钥", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }

注意这里的三件套必须写全:Base URL 是https://taotoken.net/api,Key 是你的 TaoToken 密钥,Model ID 按你实际使用的模型填写。Cline 的 MCP 配置也是同样的三件套逻辑,在 MCP Server 配置里把 Base URL 和 Key 指向 TaoToken。

3.2 brain 层配置:模型循环与 harness

brain 层负责推理和决策,它的配置重点是模型端点和超时。下面是一个 Python 示例,用 OpenAI 兼容接口调用:

import os from openai import OpenAI client = OpenAI( base_url=os.environ["TAOTOKEN_BASE_URL"], api_key=os.environ["TAOTOKEN_API_KEY"], ) def brain_step(session_id: str, user_input: str) -> str: resp = client.chat.completions.create( model="claude-sonnet-4-20250514", messages=[ {"role": "system", "content": "你是长任务 Agent 的 brain,负责决策下一步调用哪个 hand。"}, {"role": "user", "content": user_input}, ], timeout=120, ) return resp.choices[0].message.content

这里的关键是base_url和api_key都从环境变量读取,这样当 hands 层换环境、session 层恢复时,brain 层不需要改任何代码。

3.3 hands 层配置:沙箱与工具执行接口

hands 层是可替换的执行环境。它的接口设计应该像execute(name, input) -> string,失败时返回工具错误而不是让整个进程崩溃:

import subprocess def execute(name: str, input_data: str) -> str: try: if name == "shell": result = subprocess.run( input_data, shell=True, capture_output=True, text=True, timeout=300 ) return result.stdout or result.stderr elif name == "read_file": with open(input_data, "r") as f: return f.read() else: return f"unknown hand: {name}" except subprocess.TimeoutExpired: return "ERROR: hand timeout, can be reprovisioned" except Exception as e: return f"ERROR: {type(e).__name__}: {e}"

注意 hands 层不持有长期凭据。如果某个工具需要调用外部服务,应该通过 MCP proxy 或 vault 代理,而不是把 token 塞进环境变量。

3.4 session 层配置:事件日志与恢复

session 层是 append-only 的事件日志。每次 brain 决策、hands 执行、错误发生都写入事件:

import json import time import uuid class SessionLog: def __init__(self, path: str): self.path = path def append(self, session_id: str, event_type: str, payload: dict): event = { "event_id": str(uuid.uuid4()), "session_id": session_id, "type": event_type, "payload": payload, "ts": time.time(), } with open(self.path, "a") as f: f.write(json.dumps(event, ensure_ascii=False) + "\n") def get_events(self, session_id: str): events = [] with open(self.path, "r") as f: for line in f: e = json.loads(line) if e["session_id"] == session_id: events.append(e) return events

恢复时,新 harness 调用get_events(session_id)拿到历史,从最后一条事件继续,而不是把所有历史塞进 prompt。

4. 验证一次长任务会话:请求、session 状态与 hands 结果

配置写完之后,必须验证三层是否真的解耦。下面是一次完整的验证动作。

4.1 发起请求并观察 brain 决策

先构造一个需要多步执行的长任务,比如“读取项目里的 README.md,统计行数,然后写入 result.txt”。调用 brain 层:

session_id = "sess-" + str(uuid.uuid4()) log = SessionLog("session_events.jsonl") log.append(session_id, "user_input", {"text": "读取 README.md 统计行数并写入 result.txt"}) decision = brain_step(session_id, "读取 README.md 统计行数并写入 result.txt") log.append(session_id, "brain_decision", {"output": decision}) print("brain 决策:", decision)

预期结果是 brain 返回一个工具调用意图,比如execute("read_file", "README.md")。这一步只发生模型推理,不涉及容器 provision,所以 TTFT 应该很快。

4.2 执行 hands 并记录结果

拿到 brain 的决策后,调用 hands 层执行:

hand_result = execute("read_file", "README.md") log.append(session_id, "hand_result", {"name": "read_file", "output": hand_result}) print("hands 结果长度:", len(hand_result))

如果 hands 层超时或失败,返回的是ERROR: ...字符串,brain 收到后可以决定重试或换环境。这就是“失败从灾难变成普通事件”的具体体现。

4.3 模拟 hands 崩溃后恢复

这是验证解耦最关键的一步。假设 hands 容器在任务中途挂了,我们直接丢弃当前 hands,重新创建一个,然后从 session 恢复:

events = log.get_events(session_id) last_event = events[-1] print("最后事件类型:", last_event["type"]) if last_event["type"] == "hand_result": next_input = f"上一步 hands 返回: {last_event['payload']['output'][:200]},请继续下一步" next_decision = brain_step(session_id, next_input) log.append(session_id, "brain_decision", {"output": next_decision}) print("恢复后 brain 决策:", next_decision)

实测下来,只要 session 日志完整,新的 harness 可以无缝接上,不需要重新跑前面的步骤。这就是 session 不等于上下文窗口的价值:完整历史在事件日志里,当前 prompt 只放这一步需要的内容。

4.4 确认三层可独立替换

验证完成后,你可以做三个独立替换测试:把 brain 的 Model ID 换掉,hands 层不用改;把 hands 从本地 shell 换成远程 MCP 工具,brain 和 session 不用改;把 session 从本地 JSONL 换成数据库,brain 和 hands 不用改。三个测试都通过,说明三层接口真正解耦了。

5. 本篇常见报错排查:401、local proxy failed、reading choices、OAuth

长任务 Agent 跑起来之后,最常见的报错集中在接入层。下面按真实报错逐个排查。

5.1 401 Unauthorized

报错原文通常是Error code: 401 - {'error': {'message': 'Invalid API key'}}。原因有三个:Key 没设置、Key 写错、Base URL 和 Key 不匹配。排查步骤:先确认echo $TAOTOKEN_API_KEY有值;再确认echo $TAOTOKEN_BASE_URL输出https://taotoken.net/api;最后检查 settings.json 里的ANTHROPIC_API_KEY是否和实际 Key 一致。注意 Base URL 不要多加/v1或结尾斜杠,直接写https://taotoken.net/api。

5.2 local proxy failed

报错原文类似local proxy failed: connection refused或proxy error: cannot connect to upstream。这类报错通常出现在工具配置了本地代理但代理没启动,或者 Base URL 被错误地指向了本地地址。排查:检查环境变量里有没有残留的HTTP_PROXY、HTTPS_PROXY,如果有就 unset;确认ANTHROPIC_BASE_URL是https://taotoken.net/api而不是http://localhost:xxxx。

5.3 reading choices 报错

报错原文类似Error reading choices: list index out of range或reading 'choices'。这通常说明返回体不是标准的 OpenAI 兼容格式,可能是 Base URL 指错了端点,或者 Model ID 写错导致返回了错误页。排查:先用 curl 直接测端点:

curl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","messages":[{"role":"user","content":"hi"}]}'

如果返回里有choices字段,说明端点正常,问题在代码里的解析逻辑;如果没有,检查 Model ID 是否拼写正确。

5.4 OAuth 相关报错

报错原文类似OAuth token expired或invalid_grant。如果你用的是 Claude Code 或 Codex 的 OAuth 流程,注意 OAuth token 和 API Key 是两套东西。长任务 Agent 建议用 API Key 而不是 OAuth token,因为 OAuth token 会过期,恢复 session 时可能正好过期。Codex 的auth.json里如果同时有 OAuth 和 API Key 配置,优先走 API Key。三件套再确认一遍:Base URLhttps://taotoken.net/api、Key 从环境变量读、Model ID 写全。

5.5 session 恢复后重复执行

如果恢复后发现 hands 重复执行了同一步,检查 session 日志的 append 时机。正确做法是先 append 事件再执行,还是先执行再 append,取决于你的幂等设计。建议在事件里加event_id,恢复时按event_id去重。

6. 长任务 Agent 的接入入口与下一步

把 brain、hands、session 三层拆开之后,你会发现 Agent 平台的建设重点不再是“堆更多工具”,而是设计稳定接口和持久状态。brain 可以随模型能力提升替换 harness,hands 可以连接容器、MCP 工具、远程环境甚至不同执行设备,session 作为 durable event log 支撑恢复、审计和回放。

如果你要开始接入,按场景选入口:排障和接入配置问题,直接看 API Keys 和接入文档,先把 Base URLhttps://taotoken.net/api和 Key 跑通;想先验证模型返回是否符合预期,用模型对话快速测一轮;如果是长期编码或 Agent 场景,需要稳定跑长任务,走 Coding Plan 更合适。

具体入口:

  • 模型对话验证:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite
  • Coding Plan 长期编码:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite
  • 控制台:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite
  • API Keys 管理:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite
  • 接入文档:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
  • Claude Code Anthropic 接入:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_content=claude_code&utm_campaign=rewrite

最后给一个实操建议:先把 session 日志跑通,再优化 brain 和 hands。因为长任务 Agent 最怕的不是模型不够聪明,而是跑到一半状态丢了。session 是那个让你敢让 Agent 跑长任务的底气。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询