mcpField
F
fable-loop

fable-loop

github.com/immamdouhaboammarAgent 工作流353 次安装6 天前更新
代码仓库

关于 fable-loop

fable-loop 是用于轮询变化中的外部或异步状态的限时技能,例如 CI、部署和批处理作业。它帮助 Agent 区分等待与失败,并依据明确的结果条件、预算和重试策略停止。

主要功能

  1. 01定义成功、等待和失败状态
  2. 02设置时间与请求预算
  3. 03检查轮询的幂等性和副作用
  4. 04采用退避并遵循速率限制
  5. 05记录循环停止原因

适用场景

  1. 01等待 CI 构建结果
  2. 02监控部署健康状态
  3. 03检查异步批处理进度
  4. 04在期限内观察最终一致性

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/immamdouhaboammar/get-fable --skill fable-loop

安装后在 Claude Code 中输入/fable-loop确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

skill.package.json
agents/
openai.yaml
evals/
scenarios.json
examples/
poll-build-job.md
references/
loop-control-guidelines.md
polling-state-machines-and-backoff.md
templates/
loop-config.template.json

详细介绍

Fable Loop

仅在重复检查能够揭示新状态时才重复检查,并明确终止条件、退避策略、错误分类,以及循环停止原因,确保毫无歧义。

使命

轮询不是“重复运行同一条命令,直到它变绿”。良好的循环会对变化中的外部条件建模,区分待处理与失败,遵守速率和成本预算,并在成功、终态失败、取消或预算耗尽时终止。

如果重复执行无法带来新信息,这项任务应该归入诊断,而不是循环。

适用场景

  • 等待 CI/部署/构建/批处理作业状态发生变化;
  • 监控有明确边界的异步操作;
  • 检查最终一致的外部状态;
  • 在已知流程推进期间,重复进行安全的测量;
  • 执行有限的稳定性采样,其中重复本身就是测量。

不适用场景

  • 一次命令/探测就足够(fable-run/fable-verify);
  • 同一确定性故障反复出现,且外部状态没有变化(fable-recover);
  • 用户期待的是未来通知/定时任务,而非会话内的有限循环;
  • 轮询会产生重复的非幂等副作用;
  • 无法定义终止条件或预算。

循环分类

循环类型成功/终态语义
CI/构建待处理 → 成功或终态失败/取消
部署进行中 → 健康/已回滚/失败
批处理作业已排队/运行中 → 已完成/失败
最终一致性旧状态 → 在截止时间内达到预期状态
受速率限制的 API待处理/可重试 → 成功或终态鉴权/架构错误
稳定性采样N 次有界观测 → 分布/方差判定

协议

阶段 1 —— 定义状态机

开始迭代前,列出:

  • 成功状态;
  • 待处理/可重试状态;
  • 终态失败状态;
  • 格式错误/未知状态;
  • 取消条件。

将所有非成功状态都视为“再试一次”的循环并不安全。

阶段 2 —— 设定预算

至少定义:

  • 最大耗时/截止时间;
  • 适用时的最大迭代次数或请求预算;
  • 初始间隔/退避策略;
  • 最大间隔;
  • API/成本/速率限制。

存在多个限制时,采用更严格的限制。

阶段 3 —— 检查幂等性和副作用

轮询操作应为只读/幂等。如果端点/命令会触发工作,应将触发操作与状态观测分开,并确保重试不会重复执行该操作。

阶段 4 —— 执行一次迭代并分类结果

记录:

  • 迭代次数/时间;
  • 观测到的状态/值;
  • 传输/命令结果;
  • 分类:成功/待处理/可重试错误/终态失败/未知;
  • 下一次延迟/原因。
阶段 5 —— 智能应用退避策略

如果预期更新频率已知且成本较低,则使用固定间隔;如果需要应对速率限制/瞬时服务错误,则使用指数退避/带抖动的退避。

适用时遵循明确的 Retry-After/服务提供方指导。不要仅仅因为工具允许,就以亚秒级的激进频率调用运行缓慢的外部作业。

阶段 6 —— 遇到终态信息时提前停止

