Loop Engineering 落地:用检查点把 Agent 循环变成可审计流水线

掘金近期关于 Loop Engineering 的文章把焦点从"写一条完美提示词"转向"设计一套能判断下一步的循环"。真正落地时,循环不能只是 while 语句,还需要明确状态、预算、工具权限、停止条件和证据。本文给出一个最小可运行的检查点模型,帮助团队把 Agent 从一次性对话改造成可恢复、可审计的工程流程。

1. 循环的核心不是重复调用模型

一个可控循环至少包含五个阶段:读取任务、规划一步、执行工具、验证结果、决定继续或停止。任何阶段都可能失败,所以每一轮都应该留下可序列化的状态:

ts 复制代码
type Step =
  | { kind: "plan"; text: string }
  | { kind: "tool"; name: string; args: Record<string, unknown> }
  | { kind: "verify"; command: string; passed: boolean; output: string };

type Checkpoint = {
  runId: string;
  revision: number;
  goal: string;
  steps: Step[];
  budgetUsed: number;
  status: "running" | "waiting-human" | "done" | "failed";
};

只保存最终答案是不够的。出了错,团队需要知道 Agent 在哪一轮拿到了什么证据、执行了什么命令,以及为什么继续。

2. 用有限状态机约束循环

不要让模型直接决定任意状态跳转。把允许的迁移写成白名单:

ts 复制代码
const transitions: Record<Checkpoint["status"], Checkpoint["status"][]> = {
  running: ["running", "waiting-human", "done", "failed"],
  "waiting-human": ["running", "failed"],
  done: [],
  failed: [],
};

function move(from: Checkpoint["status"], to: Checkpoint["status"]) {
  if (!transitions[from].includes(to)) {
    throw new Error(`illegal transition: ${from} -> ${to}`);
  }
}

例如删除文件、修改数据库、发布版本等高风险动作,必须先进入 waiting-human,由人工批准后才能回到 running。这比在提示词里写"请谨慎操作"可靠得多。

3. 每一轮只做一个可验证动作

循环容易失控,常见原因是一次让模型生成大量代码、运行多个命令,再用一句"看起来没问题"收尾。更稳妥的做法是把一轮限制为一个动作:

  1. 读取一个明确的输入或错误日志。
  2. 生成一个小修改计划。
  3. 执行一个工具调用。
  4. 运行一个确定性验证。
  5. 写入检查点,再决定下一轮。
ts 复制代码
async function runRound(cp: Checkpoint, model: Model, tools: Tools) {
  const plan = await model.plan({ goal: cp.goal, history: cp.steps.slice(-6) });
  cp.steps.push({ kind: "plan", text: plan.text });

  if (plan.risk === "high") {
    cp.status = "waiting-human";
    return cp;
  }

  const result = await tools.execute(plan.tool);
  cp.steps.push({ kind: "tool", name: plan.tool.name, args: plan.tool.args });
  const check = await tools.verify(plan.verifyCommand);
  cp.steps.push({ kind: "verify", command: plan.verifyCommand, passed: check.ok, output: check.output });
  cp.revision += 1;
  return cp;
}

history.slice(-6) 不是固定最佳值,只是为了防止上下文无限增长。生产环境应按 token 预算和任务阶段动态选择历史。

4. 停止条件必须独立于模型自述

"已经完成"不能作为验收证据。停止条件应该由代码检查:

  • 测试命令退出码为 0。
  • 类型检查和 lint 没有新增错误。
  • 变更文件在允许目录内。
  • 关键接口返回符合 schema。
  • 预算未超限,且没有未处理的高风险动作。
ts 复制代码
function canFinish(cp: Checkpoint, changedFiles: string[], checks: boolean[]) {
  const allowed = changedFiles.every(f => f.startsWith("src/") || f.startsWith("tests/"));
  return cp.status === "running"
    && allowed
    && checks.every(Boolean)
    && cp.budgetUsed < 100;
}

如果验证失败,下一轮应携带失败输出和差异摘要,而不是把整个仓库重新塞给模型。这样既节省预算,也降低模型反复改动无关文件的概率。

5. 接入层也要能替换

循环系统通常需要在不同模型之间切换。可以把提供方抽象成最小接口:

ts 复制代码
interface Model {
  plan(input: { goal: string; history: Step[] }): Promise<{
    text: string;
    risk: "low" | "high";
    tool: { name: string; args: Record<string, unknown> };
    verifyCommand: string;
  }>;
}

如果团队评估统一的多模型接入点,HaerAPI 公开首页自述可通过一个密钥接入 Claude、GPT、Gemini 等模型,并展示订阅转 API、会话保持和按量计费。它可以放在实验环境的提供方适配器后面,但不能据此推断所有模型、协议或计费细节都满足你的任务。

上线前应独立核验:模型列表和版本、流式/工具调用兼容性、限额与错误码、日志和数据处理、会话保持语义、服务条款及退出方案。保留直连实现和配置开关,避免把循环状态绑定到单一入口。

6. 让循环可回放、可审计

每个检查点建议包含:输入摘要哈希、模型标识、提示模板版本、工具参数、命令输出摘要、人工批准人和时间。敏感内容可以脱敏,但不要删除决定性证据。

回放时只重放纯函数和验证步骤;真实写操作默认使用模拟工具。这样可以复现"为什么进入下一轮",又不会在调试时再次修改生产资源。

总结

Loop Engineering 的价值不在于让 Agent 无限运行,而在于让每一轮都小、可验证、可暂停。有限状态机约束权限,检查点保存证据,独立验收决定停止,提供方适配器保证可替换。做到这些,循环才是工程系统,而不是更长的提示词。

相关推荐
菜是原罪1 小时前
ECS CPU 100% 故障排查与安全事件复盘报告
运维·服务器·网络安全
ClouGence1 小时前
当 AI 开始直接操作数据库,传统数据库管理工具还有必要吗?
数据库·后端·agent
渣渣盟1 小时前
误删数据之后:MySQL、PostgreSQL、Oracle三库紧急恢复完全实操手册
mysql·postgresql·oracle
12.=0.2 小时前
【REVIEW_C】【持续更新】
服务器·前端·javascript
皮皮虾❀2 小时前
广州云服务器价格:阿里云代理商折扣报价单指南
运维·服务器·阿里云
Hugh-Yu-1301232 小时前
zhangxuefeng-skill配置教程
数据库
金刚钻信息2 小时前
如果服务器坏了,加密文件还能恢复吗?
服务器·网络·加密软件·桌面管理·防泄密
布莱克6052 小时前
理解B+树:原理、特性与应用场景
数据结构·数据库·mysql
冰暮流星2 小时前
mysql之排序查询
数据库·mysql
7177772 小时前
让权限治理成为可复制资产:Gitee Team 空间配置方案与安全级别落地详解
数据库·gitee