
1. 从一次“跑偏”的 Agent 任务说起任务循环与上下文管理到底难在哪如果你自己动手写过 Agent大概率遇到过这种场景让它重构一个小模块前两轮还挺正常第三轮开始它忘了自己改过哪个文件第五轮直接把之前删掉的代码又加回来第七轮上下文爆了客户端报一个context length exceeded整个任务链断掉。这不是模型不行而是任务循环和上下文管理这两条工程主线没搭好。Claude Code 之所以被很多开发者当成 Agent 工程学的参考样本核心不在于它用了多强的模型而在于它把「任务循环」和「上下文管理」这两件事做成了闭环。任务循环解决的是“下一步该干什么、干错了怎么办”上下文管理解决的是“在有限窗口里怎么记住真正重要的东西”。这两条线任何一条塌了Agent 都会从“能干活”退化成“能聊天”。这篇文章面向想理解 Agent 工程化设计的开发者我会给出一条可复制的源码阅读路径、关键模块拆解清单并且用统一的 Key/API 通道实际验证多轮任务循环里的上下文传递效果。你不需要有 Claude Code 的完整源码跟着思路和验证方法走一样能把这套设计迁移到自己的 Agent 项目里。先明确一个检索词Claude Code 任务循环与上下文管理源码拆解这是本文的主线。适合谁看写过基础 ReAct demo、想让 Agent 稳定跑长任务的开发者正在被上下文溢出和工具调用容错折磨的人以及想搞清楚“为什么顶级 Agent 模型只占一半功劳”的人。我试过用最朴素的 while 循环套 LLM 调用去做代码助手结果就是上面说的那种崩溃。后来把任务循环和上下文管理分开设计稳定性立刻上了一个台阶。下面按这个思路拆。2. 阅读 Claude Code 源码前的前置准备统一 Key/API 通道与工具链在拆源码之前得先有一个能实际跑起来的环境否则你看到的只是静态代码验证不了任务循环的行为。Claude Code 这类工具本质上是「客户端 模型 API」的结构客户端负责任务循环、上下文管理、权限控制模型负责推理和工具调用决策。要复现它的行为你需要一条稳定的 API 通道。这里用 TaoToken 作为统一通道原因是它同时提供 Claude 系列和多家模型的兼容接口方便你在同一套任务循环里切换模型做对照实验。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。前置准备分三步。第一步拿到 Key。进入控制台创建 API Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。创建后立刻复制保存页面刷新后不再完整显示。Key 的格式通常是一串以特定前缀开头的字符串别把它提交到 Git。第二步确认你要用的模型 ID。Claude Code 场景下常用的是 Claude 系列模型模型 ID 要写全比如claude-sonnet-4-5这类。模型 ID 写错是最常见的 404 来源后面排障章节会细说。第三步准备一个能发请求的客户端。你可以直接用 curl 验证也可以用 Claude Code 本体、Cline、或者自己写的脚本。如果走 Claude Code 本体需要配置 Base URL、Key、Model ID 三件套如果走自写脚本用 Anthropic 兼容格式即可。这里给一个最小验证命令确认通道通了再往下拆源码curl https://taotoken.net/api/v1/messages \ -H x-api-key: $TAOTOKEN_API_KEY \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-5, max_tokens: 256, messages: [ {role: user, content: 用一句话说明什么是任务循环} ] }返回里能看到content数组和stop_reason字段就说明通道正常。stop_reason这个字段在任务循环里非常关键它告诉你模型是正常结束end_turn还是想调用工具tool_useClaude Code 的循环就是靠它决定下一步走向。注意API Key 只放在环境变量或本地配置文件里不要硬编码进源码也不要在截图里暴露。这是所有 Agent 项目的基本安全线。环境通了之后你才有资格谈“拆源码”。因为任务循环的很多行为只有实际发请求、观察返回才能理解它为什么这么设计。静态读代码容易漏掉运行时才暴露的边界情况。3. 任务循环源码拆解从 Thought 到 Action 的状态机怎么落地Claude Code 的任务循环不是简单的“问一句答一句”而是一个自驱式状态机。核心状态可以抽象成三段Thought思考、Action工具调用、Observation观察结果。这三段循环往复直到模型给出终止信号。先看循环的骨架。伪代码大致是这样def agent_loop(task, context): while True: response call_model(context) if response.stop_reason end_turn: return response.text if response.stop_reason tool_use: tool_call extract_tool_call(response) result execute_tool(tool_call) context.append(tool_result_message(result)) continue看起来简单但魔鬼在细节里。Claude Code 在三个地方做了加固这也是它和普通 demo 的分水岭。第一处加固强制显式思考。它在系统提示里要求模型在调用工具前先在输出里包含思考内容。这不是为了好看而是为了让循环的每一步都有可追溯的决策依据。当任务跑偏时你能从思考内容里定位是哪一步推理错了。落地到配置上就是在系统提示里加约束比如要求“在调用任何工具前先用一段文字说明你为什么选这个工具”。第二处加固工具描述极其详尽。普通 Agent 给工具写一句“读取文件”就完事Claude Code 会给每个工具写清楚参数含义、边界条件、失败时的返回格式。工具描述本质上是给模型的 API 文档描述越准模型选错工具的概率越低。你在自己的项目里可以照做每个工具的描述至少包含“什么时候用、参数是什么、返回什么、失败长什么样”。第三处加固错误即输入。当工具执行失败系统不会中断循环而是把标准错误输出原样塞回上下文并追加一句引导让模型自己修正。这是任务循环鲁棒性的关键。普通 Agent 遇到报错就复读是因为它把错误当成了终点Claude Code 把错误当成新的观察结果循环继续。下面是一个可复制的工具定义片段展示怎么把工具描述写细{ name: read_file, description: 读取指定路径的文件内容。当需要查看已有代码、配置或日志时使用。参数 path 必须是相对项目根目录的路径。如果文件不存在返回错误信息而不是抛出异常。单次读取超过 2000 行时只返回前 2000 行并提示截断。, input_schema: { type: object, properties: { path: { type: string, description: 相对项目根目录的文件路径例如 src/main.py } }, required: [path] } }注意description里把“什么时候用、参数约束、失败行为、截断行为”都写清楚了。这段描述直接决定模型会不会在错误的时机调用它。任务循环还有一个容易被忽略的点循环终止条件。除了模型主动end_turn还要有硬性保护比如最大轮次上限、单次任务总 token 预算、连续失败次数阈值。Claude Code 在源码里对这些都有兜底否则一个死循环能把额度烧光。你在自己项目里至少要加最大轮次和连续失败计数两个保护。验证任务循环是否正常可以设计一个多步任务让 Agent 先读一个文件再根据内容改另一个文件最后运行一条命令。观察每一轮的stop_reason和工具调用参数如果第三轮它还记得第一轮读到的内容说明循环的上下文传递是通的。这一步的验证方法在第四节展开。4. 上下文管理源码拆解分层摘要与动态清理怎么配合上下文管理是 Claude Code 最值得抄的部分。编程任务动辄涉及几十个文件、上百轮对话上下文窗口再大也会爆。Claude Code 没有暴力截断而是做了一套类似操作系统虚拟内存的分层机制。第一层核心层。系统提示 最近几轮对话权重最高永远保留。系统提示定义了 Agent 的角色、行为约束、输出格式丢了它 Agent 就失忆。最近几轮对话保留了当前任务的即时状态比如“刚改完哪个文件、下一步要干什么”。第二层压缩层。中间的历史对话会被模型自己总结成简短摘要。注意是“模型自己总结”不是简单截断。摘要保留了任务的关键决策和已完成步骤丢弃了冗长的中间过程。这样即使对话很长核心脉络还在。第三层临时层。巨大的工具输出比如搜索返回了 100 个文件、读了一个 5000 行的日志不会全部塞进上下文而是先存到临时缓冲区只保留最关键的几行摘要。需要细节时再按需取回。这套分层的关键在于“按需取回”。上下文不是一次性全塞进去而是维护一个索引模型需要哪部分细节再通过工具调用把对应内容拉回来。这就像操作系统只把当前用到的内存页加载进来其余留在磁盘。动态清理机制是配套的。源码里有一段逻辑专门算 token 预算当即将超标时优先丢弃“非必要”信息比如冗长的文件列表、重复的工具输出而不是丢弃用户的原始意图。用户意图是最高优先级任何情况下不能丢。落地到配置上你可以在自己的 Agent 里维护一个上下文对象结构大致如下{ system_prompt: 你是资深工程师简洁、注重生产力……, recent_turns: [ {role: user, content: 重构 auth 模块}, {role: assistant, content: 已读取 auth.py准备拆分校验逻辑} ], summary: 任务重构 auth 模块。已完成读取 auth.py识别出校验逻辑耦合。待办拆分校验函数、更新调用方。, buffer_refs: [ {id: search_1, desc: 搜索 auth 相关文件命中 12 个, preview: auth.py, login.py, ...} ], token_budget: 180000, used_tokens: 42000 }每次调用模型前先算一遍used_tokens超过阈值就触发压缩把recent_turns里较早的轮次合并进summary把大块工具输出转成buffer_refs的预览。这样上下文始终维持在预算内同时不丢关键信息。验证上下文传递效果可以设计一个跨多轮的任务第一轮让 Agent 读一个配置文件并记住某个值中间插入若干轮无关操作最后一轮问它那个值是多少。如果它能答对说明摘要和核心层配合正常如果答错说明压缩时把关键信息丢了需要调整摘要策略。这里有个坑摘要不能太激进。如果每轮都压缩模型会丢失细节导致“晚年痴呆”。合理的做法是设置一个水位线比如用到预算的 70% 才开始压缩且压缩时保留最近 5 轮原文。这个参数需要根据你的任务类型调代码任务建议保留更多原文因为代码细节容易在摘要里失真。上下文管理做得好Agent 才能跑长任务。这也是为什么说“上下文是昂贵的资产”学会做信息的断舍离是 Agent 从 demo 走向可用的必经之路。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth拆源码和验证的过程中报错是常态。这一节把最常见的几类错误和排查路径列清楚对照真实报错定位问题。401 Unauthorized。这是 Key 相关错误里最高频的。表现是请求返回 401提示认证失败。排查顺序先确认 Key 是否完整复制有没有多余空格再确认请求头字段名是否正确Anthropic 兼容格式用x-api-keyOpenAI 兼容格式用Authorization: Bearer两者不能混最后确认 Key 是否已过期或被禁用。如果用的是 Claude Code 本体检查配置文件里的 Key 字段有没有写错位置。local proxy failed。这个报错通常出现在客户端配置了本地代理但代理没起来或者 Base URL 写成了本地地址。排查确认 Base URL 是https://taotoken.net/api不要写成localhost或带端口的本地地址确认没有残留的代理环境变量比如HTTP_PROXY、HTTPS_PROXY这些变量会让请求走本地代理导致失败。清掉这些变量再试。reading choices 相关报错。这类错误一般出现在解析模型返回时客户端期望 OpenAI 格式的choices数组但实际拿到的是 Anthropic 格式的content数组或者反过来。根因是接口格式和客户端预期不匹配。排查确认你用的客户端走的是哪种兼容格式Anthropic 格式返回contentOpenAI 格式返回choices。如果客户端只认choices就要用 OpenAI 兼容端点如果只认content就用 Anthropic 兼容端点。别混用。OAuth 相关报错。如果客户端提示 OAuth 失败或 token 无效通常是因为它尝试走 OAuth 流程而不是 API Key 流程。Claude Code 本体在某些配置下会走 OAuth如果你用的是 API Key 通道需要在配置里明确指定用 Key 认证关掉 OAuth 相关选项。检查配置文件里是否有oauth字段被误开。模型 ID 错误导致的 404。这个单独拎出来说因为太常见。表现是请求返回 404 或提示模型不存在。排查确认模型 ID 拼写完整大小写正确不要用简称。比如claude-sonnet-4-5不能写成sonnet或claude-sonnet。模型 ID 以控制台或文档里列出的为准。上下文超限报错。表现是context length exceeded或类似提示。这说明你的上下文管理没生效或者单次塞入的内容太大。排查检查是否把整个大文件直接塞进了上下文应该走临时层只保留摘要检查压缩逻辑是否触发水位线是否设得太高检查是否有工具输出没有做截断。排查的通用思路是先看报错原文定位是认证、网络、格式还是模型问题再对照配置三件套Base URL、Key、Model ID逐项确认最后用最小 curl 命令复现排除客户端本身的干扰。最小复现能通说明通道没问题问题在客户端配置最小复现也不通说明通道或 Key 有问题。提示遇到报错先别急着改代码把完整报错信息复制出来对照上面的分类定位。大部分问题集中在配置三件套和格式不匹配上真正需要改源码的情况很少。6. 把任务循环和上下文管理迁移到自己的 AgentCTA 与下一步拆完这两条主线你会发现 Claude Code 的工程底力不在某个炫技的算法而在任务循环的容错设计和上下文管理的分层策略。这两块做好了模型能力才能真正发挥出来。工程化大于算法化边界比自由更重要上下文是昂贵的资产这三条在拆解过程中反复被验证。如果你想继续深入下一步可以做三件事。第一用统一通道跑一个多轮任务观察每一轮的stop_reason和上下文变化验证循环和压缩是否按预期工作。第二把工具描述按“什么时候用、参数、返回、失败”四要素重写一遍对比模型选错工具的概率有没有下降。第三给自己的 Agent 加上最大轮次、连续失败计数、token 预算三个保护避免死循环烧额度。验证模型行为、做多轮对话实验可以用模型对话入口快速试https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。如果你要长期跑编码类 Agent 任务Coding Plan 更适合持续调用https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。需要新建或管理 Key 时控制台在这里https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。接入细节和参数说明看文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。如果你用 Claude Code 本体接入参考 Anthropic 接入说明https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude-code-anthropicutm_campaignrewrite 。最后留一个实操建议别一上来就追求完美的上下文管理。先把任务循环跑通加上错误即输入和最大轮次保护让 Agent 能稳定完成三步以内的任务再引入分层摘要逐步拉长任务链。每加一层机制都用多轮任务验证一次确认没有丢关键信息。这样迭代下来你的 Agent 会从“能聊天”变成“能干活”。