LoopExec is a deterministic runtime for bounded agentic execution loops. Work progresses through an external check and stops on a computed reason — never because an agent says it is done.
Supply a work command and an external check. LoopExec bounds execution, detects regression, no progress and oscillation, applies integrity guards, and records replayable receipts. Opt-in workflows add usage evidence, scoped model-call budgets and candidate restoration. Isolation orchestration composes with operator-provided container, egress and credential hooks.
The runtime governs execution; adapters supply models, checks and infrastructure. Synthetic creative examples prove runtime mechanics, not production model quality. Observed spending cannot enforce a provider-side cap, a signature file requires explicit verification, and retaining a candidate does not establish owner acceptance.
Getting Started begins with an offline deterministic proof. SMALL describes plans, constraints, progress and handoff; LoopExec drives one bounded loop. SMALL is optional for consumers.
The normative contract is SPEC.md. The current source implements bounded execution, determinism probing, integrity and regression guards, offline-verifiable receipts, and opt-in unattended workflows. See SPEC.md section 11 for the implemented scope and remaining sub-parts.
Source identity: v0.5.0-rc.1, a release candidate adding visible model profiles and task/role assignments. See candidate notes; the Releases page establishes publication status. Workflow thresholds remain supplied by each integration.
Implemented through v0.4.0:
-
Real bounded
runloop: iterates--execthen--checkuntil the check passes (success_condition_met), a bound trips (max_iterations_reached), or work fails (execution_failure); "no check, no loop"; computed halt reasons mapped to a stable exit-code class; typed JSONL receipts (.loopexec/run-<id>.jsonl) and atomic durable state. -
probe-check- determinism as a 95% confidence bound (rule of three);doctor- precondition gate (determinism + isolation preflight). -
Set-based progress + no-regression ratchet (oscillation / no-progress / regression halts) +
explain-halt(raise-the-limit vs do-not-retry). -
Metric-integrity gate (
run --integrity-cmd): guards dominate success (collected-set monotonicity). -
Receipt pinning (model tuple + sampling + context manifest + cost + check fingerprint);
replay(verify a receipt offline, agent-free) andattest(HMAC-sign + verify). -
reexecute(live re-run distribution),escalate/watch(heartbeat + structured packet), comprehensionackgate. -
build-context- budgeted, workdir-confined, symlink-safe relevant-file slice. -
Shared subprocess deadlines/cancellation with bounded diagnostics; fail-closed collectors.
-
run --workflow: exact usage/reservations, explicit strict/observed/unknown money, numeric progress/patience, and manifest-based best-candidate restoration. -
An offline Go creative-workflow adapter with independent simulated roles and candidate-bound signed reviews. No Python loop, model key, network, or engine required.
-
Opt-in shared model-call budgets across run IDs, with pinned per-phase allowances and durable pre-call reservations. See the offline adapter proof.
-
isolate- two-zone orchestration: detached-clone sandbox + per-run minted/revoked credential + rendered/launched exec/agent zones. -
Global
--jsonoutput, explicit exit-code contract, contract and unit tests, GitHub Actions CI (gofmt,go vet,go test ./...).
See SPEC.md section 11:
- The operator-provided infra
isolatecomposes with: the container engine, the auditing egress proxy, and the provider key API (--runtime/--egress-proxy/--mint-cmd+--revoke-cmd). - Provider-specific live usage wrappers; the deeper metric-integrity layers (assertion-count / coverage-floor);
probe-checkadversarial perturbation + the in-loop sequential monitor. - The
import_closure/dep_graphcontext-relevance tiers; github/slack escalation channels; the kill-the-PID watchdog actuator. - Full SMALL-driven
task_listloop execution; container, Nix, or remote substrates and multi-worker orchestration.
go install github.com/justyn-clark/loopexec/cmd/loopexec@latestRequires Go 1.26 or newer. For the published v0.4.1 install, use @v0.4.1.
That release does not contain model assignments. After RC publication, pin
@v0.5.0-rc.1 to test this feature; @latest stays on stable.
Prebuilt archives and SHA256 checksums are linked from
GitHub Releases.
loopexec --version prints the installed version; loopexec version --json emits its machine-readable identity. See the release notes for compatibility and platform limits.
SMALL is optional for LoopExec consumers. This repository uses the tracked .small/ files for its own development audit; CI requires a canonical progress update with source or documentation changes and validates the tracked state. The SMALL integration guide covers SMALL CLI v1.1.2 with legacy v1 artifacts and opt-in collaborative v2 sessions; LoopExec remains the loop governor.
Run the built-in deterministic demo with no model, API key, Python runner, or network access:
loopexec demoThe command creates a red local fixture, sends it through the real bounded loop, repairs it, observes the external check turn green, writes a typed JSONL receipt, and verifies the recorded check fingerprint through the same verifier used by loopexec replay. It proves the execution/check/receipt/replay contract, not agent intelligence.
For your own work command and check, follow Getting Started.
The receipt path in the output identifies the retained temporary workdir. To keep the proof at a known path, pass a fresh directory with --workdir <dir>; demo refuses to overwrite an existing .loopexec directory or status.txt fixture.
From the repo root:
go build ./cmd/loopexecgo test ./...CI enforces:
gofmtgo vet ./...go test ./...
Code/tooling changes also require canonical documentation and changelog updates. The generated CLI and JSON contract is checked against the runtime. Every release packages source-bound docs and publication requires matching deployed content. See continuity policy for enforced source-bound release gates and the operator/account boundary.
The implemented CLI returns deterministic human or JSON output.
loopexec init/demo/run/status/check/steploopexec probe-check/doctor/explain-haltloopexec replay/attest/report/reexecuteloopexec escalate/watch/ackloopexec build-context/isolate/inspect-costloopexec budget status/budget reservefor cross-run child-call limits
See docs/cli.md for flags and exit semantics. The opt-in scoped budget reserves a child model call before an adapter launches it; changing the run ID does not reset the allowance. It counts calls, not tokens or dollars.
See acceptance and evidence for general-purpose objective, retention, convergence and owner-decision boundaries. The creative verification guide is an optional example. The status and roadmap distinguishes published capabilities, source changes, and remaining work.
--json- emit exactly one JSON object to stdout
loopexec init
# A real bounded loop: run the work command, then the check, until green or a bound trips.
loopexec run --json --check "go test ./..." --exec "make fix" --max-iterations 10
loopexec status --run-id local --iteration 1
loopexec checkExample JSON response (a converged run):
{
"tool": "loopexec",
"version": "0.4.1",
"status": "halted",
"run_id": "local",
"iteration": 3,
"halt_reason": "success_condition_met",
"check_exit": 0,
"receipt": ".loopexec/run-local.jsonl",
"errors": []
}The halt_reason string is the stable contract; the exit code is its coarse class (SPEC section 5). Every class 13-19 emits today alongside the base 0/10/12/20/30/40/50 (class 18, budget_exceeded / cost_anomaly, via inspect-cost and workflow runs; class 15, check_inadequate, via the doctor --mutate-cmd adequacy canary); only class 11's task-list reasons (no_actionable_tasks / human_required) remain reserved, and those belong to the task_list loop topology. A few individual reasons inside active classes, the doctor coverage-delta and hermeticity tiers, are still Planned (see SPEC section 11).
0success (loop ran, no halt)10converged:success_condition_met11terminal-blocked:no_actionable_tasks,human_required12iteration-cap:max_iterations_reached13integrity:blocked_path_modified,reward_hacking_detected,metric_integrity_violation14oracle-untrusted:check_flaky,check_not_hermetic,hermeticity_violation15check-inadequate:check_inadequate16resumable-judgment:escalation_pending,reviewer_rejected17no-convergence:no_progress_detected,oscillation_detected,infeasible_suspected18budget:budget_exceeded,cost_anomaly19liveness/drift:heartbeat_stale,model_drift_detected,comprehension_debt_exceeded20invariant failed30workspace invalid or missing40execution failure50internal error
SPEC.md canonical, normative contract (source of truth)
cmd/loopexec/ loopexec CLI
docs/architecture.md implemented runtime architecture
docs/cli.md current loopexec command contract
docs/integrations.md integration guidance for the implemented CLI
docs/loop-contract.md task_list mode profile of SPEC.md
.github/workflows/ci.yml fmt/vet/test CI gate
scripts/feeltest.sh deterministic shell feel test helper
This repo is SMALL-governed at the repository level. The implemented loopexec binary runs the check_fixpoint loop standalone; the full SMALL-driven task_list loop is the profile described in docs/loop-contract.md.
Read the docs in this order:
SPEC.md- the canonical, normative contract (source of truth for the binary and the docs site)docs/cli.md- what the current CLI actually doesdocs/integrations.md- how to integrate with the current implementationdocs/architecture.md- implemented architecture and integration boundariesdocs/loop-contract.md- thetask_listmode profile
- Docs site: https://loopexec.dev
- SMALL Protocol: https://smallprotocol.dev
MIT. See LICENSE.
mkdir -p build
go build -o build/loopexec ./cmd/loopexec
go build -o build/creative-workflow ./examples/creative-workflow
./scripts/creative-proof.sh ./build/loopexec ./build/creative-workflow build/creative-proofThe proof asserts convergence, budget stop before further work, regression
restoration, stale-evidence rejection, critic skip after technical failure, and a
four-attempt cap. Expected convergence is loopexec exit 10 (external check exit 0).
All fixture scores, captures, and charges are synthetic; they prove runtime wiring.
Read the workflow contract for interfaces, receipts, trust
boundaries, and live setup. Migration: a nonzero --budget-usd now requires
explicit workflow metering; legacy set-based progress remains the default.