1. 从 Claude Code 源码泄露事件说起:Agent 循环到底强在哪
Claude Code 源码泄露这件事,在开发者圈子里炸开锅的原因,不是那 51 万行代码本身有多神秘,而是它第一次把「一个真正好用的编程 Agent 是怎么搭出来的」摊在了所有人面前。很多人第一反应是 Anthropic 的模型更强,但把代码翻一遍就会发现,真正拉开差距的是工程系统:Agent Loop 的状态机设计、工具调用的并发调度、System Prompt 的动态组装、上下文的分级压缩、多 Agent 的权责隔离。这些东西跟模型能力无关,是纯粹的工程活。
我关心的角度可能跟大多数人不太一样。源码里那套 Agent 循环,本质上是一个「反复调用大模型 API + 执行工具 + 回填结果」的闭环。这个闭环要跑起来,最基础的前提是:你得有一个稳定、统一、能兼容多种模型协议的 API 通道。Claude Code 自己走的是 Anthropic 官方通道,但我们在自己的项目里复刻类似架构时,往往要同时对接 OpenAI 兼容接口、Anthropic 接口、各种国产模型接口,Key 管理一乱,Agent 循环跑到一半就 401,排查起来非常痛苦。
这篇就从这个痛点切入:先讲清楚 Claude Code 源码里 Agent 循环和工具调用的核心设计思路,再落到实操——怎么用 TaoToken 的统一 Key/API 通道,把 Base URL 配好,在兼容 OpenAI 接口的工具里完成接入和连通性验证。适合正在自己搭 Agent、或者想把现有 AI 工具接到统一通道上的开发者。读完你能拿到一套可复制的配置,以及几个真实会踩的坑。
2. Agent 循环与工具调用:源码里的工程化思路拆解
2.1 两层循环模型:QueryEngine 与 queryLoop 的分工
Claude Code 的 Agent 循环不是简单的while(true),而是拆成了两层。外层是 QueryEngine,管的是会话级的东西:多轮状态持久化、SDK 协议适配、用量统计、会话恢复。内层是 queryLoop,管的是单轮执行:调 API、执行工具、处理错误恢复。两者通过 AsyncGenerator 连接,QueryEngine 消费 queryLoop yield 出来的消息。
这个设计的好处很实在。背压控制——调用方按需消费,不会被消息洪水淹没;中断语义——generator 的.return()能级联关闭所有嵌套 generator,取消操作自然传播;流式组合——子 Agent 的runAgent()也是 AsyncGenerator,能直接嵌到父 Agent 的流里。你在自己写 Agent 的时候,如果还在用回调或者 Promise 链硬拼,遇到「用户中途取消」这种场景就会很别扭,AsyncGenerator 这套模式值得借鉴。
2.2 Tool-Use Loop:比 ReAct 更省 Token 的工作模式
源码里明确放弃了 ReAct 模式,改用 Tool-Use Loop。ReAct 是 2022 年那套 Thought-Action-Observation 三步循环,问题是每轮都要输出 Thought 文本,占上下文;还要解析模型输出区分 Thought 和 Action,容易格式错;而且它本质是为弱模型设计的,靠显式思考引导推理。
Tool-Use Loop 的哲学是信任模型的推理能力,应用层框架尽量简单。循环体里就几步:压缩上下文、流式调 API、分析返回、执行工具、更新 state 继续循环。模型直接返回两种结果——tool_use表示要调工具,end_turn表示任务完成。没有显式 Thought 步骤,因为强模型支持 Extended Thinking,推理在模型内部完成,不占应用层上下文。
// 精简后的循环骨架,理解设计意图即可 async function* queryLoop(params: QueryParams): AsyncGenerator<StreamEvent | Message, Terminal> { let state: State = { messages, toolUseContext, turnCount: 1 }; while (true) { // 1. 压缩上下文(五步从轻到重) // 2. 流式调用大模型 API for await (const event of streamAPI(params)) { yield event; } // 3. 分析返回 if (response.stopReason === 'end_turn') break; // 4. 执行工具调用(并发/串行编排) const toolResults = await executeToolCalls(toolUseMessages); // 5. 更新 state,继续循环 state = { ...state, messages: updatedMessages, turnCount: state.turnCount + 1 }; } }2.3 流式工具执行:并发与串行的智能调度
模型一次返回多个工具调用时,Claude Code 不是无脑并行,也不是全串行,而是用 StreamingToolExecutor 做分区。每收到一个tool_use块就立即开始执行,不用等流式接收完全结束。连续的并发安全工具(比如多个读文件)组成一个并行分区,内部最多 10 个并发;遇到非并发安全工具(写文件、编辑文件),结束当前分区,开新的串行分区。分区间串行,分区内并行。
默认情况下,工具没声明自己是并发安全的,就视为非安全,串行执行。这是 Fail-closed 原则——不确定就保守处理。你在设计自己的工具调用层时,这个思路可以直接抄:给每个工具打一个concurrencySafe标记,调度器按标记分区。
2.4 消息预处理管线:五步压缩的成本平衡
每次 API 调用前,消息要过一条压缩管线,从轻到重:applyToolResultBudget 限制工具结果大小;snipCompact 片段级裁剪;microCompact 微压缩,优先清理旧的高频工具输出,通过缓存编辑保住前缀缓存;contextCollapse 上下文折叠;autoCompact 全量摘要,最后手段。
AutoCompact 有明确阈值:200k 上下文的模型,剩余空间小于 13000 token 才触发。还有断路器,连续失败 3 次就停,避免浪费 API 调用。源码注释里提到曾经有 1279 个会话出现 50+ 次连续失败,每天浪费 25 万次 API 调用——这个细节说明工业级系统必须考虑异常路径的成本。
这套压缩策略的核心是「能轻则轻,逐步加码」。前三层几乎没信息损失,也不需要额外 API 开销;第四层中等损失;第五层损失最大,要调大模型生成摘要。大部分场景前三层就够了。
2.5 多 Agent 协作:工具隔离保证权责分离
Claude Code 内置 6 个专业 Agent:General Purpose、Explore、Plan、Verification、Guide、Statusline Setup。每个 Agent 有自己的disallowedTools列表。比如 Explore Agent 禁止编辑文件、写文件、嵌套调用 Agent,只能读和搜索。Plan Agent 也是只读,负责输出实现计划。Verification Agent 最独特,任务是「想方设法破坏代码」,做并发测试、边界值测试、幂等性测试,所有结论必须有实际执行的命令输出,不能只读代码猜结果。
这种设计遵循 Unix 哲学:一个工具只做一件事。探索的只管探索,规划的只管规划,验证的只管验证,改代码留给主 Agent。你在搭多 Agent 系统时,工具隔离比 Prompt 约束可靠得多——Prompt 可能被绕过,工具列表是硬边界。
3. TaoToken 统一 Key/API 通道的前置准备与配置
3.1 为什么 Agent 架构需要一个统一通道
上面那套 Agent 循环,跑起来的第一步就是调 API。如果你同时用 OpenAI 兼容接口、Anthropic 接口、国产模型接口,每个都要单独管 Key、单独配 Base URL、单独处理错误码,Agent 循环里的错误恢复逻辑会变得非常复杂。统一通道的价值在于:一个 Key、一个 Base URL、一套错误码,Agent 循环只需要处理一种协议。
TaoToken 提供的就是这样一个统一通道,兼容 OpenAI 接口规范。你可以在官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 了解整体能力,API 入口是 https://taotoken.net/api(这个地址不加 UTM 参数)。
3.2 获取 API Key 与模型 ID
先到 API Keys 管理页创建 Key:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 。创建后复制保存,Key 只显示一次。
模型 ID 需要跟你的工具匹配。如果你用的是 Claude Code 类工具,模型 ID 填 Anthropic 系列;如果用 OpenAI 兼容工具,填对应的模型 ID。具体可用模型列表在文档里查:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
3.3 可复制的配置文件片段
不同工具的配置格式不一样,下面给几个常见的。Claude Code 的 settings 文件(路径~/.claude/settings.json):
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "你的TaoToken Key", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }Cline 的 MCP 配置(路径~/.cline/mcp_settings.json或 VS Code 设置里):
{ "mcpServers": { "taotoken": { "command": "npx", "args": ["-y", "@taotoken/mcp-server"], "env": { "TAOTOKEN_BASE_URL": "https://taotoken.net/api", "TAOTOKEN_API_KEY": "你的TaoToken Key", "TAOTOKEN_MODEL": "claude-sonnet-4-20250514" } } } }Codex 的 auth.json(路径~/.codex/auth.json):
{ "base_url": "https://taotoken.net/api", "api_key": "你的TaoToken Key", "model": "claude-sonnet-4-20250514" }三件套记住:Base URL 填https://taotoken.net/api,Key 填你创建的,Model ID 填对应模型。这三个缺一不可,少一个就会报错。
3.4 环境变量方式(适合脚本和 CI)
如果你在脚本或 CI 里用,直接设环境变量:
export OPENAI_BASE_URL="https://taotoken.net/api" export OPENAI_API_KEY="你的TaoToken Key" export OPENAI_MODEL="claude-sonnet-4-20250514"注意 OpenAI 兼容工具读的是OPENAI_BASE_URL,Anthropic 系工具读的是ANTHROPIC_BASE_URL,别搞混。配完之后,Agent 循环里的 API 调用就会走统一通道。
4. 连通性验证:从 curl 到实际请求的成功结果
4.1 先用 curl 做最小验证
配置完别急着跑 Agent,先用 curl 打一发,确认通道通:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer 你的TaoToken Key" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "回复 OK 两个字母"}], "max_tokens": 10 }'成功的话返回 JSON 里choices[0].message.content会有内容。如果返回 401,说明 Key 不对或没带上;返回 404,说明 Base URL 路径不对,检查是不是漏了/v1。
4.2 Python 脚本验证
from openai import OpenAI client = OpenAI( base_url="https://taotoken.net/api/v1", api_key="你的TaoToken Key" ) resp = client.chat.completions.create( model="claude-sonnet-4-20250514", messages=[{"role": "user", "content": "用一句话说明什么是 Agent Loop"}], max_tokens=100 ) print(resp.choices[0].message.content)跑通后会打印模型返回的内容。这一步验证的是 OpenAI SDK 能不能正常走统一通道。
4.3 在 Claude Code 里验证
配好 settings.json 后,直接启动 Claude Code,输入一个简单任务,比如「读一下当前目录的 package.json,告诉我项目名」。如果 Agent 能正常调工具、返回结果,说明通道通了。你可以在模型对话页 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 先手动测一下模型响应,确认模型 ID 没写错。
4.4 验证工具调用是否正常
Agent 架构的核心是工具调用,光验证文本生成不够。发一个需要调工具的请求:
resp = client.chat.completions.create( model="claude-sonnet-4-20250514", messages=[{"role": "user", "content": "北京现在几点?"}], tools=[{ "type": "function", "function": { "name": "get_time", "description": "获取指定城市的当前时间", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"] } } }], max_tokens=200 ) print(resp.choices[0].message.tool_calls)如果返回里有tool_calls字段,说明工具调用协议正常。这一步过了,你的 Agent 循环就能正常跑 Tool-Use Loop 了。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
5.1 401 Unauthorized
最常见。原因通常是 Key 没带、Key 写错、或者 Key 被删了。检查三处:配置文件里的 Key 是不是完整复制了;环境变量有没有覆盖配置文件;请求头是不是Authorization: Bearer xxx格式。如果用的是 Claude Code,检查ANTHROPIC_AUTH_TOKEN有没有设对。
5.2 local proxy failed
这个报错通常出现在工具试图走本地代理但代理没起来。检查你的工具配置里有没有多余的 proxy 设置,把HTTP_PROXY、HTTPS_PROXY环境变量清掉再试。TaoToken 通道不需要本地代理,直连即可。
5.3 reading choices 报错
一般是响应格式不对。可能原因:Base URL 路径少了/v1,或者模型 ID 写错导致返回了错误结构。先确认 Base URL 是https://taotoken.net/api/v1(OpenAI 兼容工具)或https://taotoken.net/api(Anthropic 系工具),再确认模型 ID 在文档列表里。
5.4 OAuth 相关报错
有些工具默认走 OAuth 登录流程,如果你配了 API Key 但工具还在尝试 OAuth,就会冲突。检查工具设置里有没有「使用 API Key」的选项,切过去。Claude Code 的话,确认没有残留的 OAuth token 文件。
5.5 模型 ID 不匹配
报错信息里如果有model not found,说明模型 ID 写错了。到文档页 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 查可用模型列表,复制准确的 ID。注意大小写和版本号后缀。
5.6 排查顺序建议
遇到报错按这个顺序查:先 curl 验证通道通不通;再检查配置文件三件套(Base URL、Key、Model ID);再看工具日志里的完整请求;最后对比文档里的示例配置。大部分问题出在三件套上,尤其是 Base URL 的/v1后缀。
6. 把统一通道接进你的 Agent 工作流
配通之后,你的 Agent 循环就有了稳定的 API 底座。回到 Claude Code 源码那套设计,你会发现它的工程化思路可以拆成两层:上层是 Agent 逻辑(循环、工具调度、上下文压缩、多 Agent 隔离),下层是 API 通道(统一协议、统一 Key、统一错误处理)。上层逻辑再精巧,下层通道不稳,整个系统就跑不起来。
如果你在长期做编码类 Agent,或者要跑多轮复杂任务,可以考虑 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。它适合需要持续调用、多会话并行的场景。Claude Code 相关的接入细节在 https://taotoken.net/doc/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude_code&utm_campaign=rewrite 有专门说明。
最后给一个实操建议:把 Base URL、Key、Model ID 三件套写进一个.env文件,所有工具都从环境变量读,别硬编码在配置文件里。这样换 Key 或者切模型的时候,改一处就行。Agent 循环里的错误恢复逻辑,也可以针对统一通道的错误码做统一处理,不用为每个模型供应商写一套。