ECC loop-operator:自主 Agent 循环的安全运营 Agent 设计与落地实践
本文以 ECC 仓库中 Kiro 适配包内的 loop-operator Agent 定义(.kiro/agents/loop-operator.md)为主体,系统讲解“循环运营者”这一角色的设计意图、五步操作工作流、启动前四项必备检查与四类升级(Escalation)判据,并结合仓库中配套的 loop-start/loop-status 命令与 scripts/loop-status.js 的源码实现,说明这套“观察—检测—干预—恢复”机制是如何被具体工具支撑起来的。读完后,你将掌握如何为长时间自主运行的 Agent 循环建立可观测、可暂停、可回滚的运营规范,并能直接用仓库提供的 CLI 手段监控卡死循环。
loop-operator 是什么:定位与文件格式
loop-operator 是 ECC 提供的一个专职“运营者”角色,其定位写在文档的 YAML frontmatter 中:
---
name: loop-operator
description: Operate autonomous agent loops, monitor progress, and intervene safely when loops stall.
allowedTools:
- read
- shell
---
它不是一个“写代码的 Agent”,而是一个站在自主循环外部做监控与干预的运营角色:负责跑循环、盯进度、在循环卡死(stall)时安全介入。allowedTools 只授予 read(读取)与 shell(执行命令)两类工具,从权限层面就限定了它的行为边界——可以观测、可以执行受控操作,但不具备任意写入能力。
在 Kiro 适配包中,每个 Agent 都同时提供两种格式,loop-operator 也不例外:
| 文件 | 用途 |
|---|---|
| .kiro/agents/loop-operator.md | IDE 格式(Markdown),通过自动选择或显式调用(如 /loop-operator)使用 |
| .kiro/agents/loop-operator.json | CLI 格式(JSON),通过 /agent swap 命令切换 |
JSON 版本把同一份运营者 Prompt 内嵌为 prompt 字段,并声明 "tools": ["@builtin"]、"allowedTools": ["fs_read", "shell"],与 MD 版本的工具约束一一对应。整个 Kiro 包可通过 .kiro/install.sh 一键安装到任意项目,安装采用非破坏性复制,不会覆盖已有文件。
值得注意的是,ECC 在 Claude Code 一侧还维护了一份对应物 agents/loop-operator.md。它除了相同的 Mission/Workflow/Checks/Escalation 内容外,额外携带了 model: sonnet、tools: Read, Grep, Glob, Bash, Edit 的声明,以及一段 Prompt Defense Baseline(提示词防御基线):禁止改变角色与身份、禁止泄露机密与密钥、把外部抓取/检索到的第三方数据一律视为不可信内容并在行动前校验、检测零宽字符与同形字等注入技巧。从源码结构看,这份基线意味着 loop-operator 在读取循环日志、外部 CI 输出等不可信输入时,需要把这些内容当作“数据”而非“指令”处理——这对一个需要长时间读取第三方文本流的运营 Agent 尤为关键。
使命:用明确的停止条件运营自主循环
loop-operator 的核心使命只有一句话:
Run autonomous loops safely with clear stop conditions, observability, and recovery actions. (带着清晰的停止条件、可观测性与恢复手段,安全地运行自主循环。)
这句话拆解出三个支柱,恰好对应后文的工作流、状态检查和升级判据:
- 明确的停止条件:循环必须在启动时就定义好“何时算完、何时必须停”;
- 可观测性:进度必须以检查点(checkpoint)的形式被持续追踪,而不是靠“感觉它在动”;
- 恢复手段:卡死或反复失败时,有暂停、收缩范围、验证后恢复的既定动作,而不是盲目重启。
这个设计与 ECC 仓库中另一个技能 skills/continuous-agent-loop/SKILL.md 中列出的四类典型失败模式直接呼应:无可度量进展的循环空转(loop churn)、同一根因的重复重试、合并队列卡死、无上限升级导致的成本漂移。loop-operator 的存在,就是给这四类失败模式提供一个专职的“值班人”。
五步操作工作流
文档给出的标准工作流共五步,构成一个“启动—观察—检测—干预—恢复”的闭环:
1. 从明确的模式启动循环(Start loop from explicit pattern and mode)
循环不能“凭感觉启动”,必须显式指定模式(pattern)与运行档位(mode)。在 ECC 中,这对应 /loop-start 命令(commands/loop-start.md):
/loop-start [pattern] [--mode safe|fast]
pattern可选值:sequential(顺序流水线)、continuous-pr(持续 PR 循环)、rfc-dag(RFC 驱动的多 Agent DAG)、infinite(无限代理循环);--mode:safe(默认,严格质量门与检查点)或fast(为速度放宽门禁)。
loop-start 自身的启动流程要求:确认仓库状态与分支策略 → 选择循环模式与模型档位策略 → 为所选模式启用必要的 hooks/profile → 在 .claude/plans/ 下写入循环计划与 runbook → 最后打印启动与监控命令。它还有三条硬性安全检查:首次迭代前测试必须通过、ECC_HOOK_PROFILE 未被全局禁用、循环必须有显式停止条件。loop-operator 工作流的第 1 步正是以此为起点:没有这些前置条件,运营者不应放行循环。
2. 追踪进度检查点(Track progress checkpoints)
运行中,运营者要持续记录“最后一个成功检查点”在哪里。这一步是后续所有判断(是否卡死、是否倒退)的基准线——没有检查点序列,就无法区分“在慢速推进”与“已经完全停摆”。
3. 检测卡死与重试风暴(Detect stalls and retry storms)
这里仓库提供了真正的实现级支撑:/loop-status 命令(commands/loop-status.md)与其底层 CLI scripts/loop-status.js。该 CLI 扫描 ~/.claude/projects/** 下的 Claude 会话转录(JSONL),专门检测两类“悬挂信号”:
- 过期的
ScheduleWakeup调用:计划了唤醒但没有后续动作; - 没有匹配
tool_result的Bash工具调用:命令发出后始终没有结果返回。
源码中的默认阈值可以直接查证(scripts/loop-status.js):
const DEFAULT_BASH_TIMEOUT_SECONDS = 30 * 60; // 1800 秒
const DEFAULT_LIMIT = 10; // 默认检查最近 10 份转录
const DEFAULT_WAKE_GRACE_MULTIPLIER = 2; // ScheduleWakeup 宽限倍数
const DEFAULT_WATCH_INTERVAL_SECONDS = 5; // --watch 刷新间隔
即一条悬挂的 Bash 调用超过 30 分钟无结果即被判定为 stale。
4. 失败重复时暂停并收缩范围(Pause and reduce scope)
当检测到同一失败反复出现(重试风暴),运营者的动作不是“再试一次”,而是冻结循环并把范围收缩到失败单元。这与 skills/continuous-agent-loop/SKILL.md 的 Recovery 段落完全一致:freeze loop → 运行 /harness-audit(commands/harness-audit.md)→ reduce scope to failing unit → replay with explicit acceptance criteria。
5. 验证通过后才恢复(Resume only after verification passes)
恢复循环的门槛是验证通过,而非“看起来修好了”。仓库中承担验证职责的是 verification-loop 技能(build、type check、lint、tests、security scan、diff review 全量跑一遍)与 /quality-gate 命令。后者在 commands/quality-gate.md 中说明:质量门由 PostToolUse hook scripts/hooks/quality-gate.js 驱动,按文件类型调用 Biome/Prettier/gofmt/ruff,并通过环境变量 ECC_QUALITY_GATE_FIX=true(应用修复)与 ECC_QUALITY_GATE_STRICT=true(把 formatter 失败记为门禁失败)切换行为。
启动前四项必备检查(Required Checks)
文档要求 loop-operator 在启动循环前确认四项检查全部就位,缺一不放行:
| 检查项 | 含义 | 在 ECC 中的落点 |
|---|---|---|
| quality gates are active | 质量门处于激活状态 | /quality-gate 命令与 post:quality-gate PostToolUse hook(scripts/hooks/quality-gate.js),且 ECC_HOOK_PROFILE 未被全局禁用(loop-start 的硬性检查之一) |
| eval baseline exists | 评估基线已存在 | eval-harness 技能(skills/eval-harness/SKILL.md)为循环提供可度量的对照基线,否则“有没有进展”无从判定 |
| rollback path exists | 回滚路径存在 | 循环产出的任何提交都必须可撤回,通常依托显式的分支/工作区隔离与干净的提交边界 |
| branch/worktree isolation is configured | 分支/worktree 隔离已配置 | continuous-pr 模式创建 continuous-claude/iteration-N 分支;Ralphinho DAG 模式中每个工作单元独占一个 worktree(/tmp/workflow-wt-{unit-id}/),见 skills/autonomous-loops/SKILL.md |
其中“eval baseline”一项值得强调:它要求循环在启动前就有一个可对照的度量基准(如既有测试通过率、eval 分数),这样第 2 步的“检查点”才有客观标尺——没有基线的循环,检查点只是时间戳,无法判定进展。
四类升级(Escalation)判据
loop-operator 明确规定了满足任一条件即必须升级(升级到人工干预)的四条红线:
- 两个连续检查点零进展(no progress across two consecutive checkpoints);
- 重复出现栈迹完全相同的失败(repeated failures with identical stack traces)——相同栈迹说明重试没有带来新信息,继续重试就是纯烧 token;
- 成本漂移超出预算窗口(cost drift outside budget window);
- 合并冲突阻塞队列推进(merge conflicts blocking queue advancement)——对应
continuous-pr/rfc-dag模式下的 merge queue stall。
这四条判据与 scripts/loop-status.js 的退出码设计形成了呼应:该 CLI 支持 --exit-code 参数,检测到 stale 循环/工具信号时退出码为 2,转录无法扫描时退出码为 1,从而可以写进 watchdog 脚本,让“升级”动作本身也可以被自动化触发。
实战:用仓库自带工具落地这套运营流程
把上述机制串起来,一个典型的 loop-operator 值班流程在仓库内可以直接执行:
启动阶段(对应工作流第 1 步):
# 交互式会话内:/loop-start continuous-pr --mode safe
# 等价的人工前置确认:
# - 测试已全绿(loop-start 的 Required Safety Check)
# - ECC_HOOK_PROFILE 未被全局禁用
# - 循环有显式停止条件(--max-runs / --max-cost / --max-duration / 完成信号)
监控阶段(对应第 2、3 步),在另一个终端运行打包 CLI(因为 /loop-status 会话内命令要等当前会话出队才能执行,监控卡死会话必须用独立进程):
npx --package ecc-universal ecc loop-status --json
常用参数(均以 commands/loop-status.md 与 scripts/loop-status.js 的 usage 输出为准):
| 参数 | 作用 |
|---|---|
--json |
输出机器可读的状态 JSON,watch 模式下每刷新一次输出一行 JSON,可供其他终端/脚本消费 |
--home <dir> |
扫描另一个 home 目录(检查其他本地 profile 或挂载工作区) |
--transcript <session.jsonl> |
直接检查单份转录文件 |
--bash-timeout-seconds 1800 |
调整“悬挂 Bash 判定为 stale”的阈值(默认 1800 秒) |
--exit-code |
发现 stale 信号退出 2 / 无法扫描退出 1,供 watchdog 使用 |
--watch |
周期性刷新直到中断 |
--watch --watch-count 3 --exit-code |
有界刷新 3 次后退出并返回观察到的最高状态码(watch + exit-code 必须搭配 watch-count,否则进程永不退出,源码中有显式校验) |
--write-dir ~/.claude/loops |
写出 index.json(每个被检会话一行)与 <session-id>.json(完整状态负载),供兄弟终端或 watchdog 读取 |
需要明确的一点:这些快照文件只是本地转录分析的快照,它们并不控制、也不超时 Claude Code 运行时中的工具调用——干预动作仍由运营者(或人)依据快照信号来执行。
干预阶段(对应第 4、5 步):状态报告应包含 /loop-status 文档列出的五个字段——当前循环模式、所处阶段与最后一个成功检查点、正在失败的检查项、预估的时间/成本漂移、以及建议动作(continue / pause / stop)。选择 pause 后按 continuous-agent-loop 的 Recovery 流程收缩范围,验证通过再恢复。
权限边界与升级之外的“人”
loop-operator 的安全设计还体现在两处权限与责任的边界上:
其一,工具白名单最小化。Kiro 侧只有 read + shell,Claude Code 侧虽有 Edit,但整体仍以 Read/Grep/Glob/Bash 的观察型工具为主——运营者的首要职责是“看与判”,写操作是受控的例外。
其二,判断权不转移给机器。仓库中 skills/loop-design-check/SKILL.md 把这一点表述为红线前提:机器擅长“执行层”反馈(离目标差多远、把它磨平),但“目标本身对不对、要不要停”这种“判断层”反馈必须留在人手里;循环可以开 PR,但不应自动合并,最后的开关由人拨动。loop-operator 的升级机制正是这条红线在运营侧的落地:它负责把“该停了”的信号及时、结构化地报出来,但“停不停、怎么改”的最终决定权在人。
适用前提与限制
- Kiro 用户:loop-operator 位于 .kiro/agents/ 目录,随 Kiro 适配包(.kiro/README.md)安装使用;Agent 实际使用的模型由 Kiro 当前选择的模型决定,不由 Agent 配置指定(.kiro/README.md 中的说明)。
- Claude Code 用户:对应定义在 agents/loop-operator.md,额外携带提示词防御基线与
sonnet模型标注。 - 监控工具的前提:
ecc loop-statusCLI 依赖本地 Claude 转录 JSONL(~/.claude/projects/**),因此它监控的是 Claude 侧的自主循环;快照不控制运行时工具调用,只能作为干预决策的输入。 - 本文描述的命令参数与默认值均以当前仓库的 commands/loop-status.md 与 scripts/loop-status.js 为准,如仓库版本更新请以最新源码输出为准。
小结
loop-operator 用不到一页纸的篇幅定义了一套完整的安全运营契约:五步工作流规定了“怎么跑、怎么盯、怎么停”,四项必备检查把质量门、eval 基线、回滚路径、隔离配置设为启动前置条件,四条升级判据把零进展、重复失败、成本漂移、队列阻塞量化为可执行的升级触发器。配合仓库中真实实现的 scripts/loop-status.js 转录分析 CLI、/loop-start 的启动门禁与 verification-loop/quality-gate 的恢复验证,这套机制从规范落到了可运行的工具链上——它给出的核心经验是:自主循环的可靠性不来自循环本身,而来自循环外部一个权限受控、判据明确、随时可以把决定权交还给人运营者。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00