一句话摘要
从提示词转向循环自动化的工作方式
停止手写提示词。开始造循环。2026年7月12日 · 21 分钟阅读 · 查看原文 ↗ Claude AI 循环 自动化
如何构建一个在你睡觉时干活的 AI agent
一年以来,资深 AI 工程师们一直在重复同一句话:别再手动给编码 agent 写提示词了,开始设计能替你给 agent 写提示词的循环(loop)。
这话听起来很棒,却什么都没解释。仓库里到底该放什么?你该敲哪些命令?第二次迭代会崩在哪?
这篇文章在三个真实工具上具体回答这些问题:Claude Code、OpenAI Codex CLI 和 Cursor CLI。下面的每一条命令、路径和标志,都已在 2026 年 7 月 11 日对照官方文档核对过。循环设计在三个工具上是一样的;只有文件名和标志不同,所以映射都是内联的。
提示词 vs 循环
一个提示词回答一次就停。一个循环持续工作,直到活儿真正做完:不是直到它产出一个答案,而是直到它达到一个被验证的结果。
每个 agent 底层都跑同一个循环:发现工作、执行它、验证结果、失败就迭代、碰到一个条件或硬上限就停。
提示词和循环的区别不在于模型。而在于:有没有某个东西能在你不在场时判它失败,以及它失败之后会发生什么。
只要循环是"经由你"在跑(写、等、读、手工修),你一旦离开键盘,一切就停摆。
在实践中它长这样。CI 凌晨 2 点变红,到早上仓库里已有三个带修复的、就绪的 PR,外加一小张 agent 诚实地承认自己无法独自解决的两个问题的清单。或者你正在啃一个 200 个文件的迁移,而每天早上都有一个文件已经被重写、测试、并打包成它自己的 PR,因为循环每次运行恰好只做一个文件,然后停。又或者你单干、没有评审人,于是另一个 agent 充当"第一读者":每天晚上它走一遍你的新提交,留下批注。
这不是关于"替你写代码"。这是关于那些无聊的、反复出现的工作在你忙别处时运行,然后递给你一个完成的 PR 或一次诚实的升级,而不是一份关于"它多努力"的报告。
四条件测试
只有当以下四条全部成立时,一个循环才值得它的设置成本。缺一条,它花出去的就比赚回来的多。
任务会重复,至少每周一次。一次性的事,用一个好提示词关掉更便宜。
验证是自动化的。测试、linter、构建、类型检查。没有自动化闸门,就意味着 agent 在给自己的作业打分,而它是一个慷慨的评分者。
你的预算能吸收浪费。一个循环每次迭代都重读上下文、重试、探索,并且无论有没有交付东西都在烧 token。Claude Code 为这个准备了一根字面意义上的保险丝:--max-budget-usd。第一天就设上。
"完成"是客观的。测试和 lint 的退出码为 0。而不是"看起来不错"。如果"完成"需要人的意见,那就让这个任务保持手工。
拿你自己的活试试。"给失败的 CI 测试做分诊"四条全过:它不断发生、一次测试运行就能验证它、而完成是一个退出码。"升级依赖并确保没坏东西"也过。"把旧模块迁移到新模式"有测试就过,没测试就崩,因为那样就没有可对照验证的东西了。
而"让界面感觉更漂亮"呢,恰恰是第 4 条失败,而且永远失败。没有任何 agent 会在"美"这件事上给你退出码 0。这类任务保持手工,这也没问题。
三个工具,一张地图
在进入步骤之前,这里是完整映射。每一项在下面展开。
安装,各一行:
curl -fsSL https://claude.ai/install.sh | bash # Claude Code -> 二进制:claude
curl -fsSL https://chatgpt.com/codex/install.sh | sh # Codex CLI -> 二进制:codex
curl https://cursor.com/install -fsS | bash # Cursor CLI -> 二进制:agent
其余的一切,逐个工具:
Claude Code(二进制:claude)
项目上下文:CLAUDE.md
权限与模型:.claude/settings.json
技能:.claude/skills/ci-triage/SKILL.md
验证 agent:.claude/agents/verifier.md
自主运行:claude -p "..."。用 --continue 或 --resume 续跑。
自动闸门:PreToolUse、PostToolUse、Stop 上的 hooks
在 CI 里:anthropics/claude-code-action@v1
Codex CLI(二进制:codex)
项目上下文:AGENTS.md
权限与模型:~/.codex/config.toml
技能:.agents/skills/ci-triage/SKILL.md
验证 agent:.codex/agents/verifier.toml
自主运行:codex exec "..."。用 codex exec resume --last 续跑。
自动闸门:没有 hooks。由 sandbox_mode 配置的沙箱本身扮演这个角色。
在 CI 里:openai/codex-action@v1
Cursor CLI(二进制:agent)
项目上下文:.cursor/rules。它也读 AGENTS.md 和 CLAUDE.md。
权限:.cursor/cli.json
技能:通常意义上没有。最接近的东西:.cursor/commands 里的命令。
验证 agent:没有。最接近的东西:以 --mode plan 单独跑一次。
自主运行:agent -p "..."。用 --continue 或 --resume 续跑。
自动闸门:.cursor/hooks.json 里的 hooks
在 CI 里:没有官方 action,但有一个基于 curl 的官方示例。
一个所有人都栽跟头的细节:Claude Code 不读 AGENTS.md。文档说得明明白白:"Claude Code 读 CLAUDE.md,而不是 AGENTS.md。"如果你的仓库已经为 Codex 准备了一个 AGENTS.md,用一个 import 或一个 symlink 把它接进来:
ln -s AGENTS.md CLAUDE.md
或者创建一个带一行 import、再加你自己的补充的 CLAUDE.md:
@AGENTS.md
## Claude Code specifics
Use plan mode for changes under src/billing/.
第 1 步。项目上下文
从这里开始是五个文件。没什么花哨的:仓库里的纯文本,每个回答一个问题。
agent 必须先理解你的代码库,才能在上面跑循环。根目录下一个文件,每个会话开始时自动读取。
AGENTS.md(Codex、Cursor)或 CLAUDE.md(Claude Code):
# AGENTS.md
## Architecture
- src/api/ - Express routes
- src/services/ - business logic
- src/db/ - models (PostgreSQL via Prisma)
- tests/ - Jest suite
## Key commands
- npm test - full test suite
- npm run lint - ESLint
- npm run typecheck - tsc --noEmit
## Rules
- Never touch src/billing/ or src/auth/ without human approval
- Always run tests before marking a task complete
- Errors only through the pattern in src/utils/errors.ts
写下那些代码里没有、但每个队友到第三个月都心知肚明的东西:哪个目录危险、哪个测试不稳定、为什么那个模块是禁区。这正是 agent 自己搞不明白的东西。
值得提前知道的限制。Claude Code 建议把 CLAUDE.md 控制在 200 行以内,并支持文件 import——写成 at 符号(@)后跟路径,最多 4 层深。它还让你把模块化规则拆进 .claude/rules,在那里 frontmatter 里的一个 paths glob 会让某条规则只在你碰匹配文件时才加载。
Codex 从项目根目录一路读到你的工作目录,把 AGENTS.md 链从上到下拼接起来,离得最近的文件赢。硬限制:project_doc_max_bytes,默认 32 KiB。超过的部分被静默截掉。
Cursor 把规则放在 .cursor/rules/*.mdc 里,frontmatter 带 description、globs 和 alwaysApply,而这比看起来更重要:一条带 globs 的规则只附着在匹配的文件上,这在一个大仓库里能省下真实的上下文。根目录下那个旧式的 .cursorrules 正在退场,迁移掉它。
第 2 步。权限与模型
第二个文件决定循环是独自跑,还是卡在第一个问题上。
Claude Code,.claude/settings.json。规则按 deny、然后 ask、然后 allow 的顺序评估,第一个匹配的赢:
{
"model": "claude-sonnet-5",
"permissions": {
"allow": ["Bash(npm run lint)", "Bash(npm run test *)", "Edit"],
"ask": ["Bash(git push *)"],
"deny": ["Read(./.env)", "Read(./secrets/**)", "Bash(curl *)"],
"defaultMode": "acceptEdits"
}
}
指定符里的空格是有意义的:Bash(ls *) 匹配 ls -la 但不匹配 lsof。一件小事,有朝一日能帮你省掉一次事故。
关于模型:model 字段要么填一个精确 ID(claude-sonnet-5、claude-opus-4-8),要么填一个别名(sonnet、opus、haiku、fable、best)。对 agentic 编码,文档指向 Opus 4.8;这个阵容里当前最强的模型是 Fable 5;而 Sonnet 5 仍是循环里的 worker 在价格/质量上合理的平衡。
Codex,~/.codex/config.toml:
model = "gpt-5.6" # GPT-5.6 于 2026 年 7 月 9 日发布
model_reasoning_effort = "high" # minimal | low | medium | high | xhigh
approval_policy = "on-request" # untrusted | on-request | never
sandbox_mode = "workspace-write" # read-only | workspace-write | danger-full-access
[sandbox_workspace_write]
network_access = true # 沙箱里网络默认是关闭的
GPT-5.6 分三档:gpt-5.6-sol(旗舰)、gpt-5.6-terra(均衡,对常规循环通常绰绰有余)和 gpt-5.6-luna(最便宜)。对一个每晚都跑的循环来说,在常规修复上,月度成本差异比质量差异更显眼,所以从最低档开始。
这里有两个陷阱。第一:旧的 suggest / auto-edit / full-auto 三件套不复存在了,而 --full-auto 标志已被官方弃用。第二:在 workspace-write 下,网络访问默认是关的,所以一个需要 npm install 的循环会失败,且没有一条清晰的消息。
Cursor,项目里的 .cursor/cli.json(只有权限能在项目层配置):
{
"permissions": {
"allow": ["Read(**/*.ts)", "Write(src/**/*)", "Shell(npm test)"],
"deny": ["Shell(git push)", "Write(.env*)", "Write(package.json)"]
}
}
Cursor 自己对生产的推荐是"受限自主":agent 只编辑文件,而 git 操作和 PR 创建发生在一个独立的、确定性的工作流步骤里。这是个好建议,而且可以移植到任何其他工具。
第 3 步。一次可靠的手工运行
被跳过最多的一步,也是循环之后在生产里崩溃的主要原因。
在自动化任何东西之前,用你计划排期的精确措辞手工跑一遍这个任务。不是"大概这样",而是字面意义上那段文字。盯着 agent 在哪里漏了,然后去修 AGENTS.md、规则和任务文本,而不是修你的期望。
一个在这里需要你三次澄清的任务,会在自主循环里直接失败,静悄悄地,而且花的是你的预算。
第 4 步。一项技能:停止反复重新解释项目
技能是一个描述重复流程的文件:你如何给 CI 失败做分诊、你如何决定一个修复、你绝不该做什么。你写一次,agent 在判断任务匹配时就自己加载它。没有它,你在每个新会话里都要解释同样的东西。
Claude Code:.claude/skills/ci-triage/SKILL.md。Codex:.agents/skills/ci-triage/SKILL.md。格式相同,就是开放的 Agent Skills 标准。
---
name: ci-triage
description: Classify CI failures by root cause and draft fixes for the easy ones.
---
# CI Triage
## Classification rules
- env: missing secret, wrong variable -> flag for a human
- flake: passes on retry with no code change -> retry once, then file an issue
- bug: deterministic failure tied to a recent commit -> draft a fix
- dependency: failure after a version bump -> draft a rollback
- infra: timeout, OOM, runner -> escalate immediately
## Fix patterns
- Auth tests -> check src/auth/middleware.ts first
- DB tests -> verify the migration ran in the CI env
- E2E -> check UI selectors against the latest snapshot
## Never do
- Disable failing tests
- Change CI config without approval
- Touch src/billing/ or src/payments/
## State
After every run, update STATE.md: what was checked, how it was classified,
which PRs were opened, what was escalated.
注意"绝不要做"那一段。没有它,agent 迟早会得出结论:修一个失败测试最高效的方式是删掉它。技术上,套件确实变绿了。
一个能省下你半小时困惑的 Claude Code 细节:命令名来自目录名,而不是 frontmatter 里的 name 字段。一个 ci-triage 文件夹给你 /ci-triage,无论你在里面写什么。技术上没有任何字段是必需的,但永远写一个 description:那是 agent 决定要不要加载这个技能时读的东西。
Cursor 没有这种形式的技能;最接近的等价物是 .cursor/commands/*.md 里的自定义命令,以 /name 调用。
第 5 步。状态:循环的记忆
agent 会忘。文件不会。
每次 agent 运行都是一张白纸:它不记得昨天已经试过这个修复、而它没成功。解药是一个普通的文本文件,agent 在运行开始时读它,在运行结束时重写它。
根目录下的 STATE.md:
# Loop state: CI triage
## Last run
2026-07-10 03:30 UTC - 7 failures classified, 3 fixes, 4 escalated
## In progress
- fix-auth-token-refresh - green locally, awaiting CI
- fix-flaky-payment-webhook - retry pattern applied, monitoring
## Escalated to humans
- src/billing/refund.ts - failing three ways, root cause unclear
- ci/staging-runner - infra timeouts, not code
## Lessons learned
- 2026-07-09: PowerShell hits TLS 1.2 on this Windows runner. Use bash.
- 2026-07-08: tests/e2e/checkout needs the webhook secret in env. Skip if absent.
加上你上下文文件里的那行,把一堆运行变成一个循环:
## Session start
Read STATE.md first and pick up where the last run stopped.
At the end of the run, update STATE.md: what was done, what's next, what you learned.
"经验教训"那一节不是装饰。它是循环累积代码和测试里都不存在的东西的唯一地方:你环境的局部地雷。没有它,agent 每晚都踩上去,花的是你的预算。
第 6 步。循环本身
循环文本,loop.md:
Read STATE.md to see what was already tried.
Triage every failing test in the last build using the ci-triage skill rules.
For each failure: classify it, draft a fix for bugs and dependency issues,
escalate env and infra problems.
Apply the fixes. Run npm test and npm run lint.
Both return 0 -> open a PR.
Otherwise -> record the reason in STATE.md and stop.
Update STATE.md with everything done this run.
HARD STOP: 8 iterations maximum. On the limit, report state and exit.
三种运行方式:
# Claude Code
claude -p "$(cat loop.md)" \
--output-format stream-json --verbose \
--max-turns 20 --max-budget-usd 5 \
--dangerously-skip-permissions
# Codex CLI
codex exec "$(cat loop.md)" \
--sandbox workspace-write \
--ask-for-approval never \
--json
# Cursor CLI
agent -p "$(cat loop.md)" \
--output-format stream-json \
--force --model composer-2.5
三个陷阱,每一个都值得一个晚上的调试。
codex exec 默认只读运行。运行会成功、会报告、却什么都不改。你需要一个显式的 --sandbox workspace-write。
agent -p 不带 --force 不写任何文件。在这个模式下 Cursor 只提出变更。结尾是同样静默的空。
Claude Code 有用于 CI 的 --bare。它会跳过一切额外东西的自动发现(hooks、技能、插件、记忆),这样一次运行在任何机器上都完全一致;文档称它是脚本化调用的推荐模式。反讽的是,我们的循环用不了它:我们既需要技能,也需要 CLAUDE.md。等 CI 里的可复现性开始要紧时,记着它。
在 GitHub Actions 里:
name: CI Triage Loop
on:
workflow_run:
workflows: ["CI"]
types: [completed]
jobs:
triage:
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Read the loop
id: loop
run: |
{
echo 'text<<EOF'
cat loop.md
echo EOF
} >> "$GITHUB_OUTPUT"
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: ${{ steps.loop.outputs.text }}
claude_args: |
--max-turns 20
--max-budget-usd 5
--model claude-sonnet-5
OpenAI 的等价物是 openai/codex-action@v1,带 prompt-file、model、effort 和 sandbox 输入,以及一个 final-message 输出。Cursor 没有官方 action,但它确实有一个官方示例:用 curl 装 CLI,把 Cursor 的 bin 目录加进 runner 的 PATH,然后调用 agent -p。
到这一步,你已经有了一个能跑的循环。接下来的两步,是把一个你敢托付过夜的循环,和一个某天早上兴高采烈地报告"它修好了所有测试"(通过删掉它们)的循环区分开的东西。
第 7 步。干活的人不能是检查的人
简单前提:刚写出一个修复的模型,永远不会说它坏。它已经为它投入过推理了;它对它有感情。让它审自己的活,它会找到办法给自己放行。
这正是新闻编辑部有文字编辑、而不是作者自己校对自己稿子的原因;也是银行让支付由创建支付之外的人来批准的原因。它之所以奏效,只有一个原因:第二方脑子里没有第一方的历史。他们只看到结果。
用 agent 的话,你通过一个辅助 agent(在文档里,一个 subagent)得到这个。辅助 agent 是一个有自己干净上下文的独立 agent:它从没见过修复被写出来,没参与任何推理,只收到测试要求和测试输出。你用一个纯文本文件定义它。
Claude Code,.claude/agents/verifier.md。--- 之间的块是设置;下面的是辅助 agent 的指令:
---
name: verifier
description: Verifies a fix against the test requirements. Never sees the implementation.
tools: Read, Glob, Grep, Bash
model: opus
---
You are a strict verifier. You get the test requirements and the test output.
You do not look at or discuss the implementation.
Tests pass -> approve. Tests fail -> reject, listing the failures.
You have no other opinion.
model: opus 那行不是装饰:让 worker 跑在更便宜的模型上,把闸门放在更强的模型上。默认情况下辅助 agent 继承主会话的模型,所以如果你想要那个拆分,要明确说出来。
Codex,.codex/agents/verifier.toml:
name = "verifier"
description = "Strict, read-only verifier."
model_reasoning_effort = "high"
sandbox_mode = "read-only"
developer_instructions = """
Verify the fix against test requirements and test output only.
Do not read the implementation. Tests green -> approve, otherwise reject.
"""
这里要紧的那行是 sandbox_mode = "read-only"。它意味着这个辅助 agent 在物理上被禁止写任何东西。它只能读。否则迟早会发生一件荒谬的事:验证者看到一个失败的测试,就"好心"地自己"修"了它,而不是拒绝这个工作。
Cursor 没有辅助 agent。最接近的近似,是一个不带 --force 的独立 agent -p --mode ask 运行:在那个模式下 agent 根本不能写文件,所以它能做的只有给个意见。
第 8 步。写在散文里的规则,和写在代码里的规则,不是一回事
你在 AGENTS.md 里写了:"绝不碰 src/billing/"。到一个长会话的第 50 条消息,那行字大约就一文不值了。模型不是违抗你;它只是不再记得了。
散文里的指令是一个请求。你要的是一个不依赖 agent 记得什么的闸门。
那些闸门叫 hooks。一个 hook 是你的脚本,工具会在 agent 即将做某事时自动运行它:跑一条命令、写一个文件、结束会话。脚本看着正在发生的事,回答:允许还是阻止。它不是用文字回答,而是用一个退出时的数字(叫退出码):0 表示"行,继续",2 表示"停,不允许"。Cursor 和 Claude Code 对 2 的处理是一样的;Cursor 是特意做成兼容的。
这个区别不是表面功夫。"请别进那间屋子"和"门上一把锁"不是一回事,而到第 50 条消息,agent 需要的是那把锁。
在 Cursor 里,hooks 放在 .cursor/hooks.json。这里是一个每次 agent 编辑文件都会触发的闸门:
{
"hooks": {
"afterFileEdit": [
{ "command": "./.cursor/hooks/guard-billing.sh" }
]
}
}
在那个 guard 脚本里你检查文件路径,如果它在受保护的目录里,就以退出码 2 退出。这个编辑不会落地,无论 agent 怎么想。
Claude Code 在不同名字下有同样的事件:PreToolUse 在 agent 做某事之前触发(可以否决它),PostToolUse 紧随其后,而 Stop 在 agent 认为它完成时触发。
最后一个最有用。把 Stop 挂到一个"测试确实绿了"的检查上,agent 就无法在测试绿之前结束会话。这和那句平淡的指令"永远跑测试"的区别在于:指令可以被忘掉,闸门不能。
Codex 没有 hooks。它的闸门是另一种:由 sandbox_mode 配置的沙箱本身,外加 .git 和 .codex 永远写保护这一事实——即使在 workspace-write 下也是。
烧钱的失败模式
虚假的"完成"。agent 半路宣布工作完成、退出,循环继续转、继续花钱。解药不是一句礼貌的请求,而是一个由别人评估的停止条件:
DONE WHEN: npm test returns 0 AND npm run lint returns 0.
Not "when the tests look fine." Not "when most of them pass."
A separate run verifies this, not the agent's own judgment.
Hard limit: 8 iterations, then report state and stop.
目标漂移。在长会话上,早期的约束会消解:第 3 条消息里的"别碰 src/billing/"到第 47 条消息已不复存在。解药是:约束住在一个会被重读的文件里(CLAUDE.md、AGENTS.md、一条带 alwaysApply: true 的 Cursor 规则),外加第 8 步那个根本不会让写入落在禁区的 hook。
自我偏袒偏差。制造者验证自己,永远通过。解药是第 7 步的拆分:验证者只看到需求和测试输出,看不到实现,而且不持写权限。
agent 式懒惰。对含糊成功标准的"够好了"。解药和第一个一样:完成的唯一定义是退出码,不是一个形容词。
起飞前检查清单
文件都到位了
上下文文件已创建:CLAUDE.md、AGENTS.md 或 .cursor/rules
SKILL.md 已写,带一个真实的 description 和一个"绝不要做"节
STATE.md 已创建,且读写它已在上下文文件里声明
loop.md 已写,其停止条件是一个退出码,而不是一个形容词
共享仓库:AGENTS.md 已通过 import 或 symlink 接进 Claude Code
运行会真正做点什么
一次用循环的精确措辞做的手工运行,无需你的提示就完成
Codex:sandbox_mode = workspace-write,否则运行什么都不写
Cursor:自主模式下设了 --force,否则运行什么都不写
Codex:network_access = true,如果循环需要装任何东西
刹车是灵的
权限已设,且 deny 列表覆盖 .env 和密钥
迭代和预算的硬限制:--max-turns、--max-budget-usd
验证者是一个无写权限的独立辅助 agent
不可逆动作(PR、deploy、git push)在 agent 之外
每一条没勾上的行,要么是一次静默失败,要么是一张什么都没换来的 token 账单。
60 秒回顾
一个循环不关乎模型,而关乎闸门。发现 -> 执行 -> 验证 -> 迭代 -> 停止,其中"验证"由工作作者之外的人来做,而"停止"由退出码来定义。
五个文件你就跑起来了:上下文文件、带权限的配置、SKILL.md、STATE.md、loop.md。然后在 CI 里或按计划跑 claude -p、codex exec 或 agent -p。
会吃掉你第一个晚上的三个陷阱:Claude Code 不读 AGENTS.md,codex exec 默认什么都不写,而 agent -p 不带 --force 也什么都不写。
最后一件事
你的第一个循环几乎从不会干净出炉。它踉跄、它超支、它停错地方。这没关系:一个你亲手搭起、亲手修好的循环,教给你的东西胜过一百个完美的提示词。
从你每周都在做、并悄悄怨恨的那一个任务开始。给它一个闸门、一份记忆和一个硬限制。让它在你睡觉时跑。
然后明天,搭下一个。
就那样搭,像一个打算继续当工程师的人那样搭。两个开发者可以跑同一个循环:一个用来更快地穿过他深懂的工作,另一个用来彻底避开理解它。循环不知道这区别。你知道。
如果这是你的菜,我在 Telegram 上更深入地写这些系统:
-> https://t.me/shmidtai
关于 agentic 工作里什么真正站得住、什么听起来优雅却在第二次迭代就散架的简短笔记。不炒作,只有能用的例子。
如果你是想构建、而不只是按下"go",那就来。
提示词
DONE WHEN: npm test returns 0 AND npm run lint returns 0.
Not "when the tests look fine." Not "when most of them pass."
A separate run verifies this, not the agent's own judgment.
Hard limit: 8 iterations, then report state and stop.
{
"model": "claude-sonnet-5",
"permissions": {
"allow": ["Bash(npm run lint)", "Bash(npm run test *)", "Edit"],
"ask": ["Bash(git push *)"],
"deny": ["Read(./.env)", "Read(./secrets/**)", "Bash(curl *)"],
"defaultMode": "acceptEdits"
}
}
# Loop state: CI triage
## Last run
2026-07-10 03:30 UTC - 7 failures classified, 3 fixes, 4 escalated
## In progress
- fix-auth-token-refresh - green locally, awaiting CI
- fix-flaky-payment-webhook - retry pattern applied, monitoring
## Escalated to humans
- src/billing/refund.ts - failing three ways, root cause unclear
- ci/staging-runner - infra timeouts, not code
## Lessons learned
- 2026-07-09: PowerShell hits TLS 1.2 on this Windows runner. Use bash.
- 2026-07-08: tests/e2e/checkout needs the webhook secret in env. Skip if absent.
Read STATE.md to see what was already tried.
Triage every failing test in the last build using the ci-triage skill rules.
For each failure: classify it, draft a fix for bugs and dependency issues,
escalate env and infra problems.
Apply the fixes. Run npm test and npm run lint.
Both return 0 -> open a PR.
Otherwise -> record the reason in STATE.md and stop.
Update STATE.md with everything done this run.
HARD STOP: 8 iterations maximum. On the limit, report state and exit.
model = "gpt-5.6" # GPT-5.6 shipped July 9, 2026
model_reasoning_effort = "high" # minimal | low | medium | high | xhigh
approval_policy = "on-request" # untrusted | on-request | never
sandbox_mode = "workspace-write" # read-only | workspace-write | danger-full-access
[sandbox_workspace_write]
network_access = true # network is OFF by default in the sandbox
# Claude Code
claude -p "$(cat loop.md)" \
--output-format stream-json --verbose \
--max-turns 20 --max-budget-usd 5 \
--dangerously-skip-permissions
# Codex CLI
codex exec "$(cat loop.md)" \
--sandbox workspace-write \
--ask-for-approval never \
--json
# Cursor CLI
agent -p "$(cat loop.md)" \
--output-format stream-json \
--force --model composer-2.5
curl -fsSL https://claude.ai/install.sh | bash # Claude Code -> binary: claude
curl -fsSL https://chatgpt.com/codex/install.sh | sh # Codex CLI -> binary: codex
curl https://cursor.com/install -fsS | bash # Cursor CLI -> binary: agent
# AGENTS.md
## Architecture
- src/api/ - Express routes
- src/services/ - business logic
- src/db/ - models (PostgreSQL via Prisma)
- tests/ - Jest suite
## Key commands
- npm test - full test suite
- npm run lint - ESLint
- npm run typecheck - tsc --noEmit
## Rules
- Never touch src/billing/ or src/auth/ without human approval
- Always run tests before marking a task complete
- Errors only through the pattern in src/utils/errors.ts
{
"hooks": {
"afterFileEdit": [
{ "command": "./.cursor/hooks/guard-billing.sh" }
]
}
}
ln -s AGENTS.md CLAUDE.md
---
name: ci-triage
description: Classify CI failures by root cause and draft fixes for the easy ones.
---
# CI Triage
## Classification rules
- env: missing secret, wrong variable -> flag for a human
- flake: passes on retry with no code change -> retry once, then file an issue
- bug: deterministic failure tied to a recent commit -> draft a fix
- dependency: failure after a version bump -> draft a rollback
- infra: timeout, OOM, runner -> escalate immediately
## Fix patterns
- Auth tests -> check src/auth/middleware.ts first
- DB tests -> verify the migration ran in the CI env
- E2E -> check UI selectors against the latest snapshot
## Never do
- Disable failing tests
- Change CI config without approval
- Touch src/billing/ or src/payments/
## State
After every run, update STATE.md: what was checked, how it was classified,
which PRs were opened, what was escalated.
name: CI Triage Loop
on:
workflow_run:
workflows: ["CI"]
types: [completed]
jobs:
triage:
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Read the loop
id: loop
run: |
{
echo 'text<<EOF'
cat loop.md
echo EOF
} >> "$GITHUB_OUTPUT"
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: ${{ steps.loop.outputs.text }}
claude_args: |
--max-turns 20
--max-budget-usd 5
--model claude-sonnet-5
{
"permissions": {
"allow": ["Read(**/*.ts)", "Write(src/**/*)", "Shell(npm test)"],
"deny": ["Shell(git push)", "Write(.env*)", "Write(package.json)"]
}
}
## Session start
Read STATE.md first and pick up where the last run stopped.
At the end of the run, update STATE.md: what was done, what's next, what you learned.
@AGENTS.md
## Claude Code specifics
Use plan mode for changes under src/billing/.
name = "verifier"
description = "Strict, read-only verifier."
model_reasoning_effort = "high"
sandbox_mode = "read-only"
developer_instructions = """
Verify the fix against test requirements and test output only.
Do not read the implementation. Tests green -> approve, otherwise reject.
"""
---
name: verifier
description: Verifies a fix against the test requirements. Never sees the implementation.
tools: Read, Glob, Grep, Bash
model: opus
---
You are a strict verifier. You get the test requirements and the test output.
You do not look at or discuss the implementation.
Tests pass -> approve. Tests fail -> reject, listing the failures.
You have no other opinion.
链接
t.me/shmidtai
标签:# X # Claude # AI # 循环 # 自动化 # 指南 # Chatgpt # Fable # Sonnet 相关文章 别再自己做工作了:构建永不休眠的 AI 循环 2026 手册 AI 自动化 Claude 循环
原文参考:https://maxed.wiki/posts/stop-prompting-start-looping/ (Maxed.wiki,本页为站内中文整理)