☰
你的工作是「写循环」:一文读懂 2026 年最新范式 Loop Engineering
2026/9/29 4:24:08 网站建设 项目流程

1. 从「敲提示」到「写循环」:Loop Engineering 到底在解决什么

如果你最近在 Claude Code 或 Codex 里反复做同一件事——让它跑测试、看报错、改代码、再跑一遍——那你其实已经在手动执行一个循环了。Loop Engineering(循环工程)要做的,就是把这个「你亲手转的圈」交给一套系统去转。它不是一个新工具,而是一种组织 Agent 工作的范式:你定义目标,系统按节拍运行、派生子 Agent、检查结果、写回进度,然后决定下一步。

一句话概括:你不再亲自当那个提示 Agent 的人,而是去设计一套替你提示它的系统。Claude Code 之父 Boris Cherny 那句被反复引用的话说得很直白——「我的工作就是写循环」。这句话刺耳的地方在于,它宣告了一个姿势转变:过去两年我们握着 AI 这把工具,现在要放手,去搭一个替我们握着工具的系统。

这篇文章面向想把重复任务交给循环编排的开发者。我会先讲清楚 Loop Engineering 在四层演进线里的位置,再给出一个能在本地跑通的最小循环配置骨架,最后把验证动作和常见报错一起过一遍。适合谁:已经在用 Claude Code / Codex 做日常开发、想让 Agent 自己跑起来而不是一句句喂提示的人。不适合谁:还没搞懂 prompt 和 context 区别、指望复制一段配置就万事大吉的人——循环会放大你的理解,也会放大你的偷懒。

2. 四层演进线:Loop 坐在 Harness 的上面一层

要理解循环工程,不能孤立地看它。把它放进一条从下往上的演进线里,人离「关键路径」就远一层:

层级名称关注点
第 1 层Prompt Engineering优化输入给模型的文字
第 2 层Context Engineering怎样把恰当的信息填进上下文窗口
第 3 层Harness Engineering设计单个 Agent 运行所在的工程环境(目标、上下文、权限、验证、回滚)
第 4 层Loop Engineering让 Harness 跑在定时器上、自己派生小助手、自己喂自己

关键在于:这四层是叠层关系,不是互相取代。Prompt 优化输入文字;Context 决定填什么进窗口;Harness 设计单个 Agent 的运行环境;Loop 则坐在 Harness 上面,让 Harness 按节拍运行、派生子 Agent、自我喂养。

所以循环工程是一个需要长期掌握的领域,而不是一次转瞬即逝的热点。如果你还没搞懂下面三层,很容易把四个概念混为一谈——比如把「写循环」理解成「写更长的提示词」,那就完全跑偏了。

2.1 五大模块 + 一处外部记忆

循环工程的完整定义是:你定义一个目的,AI 持续迭代直到完成。它由五大模块加一处外部记忆构成,让「单次运行」变成一个「可以自己重复、自己推进的系统」。好消息是,这五大模块今天在 Codex 与 Claude Code 上几乎一一对应:

模块作用Claude CodeCodex
Automations定时发现与分类,循环的「心跳」hooks / cron 调度Automations 标签页 + Triage 收件箱
Worktrees并行隔离底座,为同一仓库开独立工作目录与分支git worktree 隔离内建 worktree
Skills把项目知识固化成 SKILL.mdSkillsSkills
Plugins / Connectors用 MCP 接入真实工具MCP 连接器MCP 连接器 + .codex/agents
Sub-agents产出与检查分离Sub-agents.codex/agents 子 Agent

补充两个容易混的概念:Skill 是编写格式,Plugin 是分发方式;MCP 是连接器的开放标准——因为 Codex 与 Claude Code 都讲 MCP,所以一个连接器常能两边通用。

至于那处外部记忆,是所有长周期循环依赖的同一个朴素技巧:模型在两次运行之间会忘掉一切,所以你要给循环一根「脊柱」。用一个对话之外的状态文件(一个 Markdown 文件,或一块看板)记住进度,让明早的运行能接着昨天继续。人会忘,仓库不会。

