Skip to content

Repeat work on a schedule

A loop runs one task again and again in a session: every weekday at nine, every five minutes, or at a pace the agent sets after each run. The agent creates it with the Loops tool, or you ask for one with /loop. Loops are stored in the database and survive an API restart.

Terminology

TermMeaningBoundary
Fixed loopFires on a 5-field cron, read in the time zone it was created in.A slot the session cannot take is skipped, not replayed later.
Dynamic loopFires after a delay the agent chooses each time with reschedule (60–3,600 s).It keeps firing at its last delay until it is removed.
Targetsession runs the task in this conversation; subsession in a fresh child.Only a fixed loop can use subsession: a child cannot reschedule itself.
OwnerThe agent that created the loop. Its fires are addressed to that agent.A fire runs in the session that created the loop.
HoldA dynamic fire waiting because the session is busy or its owner's route is exhausted.The hold is stored; fixed loops skip those occurrences.

What you can do

NeedMechanismBoundary
Start one/loop <task>, or ask the agent; it calls Loops with action="add".The same task, cadence and target is one job; a repeat add returns it.
See what is scheduledThe composer strip lists cadence, next run, run count and the last result.The agent sees the same list through Loops with action="list".
Run one nowThe strip's Run button, or Loops with action="run".An extra run: it does not use up a fixed loop's next slot.
Cancel oneThe strip's Cancel button, or Loops with action="remove".Removes the schedule; session-target runs have scoped cancellation.

How a loop behaves

When a fire cannot run

For target: session, a conversation busy with another turn does not take a loop fire on top of it. A fixed loop gives that slot up and fires at the next one. A dynamic loop keeps its fire waiting and runs it as soon as the session is idle.

A fixed target: subsession loop starts a fresh child through its own runner. A loop an agent armed runs each child as that agent, on its own model route; a loop a person armed runs on the default agent. It does not use the parent-session busy or quota gate described here; the child still faces ordinary provider and runtime limits.

A quota is tracked per provider route — the provider connection and the model on it — not per conversation. When a run fails because a provider reports a rate limit, fires on that route wait until the cooldown ends. A temporary rate limit holds that one model; an exhausted plan or credit balance holds every model on that connection. The strip shows the time the hold ends.

These holds apply to dynamic session-target loops. Fixed session-target loops skip the affected occurrence and try their next cron slot, rather than replaying it after the cooldown.

When fires fail

A fixed loop's failed run can push its next due time later: at least one minute after completion, then two, four, up to an hour for consecutive failures, without advancing an already later scheduled slot. A successful run clears the streak. A dynamic loop keeps the pace the agent set; before its first reschedule, its watchdog delay is one hour. The agent sees failures in the loop list.

After a restart

A fixed loop with an overdue stored slot makes at most one catch-up attempt after restart, then computes its next slot from the current time. Busy/quota gates still apply; missed slots do not form a replay backlog. A dynamic loop resumes its stored due time and continues at its last delay unless the agent reschedules it. Failure-backoff streaks are in memory and reset on restart.

Cancelling

Run now refuses to overlap a fire already in progress.

Run now is an explicit extra fire and bypasses the automatic busy/quota gate. A session-target fire can therefore enter the session's wake queue while another turn is active. It leaves the existing due time in place, though a failed manual run can still apply the fixed loop's failure backoff.

Cancelling a session-target loop withdraws its own queued wake or stops its own active run. Other messages and runs are unaffected. Cancelling a subsession-target loop removes future scheduling but does not stop a child fire already running or waiting for the child runner's concurrency slot. Inspect and stop that child separately when needed.

Source of truth