loopy-loop runs long-running AI agent workflows inside your repository.
It turns a goal file in your repository into an inspectable sequence of agent
iterations: plan, implement, review, optionally evaluate, record evidence, and
continue until the goal is met or the loop hits a terminal blocker.
The value is control and durability. Instead of asking one agent to solve a large task in one fragile chat, loopy-loop gives each durable goal layer a persistent session directory, immutable attempt assignments, explicit stop conditions, and structured evidence. You can stop and resume the service, append instructions while it runs, audit what happened, inspect attempt traces, and keep the actual project changes in normal git branches and PRs.
Under the hood, loopy-loop runs a small FastAPI coordinator and a single
worker. The coordinator owns the loop state and chooses the next workflow. The
worker runs assignments through
team-harness, which can delegate
to agent CLIs such as Codex, Claude Code, and Gemini. The packaged
inner_outer_eval template also uses
eval-banana conventions for
session-scoped evaluation checks; eval-banana installs automatically as a
loopy-loop dependency.
Install the CLI from the official PyPI package.
With uv, install it as a command-line tool:
uv tool install loopy-loopOr with pip:
pip install loopy-loopFor development inside this repository:
uv sync --extra devThe stock protocol-v3 contract spans three owned projects. It requires
team-harness>=0.5.4 for caller-owned run records, nested assignment context,
capability-roster propagation, and canonical agent streams. When a workflow
uses evaluation, eval-banana>=0.5.0 supplies hermetic
--no-project-config runs, explicit harness selection, canonical check
digests, retained judge evidence, and the --result-out provenance-stamped
result the stock inner_outer_eval eval runner writes to eval_results.md
(D14). Install compatible releases of all three projects together.
For coordinated development across the repositories, install the corresponding
team-harness and eval-banana checkouts as editable dependencies:
uv pip install -e /path/to/team-harness -e /path/to/eval-bananaAn older dependency is not a reduced-fidelity mode: a fresh stock session fails registration clearly if its worker or harness cannot advertise the required protocol-v3 capabilities.
This repo also ships an Agent Skill that teaches Claude Code, Codex, and compatible agents how to set up and run loopy-loop in another target repo.
npx skills add https://github.com/writeitai/loopy-loop --skill loopy-loopThe skill source lives under skills/loopy-loop/.
Run this from the repository you want agents to work on:
loopy init --template inner_outer_evalThis is the recommended starting template. It creates:
loopy_loop_config.yamlloopy_loop_goal.txt.loopy_loop/workflow_sets/inner_outer_eval/contract.yaml.loopy_loop/workflow_sets/inner_outer_eval/workflows/outer/.loopy_loop/workflow_sets/inner_outer_eval/workflows/inner/.loopy_loop/workflow_sets/inner_outer_eval/workflows/eval_reviewer/.loopy_loop/workflow_sets/inner_outer_eval/workflows/eval_runner/- additive
.gitignoreentries for session state, traces, the trace-finalization outbox, repository identity, and root state/lock/archive files
For a double loop, initialize the program-level template instead:
loopy init --template pm_planner_dispatcherIts planner works in high-level phase or milestone outcomes. Its dispatcher
turns one selected outcome into an inner_outer_eval child session, whose
outer role owns the detailed leaf plan. The program layer deliberately has no
scheduled eval roles; the planner may coordinate optional program-level or
goal-required final evaluation itself.
loopy init is idempotent. It creates missing files and leaves existing files
alone — except .gitignore, which is updated additively with all runtime ignore
rules.
The loop goal lives in loopy_loop_goal.txt. Replace the scaffolded example
with the real target, including constraints and observable completion criteria.
Example:
Implement passwordless email login.
Completion criteria:
- Users can request a one-time login link from the sign-in page.
- The link expires after 15 minutes and cannot be reused.
- Existing password login keeps working.
- Tests cover token expiry, token reuse, and successful login.
- README documents required environment variables.
Keep the goal specific enough that its orchestrator and reviewers can assess
whether the scoped outcome is complete. For one-off overrides, start the
coordinator with --goal-file PATH; the file is copied into the session as
goal.md.
Start the coordinator in one terminal:
loopy coordinator --host 127.0.0.1 --port 8080Start a worker in another terminal:
loopy worker --coordinator http://127.0.0.1:8080Useful control commands:
loopy status
loopy status --json
loopy update Prioritize the failing integration test
loopy stop
loopy stop --force
loopy reload
loopy traces listIf the coordinator stops while a session is still running, restart it with:
loopy coordinator --host 127.0.0.1 --port 8080 --resumeThe default templates use team_harness_provider: "codex", so the coordinator
uses local Codex authentication. If you switch to an OpenAI-compatible provider,
export the environment variable named in team_harness_api_key_env, usually
OPENROUTER_API_KEY, in both the coordinator and worker shells.
At a high level:
loopy initwrites a root config, a goal file, and workflow files into the target repo.loopy coordinatorloadsloopy_loop_config.yaml, freezes the goal and stock protocol-v3 workflow contract, creates a root session under.loopy_loop/sessions/, and exposes/registerand/finished.- A protocol-v3 worker advertises its Loopy and team-harness capabilities plus repository identity. The coordinator dispatches only to a matching checkout with the required capability-roster context support.
- For each attempt, the coordinator freezes the exact workflow config/prompt/contract, an assignment, and a conditional scheduler view. The assignment gives the harness coordinator absolute paths to its scoped goal, plan, tasks, decisions, handoff, workflow roster, scheduler view, capability roster, outputs, and trace directory. Durable receipts still use portable logical references.
- Before calling a model, the worker verifies that assignment and its trace, records the exact task response, and writes rendered prompt and git-before evidence.
team-harnessruns the coordinator model. It may dynamically spawn Codex, Claude Code, Gemini, or another enabled family. Each direct spawn receives the current layer identity, relevant absolute state paths, the frozen capability roster, and its focused delegated assignment. The workflow coordinator remains accountable for integration.- The worker posts a completion bound to the exact worker, repository,
attempt, and assignment hash. A successful iteration means the harness ran
without an execution error; it does not mean the work was semantically
accepted. The coordinator records and seals the observable execution under
.loopy_loop/traces/. - The coordinator enforces protocol facts such as identity, topology,
schemas, hashes, and reference containment. The workflow contract's durable
orchestrator decides semantic acceptance and completion from the available
evidence. A terminal protocol-v3 session receives a topology-neutral
session_outcome.jsonthat links its control, handoff, and available evidence.
The inner_outer_eval template is organized around four workflows:
outer: owns the layer plan, selects and accepts leaves, maintains compact resumption state and the upward handoff, and alone decides successful completion for this layer.inner: implements and verifies the one leaf selected byouter, then reports evidence upward. It does not create the layer plan or accept its own work.eval_reviewer: may create or refresh outcome-oriented, session-scopedharness_judgechecks as advisory evidence.eval_runner: may run those checks and publish provenance-rich receipts forouterto weigh. It does not writegoal_check.jsonor successful terminal control.
The pm_planner_dispatcher template has two durable roles:
planner: owns a high-level phase/milestone plan, accepts or reroutes child outcomes, maintains the program handoff, and decides program completion.dispatcher: faithfully turns the one selected milestone outcome into a child request. It does not pre-plan the child's leaves or accept the child's result.
Evaluation is optional evidence in both sets. The completion owner can run or
delegate checks, wait for a scheduled eval role, or decide from stronger
repository, review, child, test, git, or delivery evidence. Protocol-v3
control.json binds goal_met to the exact current orchestrator attempt;
evidence_refs, plural eval_receipt_refs, and handoff_ref are optional,
but any cited reference must validate. unresolvable_error remains the
last-resort stop for a genuinely terminal blocker after autonomous routes are
exhausted.
The loop does not hide state inside a chat transcript. Each layer has a visible
semantic spine in project_state/—plan, stable task records, current state,
decisions, accepted-work ledger, optional eval index, and rolling handoff. A
session-frozen workflow roster explains every scheduled role; an
attempt-frozen scheduler view forecasts the next role under explicit
assumptions; and the root capability roster shows every enabled harness family
across the configured strength tiers. Detailed prompts, model turns, tool and
spawn I/O, raw eval reports, and verbose logs live separately in the gitignored
trace tree.
After initialization, the target repo has this shape:
target repo/
├── loopy_loop_config.yaml
├── loopy_loop_goal.txt
└── .loopy_loop/
├── repository.json # ignored checkout identity
├── workflow_sets/
│ └── <workflow_set>/
│ ├── contract.yaml
│ └── workflows/<workflow_id>/
│ ├── config.yaml
│ └── prompt.txt
├── sessions/
│ └── <session_id>/
│ ├── goal.md
│ ├── goal_contract.json
│ ├── session.json
│ ├── workflow_contract.json
│ ├── workflow_roster.json
│ ├── harness_capability_roster.json # root, shared by session tree
│ ├── state.json
│ ├── control.json # written only to stop
│ ├── session_outcome.json # terminal projection
│ ├── inputs/{user_updates.jsonl,accepted_request.json,artifacts/}
│ ├── project_state/
│ │ ├── plan.md
│ │ ├── tasks/
│ │ ├── current_state.md
│ │ ├── decisions/
│ │ ├── finished.md
│ │ ├── eval_state.md
│ │ └── handoff.json
│ ├── eval_checks/
│ ├── eval_receipts/
│ ├── child_requests/{pending,accepted,rejected}/
│ ├── child_outcomes/
│ ├── parent_acceptance/
│ ├── git_receipts/
│ ├── delivery_receipts/
│ ├── trace_seals/
│ ├── iterations/<n>/<role>/workflow_snapshot/<attempt>/
│ │ ├── assignment.json
│ │ └── scheduler_view.json
│ └── children/<child_session_id>/...
├── traces/<root>/sessions/<session>/attempts/<attempt>/
└── trace_finalization_outbox/
Workflow definitions are part of the repo and should usually be committed.
Session directories, traces, the trace-finalization outbox, and
repository.json are runtime output and are ignored by default. Session
state/evidence is required for recovery; trace retention is independent from
that compact truth.
Root config lives at loopy_loop_config.yaml:
goal_file: loopy_loop_goal.txt
workflow_set: inner_outer_eval
max_turns: 160
goal_check_consecutive_failures_cap: 3
# workflow_consecutive_failures_cap: 5
team_harness_provider: "codex"
team_harness_model: "gpt-5.5"
team_harness_agents:
- "codex"
- "claude"
- "gemini"
team_harness_agent_models:
codex: "gpt-5.5"
claude: "claude-opus-4-8"
gemini: "gemini-3.5-flash"
team_harness_agent_reasoning_efforts:
codex: "high"
team_harness_api_base: "https://openrouter.ai/api/v1"
team_harness_api_key_env: "OPENROUTER_API_KEY"Important rules:
-
workflow_setselects the default workflow set for new sessions. -
goal_fileis resolved relative toloopy_loop_config.yaml. -
Inline
goalvalues in YAML are rejected; the goal should live in a file. -
max_turnsis the maximum number of completed workflow iterations. -
team_harness_modelcontrols the team-harness coordinator model. -
team_harness_agent_modelscontrols default models for worker subprocesses. -
model_tiers(optional) maps semantic strength → enabled harness family →{model, effort}. The four stock tiers arefrontierfor maximum-capability and highest-stakes work,strongfor complex work,standardfor the balanced default, andeconomyfor bounded low-risk work. At root-session creation, Loopy freezes every family/tier cell—including unavailable cells— intoharness_capability_roster.json; the assignment and team-harness caller context carry that roster to coordinators and nested delegates. Agents choose proportionately and are encouraged to use another enabled family for useful independent review, especially during eval-check design. This remains guidance, not a quota or semantic gate (D8/D9).With
default_tierset, that tier derivesteam_harness_agent_modelsandteam_harness_agent_reasoning_efforts; it must cover every configured family, and the two flat mappings must be omitted. Withoutdefault_tier, flat per-family model settings appear as configuredstandardbundles.model_tiers: frontier: codex: {model: "<frontier codex model>", effort: "<effort>"} claude: {model: "<frontier claude model>", effort: "<effort>"} gemini: {model: "<frontier gemini model>", effort: "<effort>"} strong: codex: {model: "<strong codex model>", effort: "<effort>"} claude: {model: "<strong claude model>", effort: "<effort>"} gemini: {model: "<strong gemini model>", effort: "<effort>"} standard: codex: {model: "<standard codex model>", effort: "<effort>"} claude: {model: "<standard claude model>", effort: "<effort>"} gemini: {model: "<standard gemini model>", effort: "<effort>"} economy: codex: {model: "<economy codex model>", effort: "<effort>"} claude: {model: "<economy claude model>", effort: "<effort>"} gemini: {model: "<economy gemini model>", effort: "<effort>"} default_tier: "standard"
-
team_harness_api_baseis normalized by loopy-loop: trailing slash stripped,/v1appended when missing. -
team_harness_max_retries,team_harness_retry_base_delay_s, andteam_harness_retry_max_delay_sare optional retry controls for transient team-harness API/network errors. -
recovery_policy(drainby default, orreap) andrecovery_drain_timeout_scontrol what crash recovery does with agent processes left by an interrupted worker task: drain lets them finish within one shared bounded deadline; reap kills them immediately. The interrupted task is recorded as abandoned, consumes a turn, and then normal scheduling continues only if no stop condition fires. These are coordinator-side settings and are not part of the config snapshot sent to the worker. -
workflow_consecutive_failures_cap(default 5) is a per-workflow circuit breaker: that many consecutive failed iterations of the same workflow stop the loop withstop_reason="workflow_failure_cap"instead of retrying a wedged workflow untilmax_turns. Any success of the workflow resets its counter. Coordinator-side only; not part of the config snapshot sent to the worker. -
model_prices(optional, coordinator-side only) sets USD prices per 1M tokens for the harness coordinator model (prompt_usd_per_1m,completion_usd_per_1m); with prices set,loopy statusderives an estimated cost from the token ledger.max_cost_usd(optional, requiresmodel_prices) stops the loop withstop_reason="max_cost_usd"once the session tree's estimated cost reaches the budget. Cost covers the harness COORDINATOR model only — agent-CLI subprocesses (codex, claude, gemini) bill through their own accounts and are not measurable here.
An explicit loopy reload refreshes the running coordinator at the next task
boundary. It reloads workflow prompt.txt contents and these non-frozen,
coordinator-operational root settings: recovery_policy,
recovery_drain_timeout_s, workflow_consecutive_failures_cap,
max_cost_usd, and model_prices. The update is atomic across the
coordinator's cached workflow sets.
Reload deliberately does not change a live session's frozen goal or
config_snapshot (including harness provider/model/families, retry settings,
system prompt extension, criteria, and turn limit), its workflow membership or
config.yaml cadence, its workflow contract/roster, or its capability roster.
Those changes require a coordinator restart and a new session. A later child
workflow set that has never been loaded still freezes its on-disk definition
when that child session is created.
Workflow config lives beside each workflow prompt:
enabled: true
priority: 0
run_every: 1
must_follow: null
not_before_iteration: 0
run_on_start: false
run_after_successes: null
description: ""Workflow rules:
- The workflow id is the folder name under
.loopy_loop/workflow_sets/<workflow_set>/workflows/. prioritybreaks ties among eligible workflows; higher values run first.run_everyis based on completed iteration count, not wall clock.run_on_start=truemakes a workflow eligible before any successful workflow has run.must_followandrun_after_successes.workflow_idmust reference existing workflow ids.run_after_successescan schedule a workflow after every N successful runs of another workflow:
run_after_successes:
workflow_id: inner
every: 10Each workflow set declares contract.yaml. It names the layer kind, every
scheduled role's responsibility and accountable state paths, the one
orchestrator that owns planning/handoff/completion, optional advisory eval
authors and runners, terminal-blocker reporting roles, and whether the set uses
the recursive child interface. This is accountability metadata and prompt
context, not a filesystem ACL or semantic scheduler gate (D8). The stock sets
declare session_protocol_version: 3; the coordinator validates that the same
orchestration role owns plan, handoff, and successful completion. Historical
custom v1/v2 contracts remain resumable under the version frozen in their
session.
Each coordinator run creates a root under .loopy_loop/sessions/. Recursive
workflow sets may create child sessions beneath it, but one worker still
advances only the deepest active session. Session files hold compact durable
truth: scoped goals, the semantic state spine, workflow and capability rosters,
attempt scheduler views, task/recovery state, optional eval receipts, child
handoffs, control, terminal outcomes, and git/delivery evidence.
Each attempt freezes its workflow sources and assignment.json. The
assignment identifies the exact repository/session/workflow/attempt and gives
the harness coordinator absolute paths to its own layer state and outputs,
along with compact roster and scheduler context. Durable receipts use logical
session:/, parent:/, root:/, and trace: references so a stopped checkout
can move. Team-harness gives every direct spawn its own absolute
assignment/output paths, current layer identity, dynamic delegated task, and
inherited capability roster; the original coordinator remains accountable for
integrating the result.
Detailed observable execution goes to the separately gitignored
.loopy_loop/traces/<root>/sessions/<session>/attempts/<attempt>/ tree. It
contains the attempt manifest, protocol exchange, canonical team-harness run,
direct-agent streams, raw eval output, and verbose git/service records. These
are raw local records and may contain private data. A sealed manifest means
the local inventory is integrity-checked and its channel completeness is
known; it does not mean the attempt succeeded semantically.
Use loopy status and loopy events for compact progress, and loopy traces list plus loopy traces inspect for attempt detail. The complete artifact and
writer/reader reference is docs/session-layout.md.
Fresh stock workflow sets use protocol v3.
Each session evaluates its own scoped goal. A delivery child may prove its task
while its parent still needs integration or release work. In the packaged
inner_outer_eval set, outer accepts task evidence and owns completion. In
pm_planner_dispatcher, planner independently accepts child outcomes and
owns program completion. Eval roles and dynamically spawned delegates report
evidence to those orchestrators; they cannot complete another role's layer.
Successful protocol-v3 control is identity-bound to the exact current attempt and must come from the completion role frozen in the workflow contract:
{
"schema_version": 3,
"control_id": "control-goal-met-id",
"state": "stopped",
"reason": "Why this scoped goal is complete",
"stop_reason": "goal_met",
"producer": {
"session_id": "session-id",
"workflow_id": "outer",
"attempt_id": "attempt-id"
},
"evidence_refs": [],
"eval_receipt_refs": [],
"handoff_ref": "session:/project_state/handoff.json",
"created_at": "2026-07-17T12:00:00Z"
}The three evidence fields are optional. An orchestrator does not need an eval to complete the goal. A missing, malformed, stale, non-passing, or conflicting advisory eval from an otherwise completed harness attempt is recorded as a diagnostic; it does not consume workflow-failure budget or become an engine veto. If control cites an artifact, however, its reference, hash, subject, and accepted provenance must be truthful.
The one D5 escape hatch is an identity-bound v3 unresolvable_error. It is for
a genuinely terminal blocker after autonomous alternatives are exhausted:
{
"schema_version": 3,
"control_id": "control-blocker-id",
"state": "stopped",
"reason": "specific terminal blocker",
"stop_reason": "unresolvable_error",
"producer": {
"session_id": "session-id",
"workflow_id": "inner",
"attempt_id": "attempt-id"
},
"attempted_routes": ["retry", "re-scope", "alternate local route"],
"evidence_refs": ["session:/protocol_failures/blocker.json"],
"created_at": "2026-07-15T12:00:00Z"
}Both successful and blocker control must identify the exact current session/workflow/attempt. A blocker producer must be authorized by the frozen contract and list the autonomous routes already tried. Invalid control is archived with repair diagnostics instead of being treated as semantic truth. Repeated broken protocol or workflow execution is bounded by the configured failure caps.
The exact eval-receipt acceptance, successful control, blocker, and rejection rules are in docs/http-contract.md.
Workflow sets are mandatory. Even a single-loop repo uses:
.loopy_loop/workflow_sets/main/workflows/...
The older .loopy_loop/workflows/... layout is not loaded.
A session workflow may request one sequential child by atomically publishing a
unique *.json file under the assignment's absolute
child_requests/pending/ path. The same edge works recursively, so one-loop,
planner/dispatcher, and deeper trees use one state machine. Only the deepest
session runs an assignment; every ancestor is suspended on one child.
The child-request payload currently uses schema version 2. It carries parent
provenance, a child-scoped outcome and completion criteria, and hashed input
references. The coordinator archives the accepted request and copies each
verified input into the child's immutable inputs/ area. Child attempts
receive those logical references, hashes, and absolute local paths; later
parent edits cannot change accepted work.
The stock PM dispatcher first freezes the selected milestone and its planning
evidence under project_state/dispatch_inputs/<request_id>.json, then hashes
that immutable snapshot into the request. Only after the request is atomically
published does it add the factual request/lifecycle link to the stable task
record. Mutable plan and task prose are never used as hashed child inputs.
When the child stops, the engine writes its topology-neutral
session_outcome.json and links that result from the parent's factual child
outcome. The parent then writes a separate acceptance, rework, or reroute
decision after reviewing the child's handoff and evidence. Terminal
descendants unwind iteratively, so the same edge supports three or more active
depths without a depth-specific scheduler. Invalid requests are archived with
reasons and can be repaired autonomously.
The packaged pm_planner_dispatcher workflow set uses this contract for PM
orchestration:
plannermaintains the high-level phase/milestone plan, selects one outcome, reviews terminal child evidence, owns parent acceptance and the rolling handoff, and decides completion.dispatcherfreezes the selected outcome into an immutable request input, publishes the schema-v2 child request, and tracks factual lifecycle evidence without deciding acceptance.
The planner can run prepared final evaluations named by the target goal or delegate other program-level review when useful. These are planner inputs, not additional scheduled PM roles.
The coordinator exposes exactly two endpoints:
POST /registerPOST /finished
Both return a TaskResponse with action equal to "run" or "stop".
Fresh stock registration requires worker protocol 3 and the declared Loopy and team-harness capabilities, then binds the worker to the absolute checkout and stable repository ID. A missing capability returns HTTP 426 without advancing state. A run response identifies the frozen session/workflow/attempt assignment and its absolute protocol-v3 context; completion must echo its worker, repository, attempt, and assignment hash. Stale or mismatched completion cannot mutate current work. Durable local result and pending-completion records allow the next registration to recover an interrupted acknowledgement exactly once.
The authoritative payload models are RegisterRequest, TaskResponse, and
FinishedRequest in
src/loopy_loop/models.py. The recursive ownership
and compatibility rules are in docs/http-contract.md.
loopy init [--template default|inner_outer_eval|pm_planner_dispatcher]Scaffolds loopy-loop files. The compatibility default template creates only
the historical goal_check workflow. inner_outer_eval creates the
recommended protocol-v3 outer/inner/advisory-eval workflow set.
pm_planner_dispatcher creates the two-role planner/dispatcher program layer
and also ships the inner_outer_eval child set its dispatcher spawns, so a
clean init is executable end to end.
loopy coordinator --host 0.0.0.0 --port 8080 [--resume] [--workflow-set NAME] [--goal-file PATH]Runs the coordinator. --workflow-set and --goal-file override the root
config for the new session. --resume reuses a non-terminal latest session.
loopy worker --coordinator http://127.0.0.1:8080Runs a blocking worker until the coordinator returns action: "stop".
loopy status # stack, liveness, family health, usage, estimated cost
loopy status --json # the same status as machine-readable JSON
loopy status --watch # re-render every 2 seconds
loopy events # the active session's event stream
loopy events --follow # tail it live (--json for raw lines)
loopy update TEXT... # append to the deepest active layer
loopy update --session SESSION_ID TEXT...
loopy stop # tree-wide stop at the next safe boundary
loopy stop --force # also reap the active iteration's tracked agent CLIs
loopy reload # refresh prompts/operational config at the next boundary
loopy traces list
loopy traces inspect MANIFEST_OR_IDstatus prints the latest session state — the whole session stack while a
child runs (the live child is shown under its suspended parent), each
session's subtree token usage, and (with model_prices configured) estimated
cost. For an active task it also reports the newest mtime anywhere in that
attempt's raw/output tree as last activity: Ns ago, plus unexpired
rate_limited_families found in the current team-harness run.json as
model families rate-limited: FAMILY until TIME. Missing, incomplete, or
older run records are tolerated. status --json exposes per-session
last_activity_at, last_activity_age_s, rate_limit_data_available, and
rate_limited_families fields.
update appends the input record exactly as supplied; without --session it
is routed to the deepest active layer and later assignments append delivery
and acknowledgement records rather than editing history. stop projects root
stop intent through the whole active path and takes effect at the next
register or finish boundary. stop --force first records that same durable
tree-wide intent, then invokes the existing recovery reaper with immediate
reap policy and reports harness-run, settled-agent, and unsettled-agent
counts. Force reaping is limited to tracked process groups on the local host;
a remote active worker is reported as unreachable rather than pretending its
agents were stopped.
reload writes an ignored, atomic reload generation under the sessions root.
At the next task boundary, the coordinator reruns preflight and atomically
refreshes only the prompt/operational fields described in Configuration above.
It does not mutate an already-frozen attempt; the following attempt receives
the refreshed prompt in its own immutable workflow snapshot.
Trace commands accept a manifest ID, a trace root, or a manifest path confined
to this repository's .loopy_loop/traces/. inspect prints the manifest plus
its currently observed integrity. Trace finalization is crash-safe: startup
retries only transitions proved by durable attempt history, records an
unobserved HTTP response as unavailable, and never lets trace-storage failure
change semantic acceptance. See
docs/session-layout.md for
the exact outbox and seal ordering.
team-harness: the model and agent-CLI orchestration layer used by the loopy-loop worker.eval-banana: a lightweight YAML evaluation framework used by the packaged eval workflows. Installed automatically as a loopy-loop dependency.