3. 前置准备:用 TaoToken 统一接入 Claude Code 与 Codex

在跑循环之前,得先让 Agent 能稳定调用模型。循环的特点是「无人值守地反复调用」,所以接入层要满足两个条件:一是接口稳定,二是能在一个地方看到用量,否则循环自己花钱你都不知道花在哪。

我这边用的是 TaoToken 做统一接入。它的定位是把 Claude Code、Codex 这类 Agent 工具的模型调用收敛到一个入口,官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api 。下面这套配置对循环场景比较友好,因为循环里子 Agent 会各自跑模型,统一入口能让你在一个面板里看清消耗。

3.1 拿 Key 与配置环境变量

先到控制台创建 API Key,入口在 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,Key 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。拿到 Key 之后,不要写进代码,用环境变量:

# 写入 shell 配置,避免循环脚本里硬编码 export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_BASE_URL="https://taotoken.net/api" # 验证变量生效 echo $TAOTOKEN_BASE_URL

注意:循环脚本会被反复执行,Key 一旦硬编码进脚本,很容易在日志或 git 历史里泄露。统一走环境变量是最省心的做法。

3.2 在 Claude Code 侧接入

Claude Code 支持通过环境变量指定接入地址。把下面这段加进你的 shell 配置或项目级.env:

# Claude Code 接入配置 export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="$TAOTOKEN_API_KEY"

配置完成后,进入项目目录启动 Claude Code,它会走你指定的入口。如果你更习惯在对话里验证模型是否通,可以直接用模型对话页试一句:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。

3.3 在 Codex 侧接入

Codex 的接入方式类似,核心是把 base_url 指向同一个端点。配置文件通常放在~/.codex/config.toml:

# ~/.codex/config.toml model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY"

这样 Claude Code 和 Codex 就共用同一个 Key 和同一个用量视图。循环跑起来之后,你只需要盯一个地方的成本,而不是在两个后台之间来回切。

4. 可复制的循环配置骨架:/loop 与 /goal

理论说再多,不如亲手跑一次。最小循环靠两个原生命令:/loop按设定的节拍重复运行一段提示,像心跳一样;/goal持续运行直到你写的条件为真,每轮后由一个独立模型判定是否真的完成。Codex 也有同名的/goal。

这里藏着一个关键设计哲学:为什么/goal要用独立模型判定?因为写代码的模型给自己打分太宽容了。循环里最有用的结构,就是让一个子 Agent 负责产出、另一个用不同指令甚至不同模型去审查。

4.1 最小循环骨架

下面是一个可以直接改用的循环骨架。它做三件事:读外部记忆、跑一轮产出、让独立检查者判定是否达标。

# LOOP.md —— 循环的外部记忆脊柱 ## 目标 让 tests/ 下所有测试通过,且不修改测试文件本身。 ## 当前状态 - 最近一次运行:2026-06-13 09:00 - 失败用例:test_parser.py::test_nested_quotes - 已尝试方案:调整 tokenizer 的引号处理(未通过) - 下一步:检查 parser 的转义逻辑 ## 停止条件 `pytest tests/ -q` 退出码为 0,且 git diff 未触碰 tests/ 目录。 ## 检查者指令 你是独立审查者。不要修改代码,只做三件事: 1. 运行 pytest,记录退出码; 2. 检查 git diff --name-only 是否包含 tests/; 3. 若两项都通过,输出 GOAL_REACHED,否则输出 CONTINUE 并列出失败原因。

然后在 Claude Code 里这样驱动:

/loop 每 10 分钟执行一次: 1. 读取 LOOP.md 的「当前状态」和「下一步」; 2. 按「下一步」修改源码,不要动 tests/; 3. 运行 pytest,把结果写回 LOOP.md 的「当前状态」; 4. 调用检查者子 Agent 按「检查者指令」判定。 /goal 直到 LOOP.md 的「停止条件」为真: 每轮结束后由独立模型判定,输出 GOAL_REACHED 才停止。

