1. 一次任务从回车到返回,Claude Code 到底在背后做了什么
你已经在 Claude Code 里配好了 GLM,敲下一句“帮我重构这个 Service”,然后看着终端里光标转圈、文件被读、代码被改。整个过程看起来像“模型在写代码”,但真实情况是:Claude Code 把 GLM 当成一个只会说下一步该干嘛的决策器,真正干活的是它自己的 Agent Runtime。
这篇就把这条链路拆开:请求怎么组装、经过统一 Key/API 通道怎么转发、响应怎么回填到状态机、循环什么时候收敛。面向的是已经配好 GLM、想看清每一跳的开发者。我会给出可复制的配置片段、逐步验证动作,以及怎么对照日志确认每一跳都走通了。
先给一个脑内结构,后面所有细节都挂在这上面:
你(输入任务) ↓ Claude Code UI(CLI / IDE 插件) ↓ Agent Runtime(调度器 + 状态机 + 工具执行器) ↓ Model Adapter(OpenAI-compatible 适配层) ↓ HTTP(S) 请求 → 统一 Key/API 通道 → GLM 接口 ↓ 响应回填 → 状态更新 → 下一轮循环关键认知只有一句:Claude Code 不知道自己在用 GLM。它只认“一个兼容 OpenAI 风格、支持 function calling 的对话接口”。你配的base_url、api_key、model三件套,最终都被适配层翻译成标准 HTTP 请求。理解这一点,后面所有“为什么报错”“为什么模型不调工具”都能对上号。
单次任务里,模型调用通常不是 1 次,而是 5 到 30 次。每一次调用 GLM 只回答一个问题:“下一步做什么?”——是读文件、是改代码、还是给出最终答复。任务完成与否,不由 GLM 说了算,而由 Claude Code 根据文件系统、diff、工具返回结果来判断。这就是为什么换模型后成功率差异,主要落在tool-calling 稳定性上,而不是“模型聪不聪明”。
下面按真实执行顺序,从配置阶段讲到循环收敛,再讲怎么用统一通道验证每一跳。
2. 配置阶段:Base URL、Key、Model ID 三件套怎么落到请求上
配置只发生一次,但它决定了后面每一次请求长什么样。Claude Code 配置 GLM 时,你实际在做三件事:告诉它模型是谁、去哪请求、怎么鉴权。
第一件,模型标识。Claude Code 内部没有glm这个分支,它统一走 OpenAI-compatible adapter。所以你写的model字段会被原样塞进请求体的model参数:
{ "provider": "openai-compatible", "model": "glm-4.7" }第二件,请求地址。你填的base_url会被拼成具体的 endpoint,通常是POST /chat/completions,新协议下也可能是POST /responses:
{ "base_url": "https://taotoken.net/api" }第三件,鉴权。api_key最终变成请求头里的Authorization: Bearer xxxxx。
把这三件套写进 Claude Code 的 settings 文件,路径和字段名要对齐。以常见的~/.claude/settings.json为例,可复制片段如下:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "sk-你的统一Key", "ANTHROPIC_MODEL": "glm-4.7" } }如果你用的是 Codex 风格的auth.json,三件套同样要写全,缺一个都会在请求阶段暴露:
{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的统一Key", "model": "glm-4.7" }这里有个容易踩的坑:base_url末尾不要自己再拼/chat/completions。适配层会负责拼接,你多写一段就会变成/api/chat/completions/chat/completions,直接 404。统一 Key 在https://taotoken.net/api-keys获取,拿到后先别急着跑任务,用一条最小请求验证通道。
配置完成后,Claude Code 内部只是把 Model Adapter 准备好了,还没有任何任务执行。真正的交互从你按下回车那一刻开始。
3. 可复制配置:把统一 Key 通道接进 Claude Code 并验证连通
这一节给你能直接抄的配置和验证命令。目标是把统一 Key/API 通道接进 Claude Code,并且用一条 curl 确认通道本身是通的,再去跑任务。
先确认你的 settings 文件位置。CLI 版通常在~/.claude/settings.json,IDE 插件版在项目根目录的.claude/settings.json。写入下面这段,注意把 Key 换成你自己的:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "sk-你的统一Key", "ANTHROPIC_MODEL": "glm-4.7" } }如果你用的是 Cline MCP 或 CC Switch 这类工具,配置项名称可能不同,但三件套逻辑一致:Base URL 填https://taotoken.net/api,Key 填统一 Key,Model ID 填glm-4.7。CC Switch 里对应的是 provider 的baseUrl、apiKey、model三个字段,别只填两个。
配置写完后,先用 curl 打一条最小请求,确认通道和模型都活着:
curl -s https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer sk-你的统一Key" \ -H "Content-Type: application/json" \ -d '{ "model": "glm-4.7", "messages": [ {"role": "user", "content": "只回复两个字:通了"} ], "temperature": 0.2 }'正常返回里会有choices[0].message.content,内容就是“通了”。如果这一步就失败,先别去 Claude Code 里排查,问题在通道或 Key 上。常见返回:
| 返回现象 | 含义 | 处理 |
|---|---|---|
| 401 Unauthorized | Key 无效或没带上 | 检查Authorization头,确认 Key 没空格 |
| 404 Not Found | 路径拼错 | 确认 base_url 是https://taotoken.net/api,不要重复拼 endpoint |
| 400 model not found | 模型名写错 | 换成通道支持的 GLM 模型 ID |
| 超时无响应 | 网络或通道问题 | 换网络环境重试,确认不是本地代理拦截 |
curl 通了之后,再回到 Claude Code 跑一个只读任务,比如“列出当前目录结构并解释每个文件夹的作用”。这个任务不需要改文件,能最快看出请求是否正常发出、响应是否正常回填。跑的时候打开 verbose 日志,观察每一跳。
4. 验证请求:从回车到响应回填,逐跳对照日志
任务真正开始时,Claude Code 不会把你那句话直接发给 GLM,而是先做结构化封装。内部状态大概长这样:
AgentState { goal: "重构 PHP Service", history: [], workspace_snapshot: {...}, rules: [...], tools: [...] }这一步完全没有调用大模型。接下来才构造第一次 Prompt,它由六部分组成,顺序很重要:System Prompt(Agent 灵魂,定义它是 coding agent、能调哪些工具、输出格式)、Developer Prompt(Claude Code 内置的拆任务规则)、Workspace Context(目录结构、已读文件、Git 状态)、Tool Schema(函数调用定义)、Conversation History(首次为空)、User Message(你输入的那句话)。
拼完之后,才发出真正的 HTTP 请求。抽象形态如下:
POST /chat/completions Host: taotoken.net Authorization: Bearer sk-你的统一Key Content-Type: application/json { "model": "glm-4.7", "messages": [ {"role": "system", "content": "你是一个 coding agent..."}, {"role": "user", "content": "帮我重构这个 PHP Service"} ], "temperature": 0.2, "tools": [...], "tool_choice": "auto" }GLM 返回的通常不是“答案”,而是三种意图之一。第一种是纯文本思考加计划,content里写着“我需要先读取 Service 文件”。第二种是工具调用,最常见:
{ "tool_calls": [ { "name": "read_file", "arguments": {"path": "app/Service/UserService.php"} } ] }第三种是多工具加隐式 Chain-of-Thought,GLM 内部多步推理,但 Claude Code 只吃结果,不吃思考过程。
收到tool_call后,Claude Code 立刻执行工具,把结果写回状态,追加一条tool_resultmessage:
{ "role": "tool", "name": "read_file", "content": "class UserService {...}" }然后进入循环:
while (!taskDone) { response = callModel(state) if (response.tool_call) { runTool() updateState() } else { applyChangesOrAskUser() } }对照日志时,你要盯的是每一轮请求的messages数组是不是在变长、tool_calls是不是被正确解析、tool_result是不是被回填。如果某一轮之后messages不再增长,说明循环卡住了,通常是工具执行失败或响应结构不符合预期。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
跑 GLM 接入时,报错基本集中在几个固定位置。下面按真实报错对照排查。
401 Unauthorized:Key 没带上或带错。检查 settings 里ANTHROPIC_AUTH_TOKEN是否等于统一 Key,注意别把Bearer前缀重复写进去。有些工具要求 Key 字段不带前缀,有些要求带,按工具文档来。用第 3 节的 curl 先验证 Key 本身有效。
local proxy failed / connection refused:本地代理或端口冲突。Claude Code 某些版本会起本地转发端口,如果端口被占用或本地网络策略拦截,就会报这个。先关掉其他占用端口的进程,确认base_url指向的是https://taotoken.net/api而不是localhost。如果你本地配了系统代理,确认它没有拦截这个域名。
reading choices 报错 / cannot read property 'choices':响应结构不符合 OpenAI 风格。GLM 正常返回里一定有choices数组,如果适配层拿不到,通常是通道返回了错误结构,或者模型名不被支持导致返回了错误体。先用 curl 看原始返回,确认有choices[0].message。如果 curl 正常但 Claude Code 报这个,检查是不是 settings 里ANTHROPIC_MODEL写成了通道不支持的模型 ID。
OAuth 相关报错 / authentication failed:Claude Code 默认走 Anthropic 官方 OAuth 流程,你换成第三方通道后,它可能还在尝试 OAuth。解决办法是在 settings 里显式设置ANTHROPIC_AUTH_TOKEN和ANTHROPIC_BASE_URL,覆盖默认鉴权路径。如果工具支持apiKey字段,优先用它而不是 OAuth。
模型不调工具 / 一直返回文本:这是 tool-calling 稳定性问题,不是通道问题。GLM 对tools和tool_choice的支持程度因版本而异。确认你用的模型 ID 支持 function calling,tool_choice设成auto。如果还是不行,把temperature调低到 0.1 到 0.2,减少模型“自由发挥”。
排查顺序建议固定:先 curl 验证通道和 Key,再看 Claude Code 日志里的请求体,最后看响应体。90% 的问题在前两步就能定位。
6. 把通道固定下来:统一 Key 与后续验证入口
链路拆完,你会发现 Claude Code 接 GLM 的核心就三件事:配置三件套写全、通道用统一 Key 打通、循环里盯住 tool-calling 是否稳定。配置阶段只发生一次,但决定了后面每一次请求的形态;循环阶段每次任务都在重复“请求组装 → 转发 → 响应回填 → 状态更新”这套动作。
想让这套链路稳定,建议把统一 Key 固定在一个地方管理,别在多个工具里各填一份,改起来容易漏。统一 Key 在https://taotoken.net/api-keys获取,接入文档在https://taotoken.net/doc,里面有各工具的配置示例和字段说明。验证模型是否正常响应,可以直接用模型对话页面发一条最小请求,看返回结构是否符合预期。
如果你后面要跑长期编码任务或 Agent 循环,建议用 Coding Plan,把额度、模型、通道统一管起来,避免任务跑到一半因为 Key 或额度问题中断。链路本身不复杂,复杂的是每一跳的细节,把日志打开、把 curl 跑通,剩下的就是对照着看。