构建生产级自主工作流
本文介绍了从手动提示到设计AI编码循环的转变,详细说明了如何通过Slate工具构建生产级的AI自主工作流。


两位在世最资深的人工智能工程师上个月说了同样的话。
Peter Steinberger,OpenClaw 的创始人,现在在 OpenAI:
"你不再应该给编程智能体写提示词了。你应该设计循环,让循环来给你的智能体发提示。"
Boris Cherny,Anthropic 旗下 Claude Code 的负责人:
"我不再给 Claude 发提示词了。我有循环在运行,这些循环给 Claude 发提示并决定该做什么。我的工作是写循环。"
大多数人读到这些,会想:这到底是什么意思?
更重要的是:我要怎么构建一个这样的循环?
这篇文章会直接告诉你方法。
没有脱离代码的理论。没有脱离上下文的代码。真实步骤。真实命令。复制后运行。

Slate 在一个真实的迁移任务中编排 GPT-5.6、Claude 和专门的子智能体。模型变得更聪明了。更大的变化是,像 Slate 这样的工具终于能让这些模型持续忙碌,而不是等待人类提示。
大多数人使用 AI 的方式已经过时了
编写提示词。等待。读取输出。手动修正。再写另一个提示词。
你本身就是那个循环。
每一步都要经过你。AI 在等待。你来决定。AI 再次等待。
你一旦停下,一切就都停下了。
在 2026 年,发展最快的构建者并不是在写更好的提示词。
他们是在构建一个系统,让系统自己去发提示。
杠杆点已经转移了。
从 输入提示词 → 转向 设计循环。

GPT-5.6 带来了什么变化?
GPT-5.6 并没有改变对循环的需求。
它提升了循环的价值。
模型越好,在两次提示之间让它闲置就越昂贵。
在终端工作流中,GPT-5.6 在以下方面明显更强:
→ 理解大型代码库 → 保持实现的一致性 → 遵循多步骤计划 → 从失败尝试中恢复 → 作为严格的验证者
结果不是"更好的提示"。
而是每次任务中人类干预更少。
循环到底是什么
简单定义:
一个提示词只回答一次就停止了。
一个循环会持续工作,直到任务真正完成。
不是直到它生成答案。
而是直到它达到一个经过验证的结果。
每一个正经的 AI 智能体都在运行同样的底层循环:
→ 发现 — 需要做什么? → 执行 — 做工作 → 验证 — 真的成功了吗? → 迭代 — 没做完?修复并重复 → 停止 — 条件满足,或者达到硬性限制
Claude Code、Cursor、Codex。
底层,它们都在运行这个循环。
提示词和循环之间的区别不在于模型。
而在于是否有东西检查工作,并持续进行直到通过。

4 条件测试 — 在构建任何东西之前先运行这个
大多数循环在这里失败。
一个循环只有在 4 个条件都成立时,才值得投入设置成本。
只要缺一个,循环的成本就会超过它的回报。
-
任务重复。 至少每周一次。一次性的任务用一个好提示就能更好地完成。
-
验证是自动化的。 必须能在没有你在场的情况下判定工作失败。测试。Linters。构建。类型检查。没有门禁 = 智能体在给自己批改作业。
-
你的 Token 预算能吸收浪费。 循环在每次迭代中都会重新读取完整的上下文。它们会重试、探索、消耗 Token,不管运行是否产生结果。这是没人提及的成本。
-
"完成"是客观的。 测试通过或不通过。构建编译成功或失败。不是"看着不错"。如果完成需要人的判断,就保持手动。
所有 4 个都通过 → 构建循环。
任何一个不通过 → 改用提示词。
诚实地说:大多数开发者目前还不需要重型循环。每个人都能用的是一个简单的循环。我们很快就会构建一个。
安装 Slate
Slate 是一个 AI 编码智能体,专为此而构建——在你的终端中运行长时间、并行、多步骤的任务。
由 RandomLabs 构建。第一个专门为群集编排而构建的智能体。
它与 Claude Code 或 Cursor 的不同之处:
→ 自动为每个步骤选择正确的模型。用 Claude 做计划,用另一个做搜索,用 Codex 执行——Slate 来决定。 → 同时在你的代码库中运行并行的子智能体。 → 在长达数小时的会话中管理自己的上下文。 → 与你一起工作——不只是为你工作。
一行安装:
npm i -g @randomlabs/slate
导航到你的项目并启动:
cd /path/to/your/project
slate
这将打开 Slate TUI——一个终端界面,你可以在其中给它任务并观察它工作。