遇到以下情况立即退出:

  • 成功;
  • 明确的失败/取消状态;
  • 不可重试的鉴权/架构/权限错误;
  • 用户取消;
  • 预算/截止时间耗尽。

结果已知后,不要继续消耗剩余迭代次数。

阶段 7 —— 检测进度停滞

如果状态包含进度/版本/时间戳,请比较各次迭代的结果。若状态长时间未变化,且已接近或超出预期 SLA,这可能成为诊断信号,而不是自动延长预算的理由。

阶段 8 —— 提供如实的结果记录

最终记录应包含停止原因、耗时、迭代次数、最后状态、瞬时错误,以及条件是否确实满足。

超时不等于成功。除非约定/截止时间另有规定,否则“仍在运行”不等于失败。

决策规则

  • 可重复的确定性失败,且外部状态没有变化 → 停止循环并恢复。
  • 可重试的传输错误可在预算范围内继续;身份验证、权限或架构错误通常应终止,直到配置发生变化。
  • 在适用的情况下,将提供方的 Retry-After 或作业建议的轮询间隔视为下限。
  • 绝不能将非幂等触发操作重复用作状态轮询。
  • 如果每次迭代都会消耗大量费用或配额,除时间外还要设定费用/请求预算。
  • 如果预计完成时间超出当前会话/任务模型的范围,在可用时创建计划任务/条件监视机制,而不是假装会话内循环可以无限运行。
  • 循环可以以 INCOMPLETE/TIMEOUT 结束;不要为了获得绿色结果而悄悄延长限制。
  • 如果进度没有变化,且截止时间尚远,则按策略继续,不要频繁向用户更新;对于长时间交互式运行,仅报告有意义的状态变化。

不变量

  • 循环开始前,明确退出条件和预算。
  • 每次迭代都是安全/幂等的,或明确控制其副作用语义。
  • 终止性失败立即停止。
  • 待处理状态与失败状态应区分开。
  • 遵守退避策略和速率限制。
  • 收据记录实际停止原因;不得将超时转换为通过。

故障分类

无限/隐式循环

没有可强制执行的预算。应拒绝并定义限制。

重试所有错误

将身份验证/架构/权限错误及终止性作业失败视为暂时性错误。应进行分类并适时停止。

重复副作用

轮询调用会重新触发工作。应使用单独的状态端点/幂等键,或停止。

轮询风暴

轮询间隔相对于服务/作业节奏过于频繁。应采用退避策略/遵循提供方的指引。

错误诊断超时

作业仍在预期 SLA 内处于待处理状态,但循环将其标记为故障。应将超时/未完成与产品故障分开报告。

进度卡住

状态在应当变化时始终没有变化。应交由恢复/运维诊断处理,而不是无限延长。

会话不匹配

请求的监控时长超出可用的执行窗口。在支持时,使用计划任务/条件监视功能。

反模式

  • 使用原始的 while true/无界休眠循环;
  • 重试所有类别的错误;
  • 通过反复重新提交作业来轮询;
  • 每次未成功后都延长超时时间,直到成功为止;
  • 对 10 分钟的部署每 1 秒轮询一次;
  • 仅仅因为状态处于待处理就判定失败;
  • 仅仅因为循环正常结束就判定成功;
  • 在最终收据中隐瞒暂时性错误;
  • 用循环逃避对可重复的确定性失败进行诊断。

循环收据

Condition/state machine:
Success / terminal failure states:
Time + iteration/request budgets:
Interval/backoff policy:
Idempotency/side-effect check:
Iterations: time → observed state → classification
Transient errors:
Stop reason:
Condition satisfied? yes/no
Final state:
Next action if incomplete/failed:

完成标准

循环满足以下条件时即告完成:

  • 状态机、成功/失败语义和预算已明确;
  • 轮询遵守幂等性/速率/费用限制;
  • 终止性信息使循环提前停止;
  • 如实呈现超时/卡住状态;
  • 最终收据准确说明循环结束的原因以及接下来应采取的措施。

渐进式资源

  • 深入指南:references/polling-state-machines-and-backoff.md
  • 现有指南:references/loop-control-guidelines.md
  • 示例:examples/poll-build-job.md

评论

支持 Markdown