1. 从一次长任务崩溃说起:为什么我要猜 Claude Code 的架构
如果你用 Claude Code 跑过稍微长一点的任务,大概率遇到过这种情况:前 20 分钟它思路清晰,改文件、跑测试、读日志一气呵成;到第 40 分钟开始重复劳动,忘了自己改过哪个文件,甚至把刚写好的函数又删掉。这不是模型变笨了,而是它的「工作记忆」被上下文噪声挤爆了。
我后来意识到,想搞明白这件事,不能只看它调了哪些工具,得从架构层去猜它到底怎么组织 Agent Loop、Tool-Calling 和 Skills。Claude Code 本质上是「LLM 驱动的 Tool-Calling 循环」加上「逐层外置的认知结构」——模型是唯一的智能体,本体代码只负责约束、反馈、隔离和知识注入。这个判断如果成立,那它的配置骨架就应该能反推出来,而且能自己复现。
这篇就按这个思路走:先讲清楚 Agent Loop 这个不变内核,再逐层拆 Tool-Calling、Todo 状态机、子代理隔离和 Skills 注入,最后给你一份可复制的settings.json与config.toml骨架,配合 TaoToken 的统一 Key/API 通道把整套猜想在本地跑起来。适合已经用过 Claude Code、想理解它内部机制、或者想自己搭一个类似 Agent 框架的开发者。
2. 架构猜想的核心:Agent Loop 是不变内核
所有版本的 Claude Code,我猜共享同一个不可约核心,用伪代码写出来大概是这样:
while True: response = llm(messages, tools) if not response.tool_use: break result = execute_tool(response.tool_use) messages.append(tool_result(result))关键点有三个。第一,决策权完全在模型手里——选什么工具、按什么顺序、什么时候结束,都是 LLM 自己判断的,代码只是被动执行器。第二,Claude Code 的「智能」不等于复杂调度逻辑,而是 LLM 自反式决策能力的直接体现。第三,这个循环从最早版本到现在完全一致,变的只是循环外面套了什么。
理解了这一点,后面所有机制都能归位:Tool-Calling 是循环的输入接口,Todo 是循环的外部状态,子代理是循环的隔离副本,Skills 是循环的知识注入。它们都不是新内核,而是围绕同一个 Loop 长出来的器官。
2.1 Tool-Calling 的工程最小集
早期版本只有一个 bash 工具,靠 shell 组合能力完成读、写、执行、递归子进程。后来演化成 bash / read / write / edit 四件套,这不是架构升级,而是工程化——更低的 token 成本、更稳定的调用接口。认知仍然完全在模型隐空间里,工具只是让模型的手伸得更准。
2.2 Todo 状态机:把思考外置
长任务会 Context Fade,因为模型的计划存在于隐状态,一旦上下文被工具结果冲淡就丢了。TodoWrite 的作用是把中间思考外显成状态机,约束是同时只有一项in_progress。这个 Todo 不是给人看的,是给模型自己看的工作记忆。
2.3 子代理:上下文隔离而非多智能体
探索代码和实施修改混在一个 history 里,token 会被垃圾信息占满。Task/Subagent 机制给子代理独立的 message history、工具白名单和专用 system prompt,父代理只拿 summary。这是进程级上下文隔离,本质是「函数调用加返回值」,不是自治多体协作。
2.4 Skills:知识从参数中剥离
Skills 是这套架构里最值得关注的一层。传统方式下知识在模型参数里,训练才能新增;Skills 把知识写进SKILL.md,显式、可版本化。注入的关键工程点在于:它不是走 system prompt,而是通过 tool_result 注入,这样不破坏 prompt cache,成本能降一个量级。Skill 不等于 Tool——Tool 是能力,Skill 是操作范式加专家流程。
3. TaoToken 前置:统一 Key 与 API 通道
要把上面这套猜想在本地复现,你需要一个稳定的模型调用通道。TaoToken 在这里的角色是统一 Key 和 API 入口,让你不用为每个模型单独维护一套鉴权和地址配置。
先到官网注册并拿到 Key:
https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=然后在控制台创建 API Key:
https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=API Key 管理页在这里,可以随时轮换和查看用量:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=API 基础地址统一用:
https://taotoken.net/api注意:API 地址不要加 UTM 参数,只有页面链接才带。Key 建议用环境变量注入,不要硬编码进配置文件。
如果你只是想先验证模型能不能正常对话,可以直接用模型对话页试:
https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=4. 可复制配置:settings.json 与 config.toml 骨架
下面这份骨架是我按架构猜想整理的,分两部分:settings.json负责 Agent Loop 和 Tool-Calling 的行为约束,config.toml负责模型通道和 Skills 路径。
4.1 settings.json:Agent Loop 与工具约束
{ "agent": { "max_iterations": 40, "loop_mode": "tool_calling", "stop_on_no_tool": true, "context_budget_tokens": 120000 }, "tools": { "enabled": ["bash", "read", "write", "edit"], "bash": { "timeout_seconds": 120, "allow_subprocess": true }, "edit": { "require_read_before_write": true } }, "todo": { "enabled": true, "max_items": 20, "single_in_progress": true }, "subagent": { "enabled": true, "isolate_history": true, "return_summary_only": true, "tool_whitelist": ["read", "bash"] }, "skills": { "enabled": true, "inject_via": "tool_result", "path": "./skills", "preserve_prompt_cache": true } }几个参数值得单独说。loop_mode固定为tool_calling,对应前面那个 while 循环。stop_on_no_tool为 true 时,模型不返回 tool_use 就结束循环。todo.single_in_progress是状态机的硬约束。skills.inject_via设成tool_result而不是system_prompt,这是保住 prompt cache 的关键。
4.2 config.toml:模型通道与 Skills 注册
[provider] name = "taotoken" base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" default_model = "claude-sonnet-4" timeout_seconds = 300 [provider.retry] max_attempts = 3 backoff_seconds = 2 [skills] root = "./skills" auto_load = true [[skills.entries]] name = "code-review" file = "skills/code-review/SKILL.md" inject = "tool_result" [[skills.entries]] name = "refactor-flow" file = "skills/refactor-flow/SKILL.md" inject = "tool_result" [subagent] model = "claude-haiku-4" max_concurrent = 3api_key_env指向环境变量,启动前先导出:
export TAOTOKEN_API_KEY="你的Key"4.3 SKILL.md 的最小结构
Skills 目录下每个技能一个文件夹,里面放SKILL.md:
--- name: code-review description: 对指定文件做结构化代码审查 --- ## 触发条件 当用户要求审查代码或提交前检查时使用。 ## 操作步骤 1. 用 read 读取目标文件 2. 按可读性、边界条件、错误处理三个维度检查 3. 输出问题列表,每条附行号和修改建议 ## 输出格式 - 文件路径 - 问题清单(行号 + 描述 + 建议)这个文件通过 tool_result 注入,模型在需要时才会读到,不会常驻 system prompt。
5. 验证请求:确认 Agent Loop 真的在跑
配置写好后,先做一次最小验证,确认通道和循环都正常。
5.1 直接测 API 通道
curl -s https://taotoken.net/api/v1/messages \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4", "max_tokens": 256, "messages": [{"role": "user", "content": "回复 OK 两个字母"}] }'返回里能看到content字段带OK,说明 Key 和地址都对。
5.2 验证 Tool-Calling 循环
给模型一个需要多步工具调用的任务,观察它是否按「调用工具 → 拿结果 → 再决策」的节奏走:
curl -s https://taotoken.net/api/v1/messages \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4", "max_tokens": 512, "tools": [{ "name": "read_file", "description": "读取文件内容", "input_schema": { "type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"] } }], "messages": [{"role": "user", "content": "读取 config.toml 并告诉我 default_model 的值"}] }'如果返回的stop_reason是tool_use,并且content里有tool_use块,说明循环的第一跳正常。你手动把 tool_result 拼回去再请求一次,模型应该能基于结果给出最终答案——这就是 Agent Loop 的最小闭环。
5.3 验证 Skills 注入
在skills/code-review/SKILL.md里写一段独特标记,然后让模型执行代码审查任务。如果模型输出里出现了你标记里的步骤结构,说明 Skills 通过 tool_result 注入成功。这一步能验证「知识外置」这条猜想是否在你的配置下成立。
6. 本篇常见错排查
6.1 401 或鉴权失败
先确认环境变量真的导出了:
echo $TAOTOKEN_API_KEY如果为空,说明当前 shell 没加载。写进~/.bashrc或~/.zshrc后重新开终端。另外检查config.toml里api_key_env的名字和实际变量名是否一致,大小写敏感。
6.2 循环停不下来或提前结束
max_iterations设太小会提前断,设太大遇到模型钻牛角尖会烧 token。建议从 40 起步,观察日志里每轮的工具调用。如果模型反复调同一个工具,多半是 tool_result 格式不对,模型读不懂返回内容,只能重试。检查 tool_result 的content是不是字符串或标准内容块数组。
6.3 Skills 没生效
最常见的原因是inject_via写成了system_prompt。改成tool_result后,还要确认SKILL.md的 frontmatter 格式正确,name和description不能缺。另外skills.root路径是相对启动目录的,用绝对路径更稳。
6.4 子代理返回内容为空
return_summary_only为 true 时,父代理只拿 summary。如果子代理的 system prompt 没要求它输出总结,summary 可能就是空的。在子代理配置里加一句「任务完成后输出不超过 200 字的结论」,问题基本解决。
6.5 prompt cache 命中率低
Skills 走 tool_result 注入就是为了保 cache。如果发现成本没降,检查是不是在 system prompt 里塞了动态内容——任何每轮都变的东西都会让 cache 失效。把动态部分挪到 messages 里,system prompt 保持稳定。
7. 继续往下走:把猜想变成你自己的 Agent
到这里,Agent Loop、Tool-Calling、Todo 状态机、子代理隔离、Skills 注入这五层你都能在本地跑通了。这套骨架的价值不在于复刻 Claude Code,而在于你理解了「LLM 是唯一智能体,其他都是外置认知器官」这个判断后,可以按自己的任务特点调整每一层。
如果你接下来要长期跑编码任务或者搭 Agent 工作流,建议直接上 Coding Plan,省去每次手动配通道的麻烦:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=接入文档在这里,遇到参数细节可以对照查:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=如果你用的是 Claude Code 的 Anthropic 兼容模式,配置参考这个页面:
https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=最后留一个我踩过的坑:别急着把max_iterations调大来「让它多想一会儿」。循环质量取决于每轮 tool_result 的信息密度,不是轮数。把工具返回精简到模型真正需要的字段,比加轮数有效得多。