步骤 1 — 设置你的工作区
在 Slate 能在你的项目上运行循环之前,它需要理解你的代码库。
在你的项目根目录创建一个 AGENTS.md 文件。这是 Slate 在每次会话开始时读取的上下文。
## AGENTS.md
### 这个代码库是做什么的
[项目的一段描述]
### 架构
- src/api/ — Express API 路由
- src/services/ — 业务逻辑
- src/db/ — 数据库模型 (PostgreSQL via Prisma)
- tests/ — Jest 测试套件
### 关键命令
- npm test — 运行完整的测试套件
- npm run build — TypeScript 编译
- npm run lint — ESLint 检查
- npm run typecheck — tsc --noEmit
### 规则
- 未经人工批准,**绝不**修改 src/billing/ 或 src/auth/
- 在标记任何任务完成前,**始终**运行测试
- 使用 src/utils/errors.ts 中已有的错误处理模式
### 环境
- .env.slate 包含 Slate 需要的所有环境变量
Slate 会在启动时自动读取这个文件——不需要每次会话都粘贴。
在 Slate 内部添加你的工作目录:
/workspace add ./src
/workspace add ./tests
/workspace list
或者使用 @ 引用直接引用特定文件:
请检查 @src/api/routes.ts 并提出改进建议

步骤 2 — 配置 Slate
在你的项目根目录创建 slate.json 来控制 Slate 的行为。
{
"$schema": "https://randomlabs.ai/config.json",
"permission": {
"*": "allow",
"bash": "ask"
},
"models": {
"main": { "default": "anthropic/claude-opus-4.6" },
"subagent": { "default": "anthropic/claude-sonnet-4.6" },
"search": { "default": "anthropic/claude-haiku-4.5" },
"reasoning": { "default": "openai/gpt-5.6" }
}
}
它的作用:
→ "*": "allow" — Slate 可以无需每次询问就读写文件
→ "bash": "ask" — Slate 在运行 shell 命令之前会询问(在信任它之前保持此设置)
→ 模型配置 — 用便宜的快速模型做搜索,用昂贵的模型做主要推理
对于需要零提示的 CI 或自动化运行:
slate run "运行测试套件并修复任何失败" --dangerously-skip-permissions --output-format stream-json
步骤 3 — 你的第一个任务(还不是循环)
在构建循环之前,先确保一次手动运行是可靠的。
这是最常被跳过的一步。也是大多数循环在生产中失败的原因。
给 Slate 一个真实的任务:
请审查我整个代码库的架构。
创建一个 ARCH.md,包含:
- 当前结构
- 模块之间的依赖关系
- 3 个需要改进的地方
先看 @src/,然后看 @tests/
观察 Slate 工作。它会:
搜索你的文件 建立对架构的理解 起草 ARCH.md 在停止之前对照你的请求检查它
这本身已经是一个微循环——它在完成前会检查自己的输出。
对于一个更长的任务:
嘿 Slate,调研我的代码库中关于认证流程的部分,
然后为添加 OAuth2 支持制定一个计划。
确保你查看了 @src/auth/ 和 @src/api/routes.ts
Slate 返回一个计划。你在上面迭代:
不,不要添加一个新的认证提供者类。
让它遵循 src/auth/api-key.ts 中现有的 ApiKeyAuth 的相同模式。
批准计划。Slate 自主执行。