4.2 用 worktree 做并行隔离

如果你想让多个循环同时跑,必须用 worktree 隔离,否则两个 Agent 会互相覆盖文件:

# 为循环 A 开一个独立工作树 git worktree add ../proj-loop-a -b loop/fix-parser # 为循环 B 开另一个 git worktree add ../proj-loop-b -b loop/refactor-tokenizer # 查看当前所有工作树 git worktree list

每个 worktree 是一个独立目录加独立分支,循环 A 改 parser、循环 B 改 tokenizer,互不干扰。跑完再合并,冲突在合并阶段处理,而不是在运行阶段互相踩。

4.3 用 SKILL.md 固化项目知识

循环最怕每轮从零重建项目意图。把项目约定写成 SKILL.md,循环每轮读一次,就不用反复解释:

# SKILL.md ## 项目约定 - 测试框架:pytest,测试文件在 tests/,禁止修改 - 代码风格:black + isort,提交前必须跑 - 分支命名:loop/<任务名> ## 常用命令 - 跑测试:pytest tests/ -q - 格式化:black src/ && isort src/ - 查看改动:git diff --stat

5. 验证请求与成功结果:怎么确认循环真的在跑

配置写完不算跑通,得看到循环真的在推进。验证分三步:先确认模型调用通,再确认单轮循环能跑完,最后确认外部记忆在更新。

5.1 先验证接入层

在启动循环之前,先用一个最小请求确认接入没问题:

curl -s 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-20250514", "max_tokens": 64, "messages": [{"role": "user", "content": "只回复 OK"}] }'

返回里能看到正常的 content 字段,说明接入层通了。如果这里就报 401 或 404,先别急着跑循环,回到第 6 节排查。

5.2 观察单轮循环的行为

启动/loop之后,重点观察三件事,而不是只看它有没有输出:

第一,LOOP.md 的「当前状态」有没有被更新。如果每轮结束文件都没变,说明循环没有写回记忆,明早的运行会从零开始。

第二,检查者子 Agent 有没有真的独立判定。你可以在 LOOP.md 里故意写一个假的「已通过」,看检查者会不会被骗——如果它直接输出 GOAL_REACHED,说明检查者没有真正运行 pytest,产出和检查没有分离。

第三,git diff 有没有越界。循环应该只改源码,不该动 tests/。跑几轮后执行:

git diff --name-only

如果列表里出现 tests/ 下的文件,说明停止条件里的约束没有被执行,需要把约束写进检查者指令,而不是只写在目标里。

5.3 成功结果的形态

一个健康的循环,跑起来之后你会看到这样的节奏:LOOP.md 每轮更新一次状态,失败用例数量单调下降,检查者每轮输出 CONTINUE 加具体原因,直到某一轮输出 GOAL_REACHED 然后停止。整个过程你不需要敲任何提示,只需要在它停下来之后看 diff。

flowchart TD A[定时器触发] --> B[读取 LOOP.md 状态] B --> C[产出子 Agent 修改源码] C --> D[运行 pytest] D --> E[写回 LOOP.md] E --> F[检查者子 Agent 独立判定] F -->|GOAL_REACHED| G[停止循环] F -->|CONTINUE| A

6. 本篇常见错排查

循环跑不起来,八成是下面几个问题。我按出现频率排一下。

6.1 报 401 / 403:Key 没生效

最常见的原因是环境变量没被循环进程继承。循环脚本如果是通过 cron 或独立 shell 启动的,它读不到你交互式 shell 里的 export。解决办法是把变量写进脚本能读到的地方,或者在启动脚本里显式 source:

# 在循环启动脚本开头显式加载 source ~/.bashrc # 或者直接写进脚本 export ANTHROPIC_API_KEY="$TAOTOKEN_API_KEY"

排查时先echo $ANTHROPIC_API_KEY确认非空,再确认 base_url 没有多余斜杠。

6.2 循环空转:每轮状态不变

