Skip to content
Development
Skill

/agentsop-bounded-loop

Universal discipline for any LM-driven loop — agent retries, plan-act-observe, multi-agent handoffs, optimiser passes, test-fix cycles. Encodes the one rule every framework documents quietly and every team relearns expensively: the LM in the loop is NEVER a reliable terminator.

From plugin
skillalchemy
28747 skills
Install
$ npx -y skills add agentsope/SkillAlchemy --skill agentsop-bounded-loop --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/agentsop-bounded-loop

Context preview

The summary Claude sees to decide when to auto-load this skill.

Universal discipline for any LM-driven loop — agent retries, plan-act-observe, multi-agent handoffs, optimiser passes, test-fix cycles. Encodes the one rule every framework documents quietly and every team relearns expensively: the LM in the loop is NEVER a reliable terminator.

SKILL.md

agentsop-bounded-loop.SKILL.md
name: agentsop-bounded-loop
version: 0.1.0
description: >-
  Universal discipline for any LM-driven loop — agent retries, plan-act-observe, multi-agent
  handoffs, optimiser passes, test-fix cycles. Encodes the one rule every framework
  documents quietly and every team relearns expensively: the LM in the loop is NEVER a
  reliable terminator. Termination must be provided by an explicit counter + exit predicate
  + stagnation signal + escalation path that live OUTSIDE the LM's control. This is a tool-
  level, framework-agnostic skill. It maps onto LangGraph (recursion_limit + state counter +
  interrupt), CrewAI (max_iter + max_rpm + human_input), Claude / OpenAI SDKs
  (max_iterations + tool_use_budget), DSPy (declared evaluation budget), Aider (REPL +
  explicit retry cap), and AutoGen (max_consecutive_auto_reply). Search keywords: infinite
  loop, recursion limit, recursion_limit, GraphRecursionError, max iterations, max_iter,
  agent stuck, agent won't stop, runaway agent, ReAct loop not terminating, agent repeating
  itself.

bounded-loop · O7

> Source posture: every load-bearing claim is cited inline with a short tag > resolved against `references/R1-source-evidence.md` and > `references/R2-cross-framework.md`. Examples cite the real GitHub issues > they're distilled from.

---

1. 何时激活 (Activation Rules)

Activate this skill when **any** of the following is true:

  • The task involves a workflow that contains a **cycle** — tool-call → reflect

→ retry, plan → act → observe → re-plan, draft → critique → revise, test → fix → re-test.

  • The user is hitting a framework's "loop too deep" error:

`GRAPH_RECURSION_LIMIT` (LangGraph), `MaxIterationsExceeded` (LangChain `AgentExecutor`), "agent exceeded max_iter" (CrewAI), `max_turns reached` (OpenAI Agents SDK), `stop_reason="max_tokens"` mid-tool-use (Anthropic).

  • The user proposes "let's just raise the limit" / "set max_iter to 100" /

`recursion_limit=200` — this is the canonical anti-pattern this skill exists to prevent.

  • The user is building a **multi-agent** system with delegation, handoff,

or supervisor patterns — these are exposure-multipliers for unbounded loops (see `[gh/crewai-330]`).

  • The user is building an **optimiser / evaluator loop** (DSPy, AutoEval,

RLHF, self-refining agent) where "stop when good enough" is the termination criterion — this is *never* sufficient on its own.

  • The user wants a **test-fix loop**, **self-healing code agent**, or

**iterative refinement** workflow — every code-agent in production (Cursor, Aider, Devin, Claude Code) ships with an explicit step budget.

Do **not** activate for: single LLM calls, one-shot RAG queries, stateless tool pipelines, or flows where the cycle is provably bounded by data (e.g., "iterate once per row in this fixed list").

---

2. 核心心智模型 (Core Mental Model)

**Every loop body must produce a state change that proves progress — and the proof must be checkable without calling another LM.**

Read that twice. It contains four claims:

1. **The body must change state.** A no-op iteration (same input → same output) is the definition of a stuck loop. If your body might return the same value twice, the loop is already broken; the safety net just hasn't fired yet.

2. **The change must be progress, not just diff.** A retry that says "I tried again, same error" is a change but not progress. The witness has to be monotone: counter strictly increasing, error list strictly shrinking, confidence strictly rising, or a new fact added to the plan.

3. **The proof must be checkable.** Pure Python. A `dict.get("retries") < N`, not `await llm.ainvoke("are we done?")`. If you ask the LM to evaluate termination, you've recreated the problem one level up — now *that* loop needs bounding.

4. **The LM is not allowed to vote.** It can *suggest* finality (`stop_reason="end_turn"`, `final_answer` tool, etc.) but the framework must verify against the predicate before terminating. Otherwise an LM that always says "let me try once more" runs forever.

Why the framework's default safety net is not enough

Every framework ships a default cap:

  • LangGraph: `recursion_limit=25` `[lc-docs/errors]`
  • CrewAI: `Agent.max_iter=20`, `Crew.max_rpm` `[crewai-docs/agents]`
  • LangChain `AgentExecutor`: `max_iterations=15` (deprecated default)
  • OpenAI Agents: `Run.max_turns`
  • Anthropic Messages: `max_tokens` per call (per-call, not per-loop)

These are **billing safety nets**, not control flow. The LangGraph docs say so explicitly:

> "If you are not expecting your graph to go through many iterations, you > likely have a cycle. Check your logic for infinite loops." > — `[lc-docs/errors]` `https://docs.langchain.com/oss/python/langgraph/errors/GRAPH_RECURSION_LIMIT`

And the cheatsheet adds:

> "Hitting the limit typically indicates an underlying design flaw. The > recursion limit is a safety net for runaway code, not a primary control > flow mechanism." > — `[cheatsheet/gotchas]`

When you raise the limit to "fix" the error, you've **moved the bug further away**, not removed it. The text-to-SQL agent in `[gh/6731]` would have hit `recursion_limit=100` after burning 5× the Databricks quota.

The three-axis termination model

A bounded loop has three independent termination axes; you need at least two firing in series:

                ┌─── (a) success predicate met → exit success
                │
[loop body] ────┼─── (b) counter / budget exhausted → exit escalation
                │
                └─── (c) stagnation detected → exit escalation

If you only have (a), the LM controls termination — it doesn't. If you only have (b), you'll burn the budget on N identical iterations. If you only have (c), one-shot flake will look like success.

Compose all three.

---

3. SOP 工作流 (Standard Operating Procedure)

A coder agent walks this top-down. Each step has a decision gate — answer "no" and you go back, not forward.

###

Read more
Ships withskillalchemy

From thought to skill. From signal to structure.

Get the whole plugin

Other skills on skillalchemy.