步骤 4 — 创建一个 Skill(让循环可复用)
Skill 是让你不必每次会话都重新解释项目的方式。
一次性写好。Slate 会在每次相关运行时都读取它。
创建文件夹结构:
mkdir -p .slate/skills/ci-triage
touch .slate/skills/ci-triage/SKILL.md
编写 skill:
---
name: "ci-triage"
description: "按根本原因分类 CI 失败,并为简单的失败草拟修复方案。"
---
## CI Triage Skill
### 我做什么
当 CI 运行失败时,我会:
1. 读取测试输出
2. 分类失败类型:环境问题 / 不稳定测试 / 真实 bug / 依赖升级 / 基础设施
3. 为 bug 和依赖问题草拟修复方案
4. 将环境和基础设施问题升级给人类
### 分类规则
- 环境:缺少密钥、环境变量错误 → 标记给人类
- 不稳定:不修改代码重试后通过 → 重试一次,然后提交 issue
- bug:与最近提交相关的确定性失败 → 草拟修复方案
- 依赖:与版本升级相关的失败 → 草拟回滚 PR
- 基础设施:超时、OOM、运行器问题 → 立即升级
### 修复模式
- 认证测试失败 → 先检查 src/auth/middleware.ts
- 数据库测试失败 → 验证迁移是否在 CI 环境中运行
- E2E 失败 → 对照最新快照检查 UI 选择器
### 绝对不做
- 禁用失败的测试
- 未经询问修改 CI 配置
- 触碰 src/billing/ 或 src/payments/
### 状态
每次运行后更新 STATE.md:
- 检查的文件
- 进行的分类
- 打开的 PR
- 升级的项目
在 Slate 内部列出可用的 skill:
/skills
手动激活一个:
@ci-triage 请分类今天失败的测试
或者当 Slate 认为它们与当前任务相关时,会自动激活 skill。
步骤 5 — 添加状态(循环的记忆)
智能体会忘记。
文件不会。
在项目根目录创建 STATE.md:
## 循环状态 — CI 分类
### 上次运行
2026-06-28 03:30 UTC — 7 个失败被分类,3 个修复草拟,4 个被升级
### 进行中
- claude/fix-auth-token-refresh — 测试本地通过,等待 CI
- claude/fix-flaky-payment-webhook — 已应用重试模式,正在监控
### 已完成
- claude/bump-axios-1.7.4 → 已合并 (CI 绿)
- claude/lint-fix-pass-june-28 → 已合并
### 升级给人类
- src/billing/refund.ts — 测试以3种方式失败,根本原因不明确
- ci/staging-runner — 基础设施超时,非代码问题
### 经验教训
- 2026-06-27: 在此 Windows 运行器上 PowerShell 遇到 TLS 1.2 问题。使用 bash。
- 2026-06-26: tests/e2e/checkout 需要在环境中设置 Stripe webhook 密钥。如缺失则跳过。
告诉 Slate 在每次会话开始时使用它,方法是在 AGENTS.md 中添加:
### 会话开始
始终先读取 STATE.md。从上次运行停止的地方继续。
每次运行结束时更新 STATE.md,记录完成了什么以及下一步是什么。
没有状态:每次运行都从零开始。
有了状态:每次运行都接续并叠加在最后一次运行之上。
步骤 6 — 构建真正的循环
现在你已经有了:
→ 工作区设置好了 (AGENTS.md) → 配置设置好了 (slate.json) → 一次可靠的单次手动运行已验证了 → 写了一个 skill (ci-triage) → 创建了状态文件 (STATE.md)
是时候把它包装成一个真正的循环了。
选项 A:队列文件循环(最简单)
创建 loop.md:
读取 STATE.md 以了解已经尝试过什么。
对所有上次构建中失败的测试运行 CI 分类 skill。
对于每个失败:
- 使用 ci-triage skill 规则进行分类
- 为 bug 和依赖问题草拟修复方案
- 将环境和基础设施问题升级
运行修复。检查测试是否通过。
如果测试通过 → 打开 PR。
如果测试仍然失败 → 记录在 STATE.md 中并停止。
更新 STATE.md,记录本次运行所做的一切。
硬性停止:最多 8 次尝试。达到限制时,报告当前状态。
运行它:
slate --queue loop.md
Slate 会读取队列文件并依次运行每个块作为排队的消息。
选项 B:无头/CI 循环(自动化)
在 GitHub Action 或 cron 任务中非交互式运行:
slate run "$(cat loop.md)" --output-format stream-json --dangerously-skip-permissions
在 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: Install Slate
run: npm i -g @randomlabs/slate
- name: Run triage loop
env:
SLATE_API_KEY: ${{ secrets.SLATE_API_KEY }}
run: |
slate run "$(cat loop.md)" \
--output-format stream-json \
--dangerously-skip-permissions \
--workspace ./src \
--workspace ./tests
现在每次 CI 失败都会自动触发分类循环。
在升级之前不需要人类参与。

