Skip to content

Configure

Adjust how a Loop runs — its checks, its human gate, its re-attempt strategy, and its stop limits — without changing its structure.

For people running agent work16 pages in this section

Configure is the middle commitment layer: change how a Loop runs without forking it. It opens as a sheet over the detail view and writes a per-Loop config overlay — the Loop's structure is untouched.

What you can tune

The sheet has four groups, all scoped to the checks and limits the Loop already declares:

  • Verification checks — enable or disable each declared check, and for a generic command check, set the project command it runs (a test suite, a linter). Disabling a command check disables its command field. A gate that judges (an agent-judge acceptance review) cannot be removed here — that is structure.
  • Human approval gate — a single switch to require, or drop, a human approval before the Loop finishes.
  • Re-attempt strategyfailed-only (the default; retry only what failed) or full-body (re-run the whole body). This is where re-attempt granularity is chosen, not on the run form.
  • Stop limits — the same six numeric limits as the run form's folded Limits panel, each clamped at its daemon ceiling. Configure sets the per-Loop default; the run form can still override per run.

Reset to defaults restores the definition defaults and failed-only. Save persists the overlay.

What needs a fork

Configure never changes structure. These belong to the visual editor or a definition edit:

  • node order or DAG structure;
  • node kinds;
  • input declarations;
  • the contract's terminal states or shape;
  • the goal or definition-of-done.

How it stores and merges

Configure writes a separate per-Loop config store keyed (workspace_id, loop_name) — distinct from the definition, which stays filesystem-as-truth. It is read and written through GET/PUT /loops/:name/config, compozy loop configure, and compozy__loop_configure.

The effective config a run actually uses is a four-layer merge, each layer bounded by the compile-time ceilings:

  1. the definition's own defaults,
  2. [loops.defaults.*] in config.toml,
  3. this per-Loop configure overlay,
  4. any per-run overrides from the run form.

Node reliability resolves more narrowly: authored node fields override the stored per-Loop lifecycle layer, which overrides the matching delivery or watch default. The resolved values are pinned when work is admitted, so a config reload never rewrites a running attempt. compozy loop inspect -o json reports the effective lifecycle values and a source for each field.

GET /loops/:name/config returns the stored per-Loop override as config and the daemon-resolved first three layers as effective_config. A missing override is config: null; it is not a missing Loop and does not prevent clients from reading the effective values. Reading or writing config for a missing Loop returns 404 and creates no detached override.

Loop run-agent workers use Loop-owned runtime_defaults and runtime_rules; they do not read [[tasks.run.task_runtime_rules]]. Runtime fields resolve independently and the daemon persists the final binder-applied provider, model, reasoning, and provenance on each generation output. The current web sheet edits checks, gates, re-attempt strategy, and stop limits. Use the structured CLI, HTTP, or native-tool config surface to write runtime defaults or rules.

Use a config file

The two CLI write paths accept the same strict Loop config object as YAML or JSON. Field names use snake_case in both formats:

loop-config.yaml
iteration_cap: 3
no_progress_window: 10
gate_max_revisions: 10

Store the file as the Loop's workspace default with --file, or apply it only to one run with --config-file:

compozy loop configure --name reviews-watch --file loop-config.yaml --workspace .
compozy loop run --name reviews-watch --config-file loop-config.yaml --workspace .

Unknown fields fail before the CLI calls the daemon, so a misspelled key cannot create a partial override. JSON files use the same field names.

Lifecycle defaults

The current Configure sheet does not edit lifecycle policy. Set these operator defaults under both [loops.defaults.delivery] and [loops.defaults.watch] in config.toml:

GroupKeysShipped defaults
retrymax_attempts, backoff_base, backoff_max3, 1s, 30s
livenesssilence_window30m; 0 disables flags
resumedeath_streak_limit3
predicatescost_limit10000
waitsadmission_attempts, admission_retry_interval3, 60s
admissiontombstone_horizon168h
autopauseordered { match, action = "pause" } rulesnone

[loops.breaker] is global rather than per kind because target health is shared within a workspace. Its defaults are threshold = 5 consecutive transport failures and probe_interval = "60s". See the config.toml reference for complete TOML.

The scalar lifecycle paths and the two breaker paths are available through structured config get/set/unset surfaces. For example:

compozy config set loops.defaults.delivery.retry.max_attempts 4
compozy config set loops.breaker.probe_interval 90s

autopause is deliberately file-owned: rules are ordered, append-merged, and first match wins, so agents cannot mutate them one scalar at a time. Node-level retry, deadline, and related DSL fields remain author-owned structure.

From an agent

Configure is fully agent-manageable — the same overlay, written structurally:

ActionCLIHTTPNative tool
Read configGET /loops/:name/configcompozy__loop_inspect (definition)
Write configcompozy loop configure --set k=vPUT /loops/:name/configcompozy__loop_configure

See the compozy loop CLI and the Loops API.

On this page