loop-agent
v0.5.1
Published
Layered loop orchestration plugin with generated Host adapter projections.
Maintainers
Readme
Loop Agent
You sleep. I’ll loop.
Loop Agent ships generated adapter projections for Codex and Claude Code. Adapter projection does not imply executable Host support; the generated Host manifests record that state separately. The plugin helps capable—but imperfect—models complete long-running work through layered planning, isolated execution, evidence-backed review, repair, and acceptance.
Loop Agent does not perform external writes merely because a task was inspected or diagnosed. Publishing, pushing, tagging, messaging, and other external mutations still require explicit user authorization.
For a safe first look after installation, invoke loop-agent:loop-help.
The plugin separates the loop roles into distinct processes:
- L1 Supervisor: Entry and meta-supervisor. Selects the delivery Profile, commissions one fresh L2 process per Delivery Cycle, owns Client Acceptance, and samples L3 evidence only for risk or anomaly.
- L1 Bootstrap Generator: Turns a short user request into an Engagement Brief and command-plane launch package.
- L2 Planner: Plans and supervises one Delivery Cycle. Two planner routes: goal workflow planner for multi-step objectives, narrow planner for bounded single-target work. Owns Vendor Acceptance.
- L3 Worker: Executes one assigned leaf task. The canonical Skill is
loop-l3-delivery-task-runner. The legacy nameloop-l3-workflow-workeris a compatibility alias that resolves to the same Skill.
Delivery Profiles
Profiles reuse the common L1/L2/L3 runtime protocol and add no additional layer:
post_design_automated_delivery: Automates technical design/development/test when Requirements and Product Design baselines are approved.full_software_delivery: Models each approved stage as a separate Delivery Cycle, pausing at declared HITL gates.editorial_delivery: Same task/phase machinery with editor, researcher, writer, fact-checker, and reviewer Expert Roles.
Process Model
Each layer runs as a separate process:
- L1 launches L2 via
launch-layer-process.mjswith a bounded timeout. - L2 launches L3 via the same launcher for each leaf task.
- L3 writes a
delivery-task-result.jsonterminal contract. - L2 writes a Vendor Acceptance Decision (
acceptance-decision.json). - L1 reads the Delivery Package and writes a Client Acceptance Decision.
- Rework at the Vendor level uses new task IDs and fresh L3 processes. Rework at the Client level creates a new Delivery Cycle with a fresh L2 process.
External Run Root
The run directory is external to the plugin. The Engagement Brief records the run_root and
target_repository paths. The plugin never embeds project-specific paths in generic skills.
Status
The core runtime scripts and stable contract schemas pass their test gates. The integration test
exercises the full L1→L2→L3 delivery chain with rework and acceptance separation using fake child
processes and real deterministic runtime scripts. Three candidate contracts
(versioned-fixture-catalog, versioned-observer-binding, execution-grading) are at
candidate-1 maturity and are not part of the stable production surface.
Host adapter projection and executable Host support are separate states. The current generated
manifests mark Claude Code, Codex, and WorkBuddy as CANDIDATE_BINDABLE; this means a validated
local runtime binding can be constructed for the capabilities listed in capability_scope, not
that every Loop workflow is supported or that a release-verification receipt exists. Codex supports
only detached one-shot prompt input with JSONL event output. It does not execute Workflow Execution
Packages or act as the inner L1→L2→L3 host. Claude Code is the only current
workflow-package-chain host. Kimi Code remains UNAVAILABLE until its manifest carries the
required receipt.
External Precompiled Workflow Ingress
An external caller may provide one prepared workflow source or one compiled Workflow Execution
Package without fabricating an L2 context. The source must be inside the Loop run_dir. First run
scripts/verify-workflow-ingress.mjs with the explicit inner Host Profile and runtime binding. Its
JSON output freezes the transitive ingress digest. Then pass the same kind, path, and digest to
scripts/launch-l1-process.mjs through --workflow-ingress-kind, --workflow-ingress-path, and
--workflow-ingress-digest. The L1 launch also requires two distinct Host triples: the ordinary
--host-profile-id, --host-profile-digest, and --host-runtime-binding select the outer L1
watchdog, while --workflow-inner-host-profile-id, --workflow-inner-host-profile-digest, and
--workflow-inner-host-runtime-binding select the inner workflow-package host. All six values are
explicit; Loop does not infer an inner host from ambient configuration or reuse the outer binding.
The ingress is valid only for the single_task route. Loop carries its immutable binding through
the real L1→L2 request, snapshots it inside the real L2 attempt, recompiles it for that attempt's
control endpoint, and launches the ordinary L3 package path. L2 and L1 still perform vendor and
client acceptance. For a Codex-based outer audit, record outer_host=codex and
inner_loop_host=claude-code separately; a Codex detached receipt is not evidence that Codex ran
the inner workflow chain.
Watchdog shutdown provides best-effort cleanup for observable, same-user descendants that cooperate with the process boundary. It does not claim complete containment of adversarial double-forked or otherwise unobservable processes; callers that need that guarantee must add an operating-system containment boundary.
Stable Gate
npm test is the stable long-task gate. It runs all shared deterministic, contract, and integration
tests. The stable boundary covers:
- L1 supervisor and bootstrap generator
- L2 goal-workflow-planner and narrow-planner
- L3 delivery-task-runner and workflow-worker
- Workflow execution packages and process evidence
- Acceptance chains (vendor and client)
- Layer launcher and watchdog
- Adapter build, install, and package distribution
Self-Iteration Boundaries
The stable gate includes the bounded production entry run-self-iteration-production.mjs. It
keeps the target read-only, records baseline evidence, performs three-way failure attribution,
permits at most one isolated repair, launches a fresh L3 retest process, and binds the structured
result to the exact attempted action and input identities.
npm run test:self-iteration remains the broader experimental gate for the 3.0 control plane,
oracle vault, case isolation, evaluation-round lifecycle, two-level semantic acceptance, and
external finalization. Those control-plane artifacts remain available for research and
compatibility, but are not required by the bounded production route and must not be treated as
live acceptance evidence merely because deterministic tests pass.
Layout
.agents/plugins/marketplace.json
.claude-plugin/
.codex-plugin/plugin.json
skills/
scripts/
references/
profiles/Project-specific rules belong in profiles. The generic skills should not hard-code a target repository, product, or private workflow.
Method Lock Resolution
scripts/resolve-method-lock.mjs is the stable executable for L2 method-lock
operations. It reads a validated method-registry config and explicit query
filters, invokes queryMethods, resolveMethod, selectAndLockMethod (no
duplication), and writes exactly one validated method-lock JSON result.
# Lock the first matching method (default selection policy)
node scripts/resolve-method-lock.mjs \
--config method-registry.json \
--output method-lock.json
# Lock an explicit method reference
node scripts/resolve-method-lock.mjs \
--config method-registry.json \
--output method-lock.json \
--ref plugin:my-skill
# Strict mode — fails closed on any registry error
node scripts/resolve-method-lock.mjs \
--config method-registry.json \
--output method-lock.json \
--mode strict
# With query filters
node scripts/resolve-method-lock.mjs \
--config method-registry.json \
--output method-lock.json \
--domain delivery --kind workflowConfig fields: command, command_args, index_path, plugin_roots,
project_roots, timeout_ms, max_output_bytes, mode.
Modes: compatible (default) falls back to a builtin lock on soft errors
(COMMAND_MISSING, NO_QUERY_MATCH, UNCONFIGURED). strict fails closed.
Error codes: COMMAND_MISSING, NO_QUERY_MATCH, INPUT_READ_FAILED,
STALE_EFFECTIVE_INDEX, INVALID_SELECTION, REGISTRY_LOCK_FAILED.
Lock fields: ref, kind, provider, index_content_hashes,
verification, diagnostics, selection_source.
The script is projected into the adapters by the explicit generation command shown below.
npm run build only checks that the checked-in projections have not drifted.
npm run build:generate -- \
--foundation-install-root /absolute/foundation-install \
--foundation-verification-receipt /absolute/foundation-verify/release-run.json
npm run buildGeneration requires an exact, canonical Foundation 0.8.1 installation root and its VERIFIED
release receipt. The generator compares the install lock and all three installed package identities
with the approved npm integrities in that receipt's release plan. The no-argument build command
remains read-only and checks the managed projections.
External L1 preparation and accepted delivery export
External orchestrators can prepare the canonical L1 runtime context without constructing private
runtime JSON. The command validates an existing engagement brief, requires its run_root and
target_repository to match the explicit directories, then freezes the brief and objective before
writing .loop-agent-context.json exclusively.
node scripts/prepare-l1-runtime-context.mjs \
--run-dir /absolute/run \
--target-repository /absolute/target \
--plugin-dir /absolute/loop-agent \
--run-id RUN-001 --round-number 1 \
--engagement-brief /absolute/engagement-brief.json \
--delivery-cycle-id DC-001 --l1-process-id PROC-L1-001 \
--objective-file /absolute/objective.md \
--model-context-limit-tokens 200000After the ordinary two-level acceptance chain finishes, the export command follows that accepted
lineage and creates one portable directory. delivery-task-result.json, every declared evidence
file, every verification record, and export-receipt.json are copied or derived from the verified
run; an existing output directory is never overwritten.
node scripts/export-accepted-delivery-result.mjs \
--run-dir /absolute/run \
--output /absolute/accepted-delivery-exportValidation
node scripts/check-skills.mjs
node scripts/check-loop-token-budgets.mjs
npm test # stable long-task gate (all shared tests)
npm run test:self-iteration # experimental self-learning gate (0 known failures)
npm run build:checkSmoke Tests
Smoke tests launch real Claude processes and exercise the full L1/L2/L3 delivery chain.
They are opt-in and never run during default npm test.
# Skip (default) — exits 0 with a clear skip reason
npm run test:smoke
# Direct layered smoke — L1-L3 real Claude delivery
LOOP_AGENT_REAL_SMOKE=1 npm run test:smoke
# Direct filter only
LOOP_AGENT_REAL_SMOKE=1 LOOP_AGENT_REAL_SMOKE_FILTER=direct npm run test:smoke
# Self-iteration — deterministic harness + real self-iteration smoke
LOOP_AGENT_REAL_SMOKE=1 LOOP_AGENT_REAL_SMOKE_FILTER=self-iteration npm run test:smoke
# L1-L2-L3 chain — experimental three-layer smoke candidate, opt-in via LOOP_AGENT_CHAIN_SMOKE (~30-60 min)
LOOP_AGENT_REAL_SMOKE=1 LOOP_AGENT_CHAIN_SMOKE=1 LOOP_AGENT_REAL_SMOKE_FILTER=chain npm run test:smokeThe chain smoke is an opt-in experimental candidate: a single passing run proves only that run's internal smoke assertions, not production acceptance.
Filters: direct, self-iteration, chain. Unknown filters exit nonzero with a clear error.
Runtime cost: The direct smoke test launches a real Claude process with a 15-minute timeout. The self-iteration smoke launches a multi-phase workflow with two trial cycles. Budget 20+ minutes for a full smoke run. The chain test launches three real Claude processes (L1→L2→L3) with the full delivery chain; budget 30-60 minutes.
Evidence location: Run artifacts are preserved under runs/real-smoke/direct-<timestamp>/ or
runs/real-smoke/self-iteration-<timestamp>/. Each run contains target-review snapshots, workflow
evidence, delivery-task-result, and watchdog evidence.
Troubleshooting:
- Claude CLI not found: Install Claude CLI and ensure
claude --versionreports >= 2.1.172. - Version below floor: Update Claude CLI. The minimum supported version is 2.1.172.
- Smoke test hangs: Check the watchdog evidence JSON under the run directory. The stale timer defaults to 600 seconds and the max timer to 900 seconds.
- Unknown filter error: Use one of the known filters:
direct,self-iteration,chain. - Chain test timeout: The chain test has a 95-minute timeout. If it hangs, check L1/L2/L3 process evidence and execution logs under the run directory. Each layer has a 600-second stream idle timer.
Install from npm
npm install [email protected]After installation, invoke loop-agent:loop-help to inspect supported entry points and environment
requirements before starting a layered run.
Install Locally
npm run build
npm run install:global
codex plugin add loop-agent@personalThe installer writes the Codex adapter to ~/plugins/loop-agent, registers it in the personal
Codex marketplace, writes the Claude Code adapter to ~/.claude/plugins/loop-agent, and syncs the
skill folders into ~/.claude/skills.
Version Floor
Requires Node.js >= 22.0.0.