步骤 7 — 添加子智能体(制造者-检查者分离)
任何循环结构改进中唯一最重要的一点。
永远不要让同一个智能体给自己批改作业。
写修复方案的模型作为评分者太慷慨了。
在 Slate 中,你可以为不同的角色设置不同的模型:
{
"models": {
"main": { "default": "anthropic/claude-opus-4.6" },
"subagent": { "default": "anthropic/claude-sonnet-4.6" },
"search": { "default": "anthropic/claude-haiku-4.5" }
}
}
然后编写你的任务,让 Slate 自然地使用这种分离:
请修复失败的认证测试。
步骤 1:让一个搜索智能体探索 src/auth/ 以理解当前实现。
步骤 2:让另一个独立的智能体基于发现的结果实现修复。
步骤 3:让第三个智能体对照原始测试要求验证修复——
这个智能体**不应该**看到实现过程。
步骤 4:只有验证者批准时,才打开 PR。
Slate 会自动编排子智能体。
搜索智能体使用快速便宜的模型。实现智能体使用更强的模型。验证者使用严格的模型,无法访问制造者的推理过程。
这种分离就是为什么 Slate 可以在一个任务上运行 5 个并行的子智能体——每个都专业化、相互隔离。

步骤 8 — 状态循环模式(用于长时间运行的任务)
对于持续数小时或数天的任务,在你的任务提示中使用这种模式:
你正在运行一个多会话循环。
目标:将所有 Express 路由迁移到新的 ApiError 模式。
在 STATE.md 中跟踪进度。
**每次会话开始:**
1. 读取 STATE.md
2. 找到 "剩余路由" 中的第一个未完成项
3. 只做这一项
**每次会话结束:**
1. 将已完成的项移到 STATE.md 的 "已完成路由"
2. 在 "阻塞项" 中记录任何阻塞原因
3. 更新 "上次运行" 时间戳
4. 干净地停止
STATE.md 格式:
---
### 已完成路由
- [x] /api/users (2026-06-27)
- [x] /api/auth/login (2026-06-28)
### 剩余路由
- [ ] /api/payments/checkout
- [ ] /api/payments/refund
- [ ] /api/admin/users
### 阻塞项
- /api/payments/refund — 需要人工审核 (涉及计费逻辑)
### 上次运行
2026-06-28 14:30 UTC
---
**硬性规则:**
- 未经人工批准,**绝不**触碰 src/billing/
- 每次路由迁移后**始终**运行测试
- 每次会话只完成**一个**路由后停止
每天早上运行:
slate --continue "$(cat loop.md)"
--continue 会接续最近一次的会话,而不是从头开始。
每天,多一条路由。STATE.md 跟踪一切。
循环会从它停止的地方精确地继续。
步骤 9 — 为你最常用的循环创建自定义命令
在 slate.json 中添加自定义斜杠命令,这样你的循环总是只需一次按键:
{
"command": {
"triage": {
"description": "运行 CI 分类循环",
"template": "读取 STATE.md。对所有失败的测试运行 ci-triage skill。完成后更新 STATE.md。",
"agent": "build"
},
"review": {
"description": "检查文件正确性",
"template": "检查 @$ARGUMENTS 的正确性、边界情况和与周围代码的一致性。"
},
"migrate": {
"description": "迁移一个路由到 ApiError 模式",
"template": "读取 STATE.md。将下一个未完成的路由迁移到 ApiError 模式。运行测试。更新 STATE.md。"
}
}
}
现在在 Slate 内部:
/triage
/review src/api/payments.ts
/migrate
每个都会立即运行你预先写好的循环提示。
你现在就可以运行的 3 个完整循环
循环 1:CI 失败分类(我们刚刚构建的)
何时运行:每次 CI 失败 做什么:分类 → 修复简单的 → 升级难的 → 打开 PR 状态:STATE.md 门禁:测试通过 设置时间:30 分钟
## 触发方式
slate run "$(cat loop.md)" --dangerously-skip-permissions --output-format stream-json
## 或在 GitHub Actions 中 — 参见上述步骤 6
循环 2:晨间简报
何时运行:每个工作日上午 7 点(cron 任务) 做什么:扫描过去 24 小时的提交、PR 和打开的 issue → 写一个 5 点简报 → 发布到 Slack
## 晨间简报的 loop.md
cat > morning-brief-loop.md << 'EOF'
读取过去 24 小时内的:
- git log --since="24 hours ago" --oneline
- 处于草稿或审核状态的开放 PR
- 过去 24 小时内打开或更新的 GitHub Issue
写一份晨间简报:
- 发生的 3 件最重要的事
- 今天需要关注的 2 件事
- 1 件可能阻碍某人的事
控制在 120 单词以内。发布到 #engineering Slack 频道。
EOF
## 使用 cron 按计划运行
0 7 * * 1-5 slate run "$(cat morning-brief-loop.md)" --dangerously-skip-permissions
循环 3:依赖升级循环
何时运行:每周一 做什么:扫描过时的包 → 测试兼容性 → 为安全的升级打开 PR
cat > deps-loop.md << 'EOF'
读取 STATE.md。
运行:npm outdated
对于每个过时的包:
1. 检查版本升级是主版本(破坏性)还是次版本/补丁(安全)
2. 对于次版本/补丁:更新包,运行 npm test
3. 如果测试通过:打开 PR
4. 如果测试失败:在 STATE.md 中记录为 "需要人工审查"
5. 对于主版本升级:总是升级给人类
硬性规则:
- 一次循环中最多升级 5 个包
- 绝不在 "peer dependencies" 部分升级包
- 每次升级后**始终**运行完整的测试套件,而不仅仅是相关测试
更新 STATE.md,记录升级了什么以及什么被升级了。
EOF
## 每周一运行
0 9 * * 1 slate run "$(cat deps-loop.md)" --dangerously-skip-permissions

