Skip to main content

Loops

Loops let the agent execute an arbitrary task as a structured execution path — an ordered set of named steps that the agent traverses, deciding when to loop back, advance, or stop based on outcomes.

Unlike a fixed pipeline, loops are agent-driven: the agent calls tools to jump between steps, swap agents mid-flow, and stop when done. This makes them a better way to execute repeatable workflows like read → build → test → review → report where the agent may need to loop back (build → test → build → test → review → stop).

Enable

Loops is a builtin plugin, disabled by default. Enable it in your config:

{
"builtin": { "loops": { "enabled": true } }
}

The server also exposes endpoints: GET /builtin, POST /builtin/:name/enable, POST /builtin/:name/disable.

Configuration

{
"loops": {
"compaction_threshold": 0.5,
"compaction_model": "anthropic/claude-opus-4-8",
"definitions": {
"fix-bug": {
"description": "Read, build, test, review, report",
"steps": [
{
"name": "read",
"agent": "plan",
"prompt": "Read and understand the task."
},
{ "name": "build", "prompt": "Implement the change." },
{
"name": "test",
"prompt": "Run the tests. If failing, call loop_next({ step: 'build' }) with the reason."
},
{
"name": "review",
"review": true,
"prompt": "Review the change for correctness and security."
},
{
"name": "report",
"agent": "TF Engineer",
"prompt": "Report the outcome."
}
]
}
},
"auto": ["fix-bug"]
}
}

Top-level

FieldDefaultDescription
compaction_threshold0.5Compact between steps when context usage exceeds this ratio (0–1).
compaction_modelModel for compaction (defaults to the session's active model).
max_step_repeats3Max times a single step can be visited before the loop pauses (doom-loop guard). 0 disables.
max_transitions20Hard cap on total step transitions. The loop pauses when exceeded. 0 disables.
definitionsNamed loop workflows keyed by id.
autoLoop ids to auto-start on non-interactive sessions (requires --auto-loops).

Step

FieldDescription
nameUnique step id the agent references in loop_next.
promptTask prompt for this step.
agentAgent for this step (build, plan, TF Engineer, …).
skillSkill/command name whose content is inlined into this step's prompt.
reviewNudges the agent to call the reviewer tool during this step.
model(phase 2) Swap to this model for this step.

Tools

When a loop is active, two tools are registered:

loop_next

Jump to any named step (forward or backward). Optionally swap to a different agent for the next step — enabling multi-agent workflows.

loop_next({ step: "build" })
loop_next({ step: "review", agent: "TF Engineer", reason: "needs security review" })

If the agent does not call loop_next, the loop auto-advances to the next step in order.

loop_done

Stop the loop early when the goal is satisfied.

loop_done({ reason: "all tests pass and review approved" })

When the last step completes with no loop_next, the loop finishes automatically.

Multi-agent workflows

Each transition can hand off to a different agent. There are two ways to control which agent runs a step:

  1. Static — set agent on the step definition.
  2. Dynamic — pass agent to loop_next at runtime to override the step's configured agent.

This lets the agent decide mid-flow which agent is best for the next step.

Backward jumps

The agent can jump back to any earlier step when it discovers a root-cause issue. For example, at step test the agent might realize the plan from read was incorrect:

loop_next({ step: "read", reason: "plan was incorrect — need to re-read the spec" })

The system prompt guides the agent to:

  • Jump back and fix the root cause rather than patching around it in the current step.
  • Provide a reason explaining why it's jumping back (for audit history).

Doom-loop prevention

If a step keeps failing and the agent loops back repeatedly, the loop auto-pauses to prevent infinite cycles. Two configurable guards:

  1. max_step_repeats (default 3) — if a single step is visited more than this many times, the loop pauses with a doom-loop message.
  2. max_transitions (default 20) — if total transitions across all steps exceed this, the loop pauses.

Both can be set to 0 to disable the guard entirely (not recommended).

When a doom loop is detected:

  • The loop pauses (not stops) — the state is preserved.
  • /loops status shows which step triggered the pause and how many times it was visited.
  • /loops resume restarts the loop from the paused step. The agent should try a different approach.
  • The loop_next tool returns a warning when a step is approaching its visit limit, nudging the agent to try a different approach or call loop_done if stuck.

The system prompt also instructs the agent to call loop_done with a reason if it's stuck, and to use the reviewer tool for a fresh perspective on why a step keeps failing.

Reviewer, model_swap, and skills

Within any step, the agent can use:

  • reviewer — get a second opinion from a stronger model (architecture, security, performance, correctness).
  • model_swap — switch to a different model mid-step when the task calls for different capabilities or cost.
  • skill — load any available guided workflow at runtime.

The review step field nudges the agent to call the reviewer. The skill step field inlines a skill's content into the step prompt.

Compaction

Between steps, if context usage exceeds compaction_threshold (default 50%), the loop automatically compacts the session to preserve context. This keeps long loops running without hitting context limits.

Commands

CommandDescription
/loops run <name>Start a loop workflow
/loops statusShow current loop state and history
/loops listList available loops from config
/loops pausePause the active loop
/loops resumeResume a paused loop
/loops clearStop and remove the active loop

Auto-start

To auto-start a loop on non-interactive sessions (e.g. tfcode run), add loop ids to auto and pass --auto-loops:

tfcode run --auto-loops "Process the queue"

Or set the environment variable:

export OPENCODE_AUTO_LOOPS=true

Auto-start never applies to interactive TUI sessions — use /loops run <name> there. State is persisted to ~/.tfcode/loops-plugin/state.json and recovered as paused on restart.

Skill

Loops ships with a loops skill that documents the loop_next/loop_done contract and transition patterns. The agent can invoke it via the skill tool, or you can reference it in a step with "skill": "loops".