如果 LOOP.md 一直不更新,通常是提示里没有明确要求写回。模型不会自动帮你维护外部记忆,你必须在/loop的指令里显式写「把结果写回 LOOP.md 的当前状态」。另一个原因是停止条件写得太模糊,比如「让代码更好」——这种条件检查者无法判定,只能一直 CONTINUE。

6.3 检查者被产出者带偏

如果检查者和产出者用同一个模型、同一段上下文,它很容易顺着产出者的思路走,把没通过的判成通过。解决办法是给检查者单独的指令,明确「不要修改代码,只运行验证命令」,条件允许时换一个模型做检查。这就是产出与检查分离的意义。

6.4 worktree 冲突:两个循环改同一个文件

没用 worktree 隔离时,两个循环会同时改同一个工作目录,git 状态会乱。表现是git status里出现大量非预期改动,或者循环报「文件被占用」。解决办法是每个循环一个 worktree,跑完再合并。合并冲突是正常的,在合并阶段处理比在运行阶段互相覆盖要好得多。

6.5 成本失控:token 消耗成倍上升

循环会自己花钱。子 Agent 各自跑模型、跑工具,token 消耗成倍上升。如果发现用量异常,先检查是不是给每一步都配了审查者。把「第二意见」花在真正值得的地方,而不是每轮都全量审查。在 TaoToken 控制台可以按时间段看用量,定位是哪个循环在烧:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 。

6.6 编排税:并行度受限于你能看多少 diff

一个残酷的现实约束:你能并行跑多少个 Agent,取决于你能认真看完多少 diff,而不是工具支持多少路。工具支持 100 路并行没用,你只看得完 3 个 diff,那你的真实并行度就是 3。这不是配置问题,是人的带宽问题,只能靠减少并行数或提高审查效率来解决。

7. 把循环补全成系统:从最小骨架到长期运行

跑通最小循环之后,下一步是把它补成一个能长期运行的系统。路径大致是:接上 Automations 做心跳,用 Worktrees 做并行隔离,用 Skills 固化项目知识,用 Connectors 接入真实工具,用 Sub-agents 做产出与检查分离,最后给循环加上外部记忆脊柱和一个独立的检查者。

如果你打算长期跑编码类循环或 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?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,需要的话可以对照着看。

7.1 堆叠循环:向上还是向下

当你能稳定跑一个循环之后,真正的进阶是堆叠循环——一层套一层。这里要在两个方向之间做判断:Going Down(向下,求稳)是用杠杆换可靠性,把自动化退回到人工把关,适用于早期阶段;Going Up(向上,求快)是用可靠性换杠杆,把原本人工的判断也交给一个新循环,适用于模型变强、你有信心的时候。

判断什么时候该往哪个方向走,正是循环工程师区别于「只会按开始的人」的地方。Karpathy 那句「别再亲手修,去做能随更多 Agent 扩展的系统」,说的就是这个。

7.2 三个必须盯住的成本

向上堆叠不是免费的。Token 成本会成倍上升,编排税会限制你的真实并行度,而最隐蔽的是理解债——出活越快,你与代码之间的认知缺口越大。验证仍在你身上:循环无人值守,它犯错也无人值守。最危险的是循环一顺,你就懒得有观点了。

同一个循环,两个人能跑出完全相反的结果。一个人用它在自己深刻理解的工作上跑得更快,另一个人用它来彻底回避理解。循环不知道区别,你知道。设计循环比写提示更难,而不是更容易——带判断地做是解药,为逃避思考而做是加速剂。

7.3 一个可以直接用的收尾习惯

最后给一个我一直在用的习惯:每次循环停下来之后,不要只看它改了什么,先看 LOOP.md 里它记录的「已尝试方案」。如果里面出现了你没想过的思路,说明循环在帮你扩展;如果里面全是重复的失败尝试,说明停止条件或检查者指令需要调整。循环会忠实地放大你的一切——放大你的理解,也放大你的偷懒。你放开了敲提示的手,但没有放开判断力,事实上判断力比以往任何时候都更值钱。

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

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

立即咨询