会花钱的故障模式
在计划任何东西之前要了解这些。
Ralph Wiggum 循环
智能体在半成品上宣布完成。
提前退出。循环继续消耗。悄无声息。
修复:由一个全新的模型检查的硬性停止条件。
停止条件:tests/auth/ 中的所有测试都通过 并且 lint 返回 0。
使用单独的检查运行验证,而不是智能体自己的判断。
硬性限制:8 次迭代。达到限制时:报告状态并停止。
目标漂移
在长时间的会话中,早期的约束会消失。
"永不触碰 src/billing/" 从第 3 条消息到第 47 条消息已经消失。
修复:添加一个 VISION.md,让 Slate 在每次会话开始时重新读取。
## VISION.md — 在每次会话开始时读取
### 核心目标
将所有 Express 路由迁移到 ApiError 模式。
### 硬性约束(绝不能违反)
- 未经人工批准,绝**不**触碰 src/billing/
- 绝**不**禁用失败的测试
- 在打开任何 PR 之前,**始终**运行完整的测试套件
### 当前优先级
src/api/payments/ 中的路由 — 要格外小心处理
自我偏好偏差
制造者给自己批改作业。总是给自己通过。
修复:验证者子智能体完全无法访问制造者的推理过程。
明确地告诉 Slate:
验证者智能体**不应**看到实现智能体的工作。
它应该只看到:原始的测试要求和测试输出。
如果测试通过 → 批准。如果测试失败 → 拒绝。别无其他意见。
智能体的懒惰
循环在部分完成时称任务 "完成得差不多"。
特别是在模糊的成功标准下。
修复:仅使用客观的停止条件。
完成条件:npm test 返回退出码 0 并且 npm run lint 返回退出码 0。
不是 "测试看起来不错。" 不是 "大多数测试通过了。"
两个命令都返回退出码 0。这是唯一的完成标准。
那些重要的 Slate 特有技巧
一些在实践中让 Slate 区别于其他智能体的东西。
在它工作时排队消息
Slate 正在运行一个长时间任务。你想到了一些重要的事情。
按 Tab 键对消息进行排队——它会在当前任务完成后运行,不会打断它。
[Slate 正在处理迁移任务...]
你:对了,确保新模式也能处理 userId 为 null 的情况
[Tab — 已排队]
[Slate 完成当前步骤,然后读取你排队的消息]
中途调整方向
如果 Slate 走错了方向,你不需要停止它:
[Slate 正在实现修复的途中...]
你:等等——不要为此添加新类。使用 src/utils/errors.ts 中已有的 BaseError
[Enter — 立即调整方向]
Slate:明白,切换到使用 BaseError...
使用 /enter-mode-next 在 调整/排队/中断 模式之间切换。
直接使用 Shell 命令
在 Slate 会话内部运行命令,无需切换到另一个终端:
!npm test # 运行测试并将输出发送到 Slate
!git diff HEAD # 检查发生了什么变化
!git status # 查看当前状态
Slate 读取输出并将其用于下一步行动。
团队设置的服务器模式
将 Slate 作为服务器运行,并从多个终端连接到它:
## 终端 1 — 启动服务器
slate serve --port 7777
## 终端 2 — 连接 TUI
slate attach http://localhost:7777 --dir /path/to/project
对于与 Slate 结对编程或在其上远程机器上运行很有用。
完整设置清单
在运行你的第一个真正的循环之前:
□ npm i -g @randomlabs/slate 已安装
□ 已创建 AGENTS.md,包含项目概述、命令、规则
□ 已创建 slate.json,包含权限和模型配置
□ 已完成一次手动运行并验证可靠
□ 已为第一个重复任务编写 SKILL.md
□ 已创建 STATE.md 并在 AGENTS.md 中引用
□ 已编写 loop.md,包含明确的停止条件
□ 迭代次数硬性限制(从 8 次最多开始)
□ 验证者**不**与制造者是同一个智能体
□ 对任何不可逆操作(PR、部署)设置人工审核关卡
在计划任何东西之前,检查每一项。
跳过一个,循环要么静默失败,要么白白向你收费。
获取更多循环灵感
一旦你理解了这个模式,瓶颈就从 "如何构建一个循环" 转变为 "我下一步应该构建什么循环"。
signals.forwardfuture.com/loop-library 上的 Forward Future 循环库是一个很好的地方,可以浏览跨类别(内容、工程、运营、研究)实际运行的循环。
当你在一个地方看到 20 个工作中的循环时,你就不再会去想一次性提示词了。
令人不安的真相
两个构建者可以运行完全相同的循环,却得到相反的结果。
一个用它来在自己已经深入理解的工作上更快地推进。
另一个用它来避免理解工作本身。
循环并不知道区别。
你知道。
循环设计比提示工程更难——而不是更容易。
重点不是工作变得更容易了。
杠杆点转移了。
构建循环。
但要像一个有意继续做工程师的人那样去构建。
而不是仅仅按"开始"按钮的人。
而新的 GPT-5.6 并没有取代这个原则。如果有的话,它强化了这个原则。
前沿不再是谁能写出最聪明的提示词。
而是谁能围绕越来越强大的模型设计出最好的系统。
60 秒回顾
循环是什么:
→ 提示词 = 问题。循环 = 工作。 → 发现 → 执行 → 验证 → 迭代 → 停止
4 条件测试:
→ 任务重复 / 验证自动化 / 预算吸收浪费 / 完成是客观的
5 个设置步骤:
→ AGENTS.md → slate.json → 一次手动运行 → SKILL.md → STATE.md
然后包装:
→ loop.md 队列文件 或 无头 slate 在 CI 中运行
故障模式:
→ Ralph Wiggum(提前退出)/ 目标漂移(忘记约束)/ 自我偏好偏差(制造者=检查者)/ 智能体懒惰("差不多完成")
Slate 的优势:
→ 每个步骤自动选择模型 → 带隔离的并行子智能体 → 长时间会话管理 → 你的循环,你的设计
- 原文链接: x.com/sairahul1/status/2...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~