multi-loop turns an agent into a long-running mission operator.
The user states a mission — "start a company", "find the best ad campaign",
"build this SaaS" — and stays hands-off. The operator (an MCP host agent
like Claude Code or Codex, or the built-in CLI agent) interviews them once,
wires up the capabilities the mission needs, then runs and supervises a
portfolio of goal loops until the mission converges — reconfiguring budgets,
schedules, runners, and capabilities along the way. multi-loop is the
durable mission brain behind that operator: deterministic state, readiness
gates, policy, verification, scheduling, lineage, and audit.
Three roles, spelled out in docs/operator.md:
- Principal (the user): owns the mission statement, side-effect approvals, and checkpoint decisions. Nothing else.
- Operator (the agent): the executive director. Owns preparation,
configuration, execution, and supervision of everyone and everything — the
candidate loops, sub-agents, schedules, and capabilities.
mission_readinessdrives its prep;mission_configureand the schedule controls give it audited authority over every mutable mission setting. - Harness (multi-loop): owns control flow, state, budgets, leases, selection, convergence, and the audit ledger. Models provide judgement inside well-scoped roles; the harness makes it durable and accountable.
The basic execution pattern the harness generalizes is a bounded goal loop:
goal -> decompose -> execute workers -> aggregate -> review -> refine -> done
Multi-loop orchestration treats that whole loop as one executable unit inside a larger meta-loop. Instead of asking one loop to solve one bounded goal, the system launches, compares, mutates, and coordinates many loops against a broad mission.
mission
-> intake and scope
-> generate loop population
-> run many candidate loops
-> compare fitness
-> preserve the best outputs
-> mutate / cross over strategies
-> launch the next generation
-> converge on an integrated result
The reference model has three levels:
- Linear prompting: user gives a task, agent completes it, user gives the next task.
- Goal loop: user gives a goal, the harness decomposes, executes, reviews, and iterates until success.
- Multi-loop orchestration: user gives a mission, the meta-harness runs many goal loops inside a broader orchestration loop.
- Operated missions: an operator agent owns the meta-loop on the user's behalf — prep, configuration, execution, and supervision — and the user is only consulted for the mission itself, side-effect approvals, and checkpoints.
A multi-loop is a deterministic meta-harness, not a giant prompt.
The outer harness owns control flow, state, budgets, lineage, selection, convergence, and user checkpoints. Models provide judgement inside well-scoped roles: intake, strategy generation, loop planning, review, fitness scoring, and mutation.
A single-goal run answers: "Can this loop complete this goal?"
A multi-loop run answers: "Which collection of loops, strategies, and
generations can make progress on this larger mission?"
Any mission that is too broad, uncertain, or high-variance for one loop can be turned into a portfolio of loop-driven experiments.
For broad missions like "start a company," no single loop should try to solve the whole mission directly. The multi-loop orchestrator should create specialized loops such as market research, customer discovery, product thesis, ad campaign experiments, brand, technical prototype, legal checklist, financial model, and launch plan. Each loop has its own success criteria, reviewer, budget, artifacts, and continuation state.
Autoresearch is useful because it treats progress as experiments: mutate a candidate, run it under a fixed budget, score it, keep or discard it, and repeat. Multi-loop should generalize that pattern beyond code and model training.
An experiment can be any loop with:
- A hypothesis.
- A controlled scope.
- A budget.
- A runnable plan.
- An artifact.
- A fitness signal.
- A keep, discard, mutate, or merge decision.
For a company mission, an ad campaign can be handled as an experiment portfolio:
- Generate several campaign hypotheses for different audiences or promises.
- Produce creative variants, landing page copy, targeting assumptions, and budget plans.
- Score each campaign by expected conversion, clarity, differentiation, risk, cost, and evidence quality.
- Mutate weak campaigns by narrowing the audience, changing the hook, changing the channel, or simplifying the offer.
- Cross over strong pieces, such as combining the best audience insight with the best creative angle.
The same experiment model applies to product design, engineering architecture, sales scripts, research approaches, content strategies, and hiring plans.
Multi-loop is expected to consume many model calls and many tokens. That is not a bug; it is the point of moving from single-loop execution to long-running mission orchestration.
The harness should manage autonomy with explicit controls instead of pretending the work is cheap:
- Mission-level budgets.
- Per-loop budgets.
- Generation limits.
- Fitness thresholds.
- User checkpoint policies.
- Durable event logs.
- Resume support.
The default mode should be autonomous enough to run for a long time, but visible enough that the user can inspect status, stop it, redirect it, or approve a major branch in the mission.
Multi-loop needs a small runtime control plane around the model loops. The orchestrator should not expose every possible tool and policy in one giant prompt. It should maintain explicit registries for capabilities, schedules, policy gates, and child-loop delegation.
Capabilities should be described as searchable cards, not hardcoded prompt text. Each card should include:
- Name and description.
- Toolset or backend required.
- Inputs, outputs, and artifact types.
- Availability check.
- Cost and latency class.
- Side-effect class: read-only, local write, external write, public publish, spend money, or message a person.
- Verification method.
The planner can search or filter capabilities when building a portfolio. Core capabilities stay directly visible, while rare or expensive capabilities can be discovered on demand by a search/describe/call bridge. This keeps prompt size bounded while still letting missions discover browser, media generation, messaging, social, remote execution, and future MCP-style tools.
Any candidate loop that can affect the outside world should pass through a policy gate before execution. Examples that should require explicit approval or a stored policy rule include:
- Publishing, posting, uploading, or sending messages.
- Spending money or launching paid ads.
- Mutating remote services.
- Deleting or replacing external assets.
- Using credentials beyond read-only access.
Worker self-reports are not sufficient for side effects. Successful external actions should return verifiable handles such as URLs, object IDs, status codes, receipts, or absolute artifact paths, and the parent loop should verify them before reporting success.
Long-running missions should be resumed by bounded scheduled jobs, not by a single never-ending agent process. A schedule tick should:
- Load mission state and the latest ledger entries.
- Run one bounded generation or maintenance step.
- Save outputs and decisions.
- Advance the next run time.
- Deliver a status report only when there is something useful to report.
Scheduled mission jobs should be self-contained and non-interactive. They should not recursively create more schedules, ask clarifying questions, or send messages directly; delivery is handled by the scheduler. Script-only jobs are useful for cheap checks that decide whether an agent run is needed.
Candidate loops can delegate internally, but delegation needs explicit limits. Default child loops should be leaves: isolated context, restricted tools, no user interaction, no memory writes, and no recursive spawning. Nested orchestration should be an opt-in role with a depth limit and a concurrency budget.
Use delegation for independent reasoning-heavy workstreams, not for single tool calls or mechanical steps. Durable work that must outlive the current turn should be scheduled instead of delegated synchronously.
The genetic layer gives the system a way to explore multiple possible paths instead of committing to the first plan.
- Genome: a candidate strategy, plan, artifact set, or business thesis.
- Population: multiple loop runs exploring different genomes in parallel.
- Fitness: measurable score from reviewers, tests, market evidence, user preferences, cost, risk, and completeness.
- Selection: preserve the strongest candidates and discard weak or redundant ones.
- Mutation: change one candidate by adding constraints, trying a different audience, simplifying scope, changing implementation approach, or targeting a different distribution channel.
- Crossover: combine useful parts from two candidates into a new candidate.
- Generation: one outer cycle of run -> score -> select -> mutate -> rerun.
intake
-> mission framing
-> portfolio planning
-> loop spawning
-> loop monitoring
-> artifact aggregation
-> fitness review
-> selection and mutation
-> synthesis
-> user checkpoint or next generation
Clarify only mission-changing unknowns. For "start a company," the system might ask about industry, budget, time horizon, risk tolerance, geography, skills, preferred business model, and whether the output should be a plan, prototype, or operating company scaffold.
Create a portfolio of loops, not just a task list. Each loop should have a role, goal, success criteria, dependencies, budget, verification method, and expected artifact.
Run many candidate experiments as executable units. A candidate can be an agent run, MCP call, shell command, mock runner, manual task, or future custom backend. Some can be parallel, some gated by dependencies, and some intentionally redundant to compare alternate strategies.
Score candidate outputs against mission-level criteria. Fitness can include quality, evidence, novelty, risk, cost, speed, user fit, test results, and compatibility with other artifacts.
Keep the best candidates, merge compatible outputs, and create new loop goals from gaps or promising variants.
Produce an integrated mission artifact: an implementation, plan, company brief, research dossier, product prototype, content package, or operating roadmap.
Every candidate run records a structured Outcome (multi_loop/models.py)
alongside its fitness score, so the system can react to why a loop turned out
the way it did, not just whether it succeeded. The rule-based
RuleBasedClassifier (multi_loop/failures.py) maps signals already present on
a finished run — policy blocks, timeouts, exit codes, exceptions, verification
results, and output shape — onto a closed FailureClass taxonomy:
policy_blocked— an approval gate withheld the action.tool_unavailable— a required capability was missing or unconfigured.resource_exhausted— the run timed out or hit a budget cap.execution_error— it crashed, raised, or exited nonzero.verification_failed— it ran clean but its evidence check failed.bad_output— it returned a thin or empty result.strategy_error— it completed but in the wrong direction.unknown— an unclassified failure.
Classification is deterministic (keeping generations reproducible) and feeds two feedback paths within a mission:
- Cause-aware retries. The planner branches its recovery on the failure
class instead of always narrowing scope: a timeout is rescoped with a raised
budget, an execution error is handed the failure detail to debug, a
verification failure is told to produce checkable evidence, and an unavailable
tool becomes a human setup task rather than a blind retry that would just fail
again (
HeuristicPortfolioPlanner._plan_evolved). - Pitfall injection. Each
Outcomecarries a short, agent-readableremedy_hint. Before a loop runs,collect_pitfallsgathers the hints from earlier failures that share a capability with — or are a parent of — the current candidate, and injects the most recent few into its prompt so the spawned agent avoids the same rake.
The same Outcome records also feed learning across missions. The derived,
rebuildable MissionIndex (multi_loop/index.py) carries an outcomes table
keyed by candidate, role, exact failing capability, and failure class, plus a
normalized mapping of every capability required by each candidate. When the
orchestrator is given a lessons_index, it refreshes the index from JSON at the
start of each generation and queries relevant_lessons for failures in other
missions that share the spawning loop's role or any required capability. Those
remedy hints are merged with the same-mission pitfalls (same-mission first, then
the most recent cross-mission lessons, de-duplicated and capped) and injected
into the loop's prompt — so a timeout that sank a campaign in one mission warns
the campaign loop of the next.
Two properties keep this honest over time:
- Recency weighting. Lessons are returned newest-first and capped, so fresh failures dominate and stale advice fades rather than piling up.
- State-tied invalidation. A
tool_unavailablelesson is dropped the moment the capability it complains about is configured again, instead of warning about a problem that no longer exists.
Cross-mission learning is opt-in at the library level (lessons_index=None
leaves behaviour unchanged) and enabled by default in the real run paths — the
run CLI command, MCP run_generation, and the scheduler. The failure class
and remedy hint are also surfaced on the queryable candidate_finished event.
Mission: "Start a company."
Possible candidate loops:
- Clarify founder constraints and target domains.
- Research 5 market opportunities.
- Generate 3 business theses.
- Validate customer pain and willingness to pay.
- Run ad campaign experiments.
- Design an MVP scope.
- Prototype the product.
- Build a brand and positioning system.
- Produce a 30-day launch plan.
- Build a basic financial model.
- Review legal, compliance, and operational risks.
Genetic behavior:
- Run multiple business theses in parallel.
- Score them by feasibility, demand, founder fit, speed to revenue, and risk.
- Mutate weak but promising theses into narrower niches.
- Cross over the strongest market insight with the strongest product idea.
- Continue until one integrated company plan is strong enough to execute.
Mission: "Find and refine the best ad campaign for a product."
Possible candidate loops:
- Define audiences and campaign hypotheses.
- Generate hooks, offers, and creative directions.
- Draft landing page variants.
- Produce channel-specific copy for search, social, email, or creator outreach.
- Score variants against user fit, differentiation, clarity, risk, and estimated cost.
- Synthesize the winning campaign plan.
Genetic behavior:
- Treat each campaign direction as a genome.
- Mutate targeting, hook, offer, proof, format, or channel.
- Cross over the strongest audience with the strongest message.
- Preserve a lineage of discarded and winning variants so the user can see why a campaign was selected.
Mission: "Build a project management SaaS."
Possible candidate loops:
- Requirements and user stories.
- Data model and architecture.
- Authentication and billing.
- Core task board UI.
- Collaboration and notifications.
- Test strategy and Playwright coverage.
- Deployment and observability.
- Security and abuse review.
Genetic behavior:
- Compare multiple architecture candidates.
- Run competing UI directions.
- Select the simplest implementation that passes verification.
- Mutate failing components into smaller scoped loops.
Mission: "Make a YouTube documentary about a topic."
Possible candidate loops:
- Research the story and timeline.
- Find source clips and transcript evidence.
- Generate competing narrative structures.
- Draft narration.
- Build an edit decision list.
- Create title, thumbnail, and packaging options.
- Review pacing, claims, and source support.
Genetic behavior:
- Generate several narrative angles.
- Score them by clarity, originality, evidence, and audience pull.
- Cross over the strongest hook with the strongest evidence structure.
Mission: "Find the best approach to solve a hard technical problem."
Possible candidate loops:
- Literature and prior-art review.
- Prototype approach A.
- Prototype approach B.
- Benchmark and evaluate tradeoffs.
- Failure-mode analysis.
- Final recommendation and implementation plan.
Genetic behavior:
- Treat each approach as a genome.
- Use benchmarks and reviewer judgement as fitness.
- Mutate the highest-potential approaches based on observed failures.
Mission
id
statement
success_criteria
clarifications
budget
schedule
generations[]
ledger[]
Generation
index
candidate_loops[]
fitness_scores[]
selected_lineage[]
mutations[]
synthesis
CandidateLoop
id
parent_ids[]
goal
success_criteria
role
dependencies[]
budget
required_capabilities[]
policy_gates[]
verification
result
artifacts[]
fitness
Capability
name
description
toolset_or_backend
availability_check
side_effect_class
cost_class
verification
Job
id
mission_id
schedule
next_run_at
state
max_generation_steps
enabled_capabilities[]
disabled_capabilities[]
LedgerEntry
id
mission_id
generation_index
candidate_loop_id
event_type
summary
artifacts[]
created_at
Onboarding is now a durable agent protocol rather than a fixed questionnaire.
The user may keep talking to the same main-loop session before and after mission
creation. Confirmed intent is stored in a canonical MissionDraft; model-written
summaries help rebuild context but never authorize operations or replace mission
state.
There are two execution modes:
- CLI: multi-loop calls a connected OpenAI-compatible provider and runs its own bounded function-calling loop. Provider profiles store only an environment variable name, never the credential value.
- MCP: the host (Codex, Claude, or another MCP client) is the main-loop agent. Multi-loop does not call a second LLM. It exposes deterministic session, drafting, policy, and generation state transitions to the host.
The session log is append-only and fsynced. Inbound user messages are persisted before a provider call, revisions prevent stale concurrent writes, context is bounded, and compaction retains the full transcript while saving a resumable working summary.
Connect the provider first, using an environment variable for its key:
export OPENAI_API_KEY=...
multi-loop provider connect work --kind openai --model <model-name>
multi-loop provider validate work
multi-loop agent chat --provider-id work --mission "Launch a useful service"Use --message "..." for one non-interactive turn. The returned session_id
can be resumed later:
multi-loop agent chat --session-id <session-id> --message "Continue where we stopped"Custom or local OpenAI-compatible endpoints are supported with
--kind openai_compatible --base-url http://127.0.0.1:11434/v1. Provider and
session configuration live under .multi-loop/main-loop/; no Hermes, Pi, or
other agent runtime is required.
The current MVP has a deterministic one-generation runtime:
MissionOrchestrator.create_mission(...)creates a persisted mission.MissionOrchestrator.run_generation(...)plans a candidate portfolio, runs it, scores fitness, selects lineage, writes synthesis, and appends event/ledger data. The planner is genetic, not a fixed candidate count:- The first generation seeds three base loops (research, strategy, review), plus any mission-specific loops, plus one loop per selected capability.
- Later generations evolve from the previous result: refine selected winners, retry failures with narrower scope, resume now-approved blocked candidates, cross over the strongest winners, and add a synthesis worker.
MockRunnerproduces deterministic local artifacts for tests and demos.ShellRunnerruns a configured shell command.AgentCommandRunnerruns an external agent CLI command with the candidate prompt on stdin.- Verification commands can run after a candidate and affect its success score.
Note: in the current MVP, candidate loops within a generation run sequentially, not in parallel. The parallel-population behavior described above is the design target, not yet the runtime behavior.
By default a run uses the deterministic MockRunner. To make a generation do real
work, pass --runner-command: it is applied to every candidate's runner config so
the shell/agent_command runners execute it. With agent_command (the default
when a command is given), each candidate's self-contained prompt is piped to the
command on stdin, so a real CLI agent works each candidate loop:
# real agents work each candidate loop in the generation:
python3 -m multi_loop run <mission-id> --runner-command "claude -p"
# or run a deterministic shell command per candidate:
python3 -m multi_loop run <mission-id> --runner shell --runner-command "pytest -q"
# or run each candidate through the installed Hermes CLI (Stage 1 subprocess bridge):
python3 -m multi_loop run <mission-id> --runner hermesThe hermes runner needs no command: it launches one hermes chat -q ... -Q
subprocess per candidate with a bounded toolset grant (default web,file),
prepends the mission's side-effect directive to the prompt, and collects
evidence from the candidate's artifact directory — the files the agent actually
wrote, not what it claims. Per-candidate runner_config accepts toolsets,
model, and executable overrides.
Real runs are governed by two safety rails:
- Side effects are denied by default. Every spawned agent is instructed to stay
read-only and local — no merging, publishing, sending, spending, or mutating remote
services. An outward action requires a recorded approval for the specific
side-effecting capability used by that candidate. The legacy
--allow-side-effectsflag cannot bypass this scope. Approved actions must return verifiable handles. - Verification is authoritative. Pass
--verify "<command>"(repeatable) and the command's exit code — not the runner's — decides success. This rescues a candidate that did the work but whose runner was killed (e.g. timed out before reporting), and fails one that exited cleanly but cannot prove its claimed work, so fitness reflects evidence rather than the worker's self-report.
Every grant, use, and revocation of side-effect authority is also written to a
durable per-mission permission ledger (permissions.jsonl), inspectable at any
time — this is what keeps hands-off operation from becoming hidden operation:
python3 -m multi_loop approve <mission-id> browser_automation --by user
python3 -m multi_loop revoke <mission-id> browser_automation --by user
python3 -m multi_loop permissions <mission-id># after approving the candidate's specific GitHub write capability, verify the action:
python3 -m multi_loop approve <mission-id> browser_automation --by user
python3 -m multi_loop run <mission-id> --runner-command "claude -p" \
--verify "gh pr view 42 --json state -q .state | grep -qx MERGED"CLI examples:
python3 -m multi_loop onboard --mission "Start a company"
python3 -m multi_loop create "Start a company" --success-criteria "Produce a launch plan"
python3 -m multi_loop run <mission-id>
python3 -m multi_loop status <mission-id>
python3 -m multi_loop listMissions can carry a schedule that the tick command advances one bounded
generation at a time. Supported expressions:
- One-shot:
30m,2h,1d, or an ISO timestamp like2026-07-01T09:00:00. - Recurring interval:
every 30m,every 2h,every 1d. - Cron:
0 9 * * *(requires the optionalcroniterpackage; other kinds stay dependency-free).
A schedule tracks operational state (scheduled, paused, completed,
error) plus the last run's outcome (last_status, last_error). Recurring
runs are pre-advanced before execution (at-most-once on crash), missed runs past
their catch-up grace window are fast-forwarded instead of firing a stale burst,
and a recurring schedule that can no longer compute its next run is surfaced as
error rather than silently disabled.
python3 -m multi_loop create "Monitor competitors" --schedule "every 1d"
python3 -m multi_loop pause <mission-id> --reason "holding for review"
python3 -m multi_loop resume <mission-id>
python3 -m multi_loop trigger <mission-id> # mark due now
python3 -m multi_loop tick # run all missions that are due
python3 -m multi_loop serve --interval 60 # keep ticking until interruptedserve is the unattended continuation path: leave it running (tmux, systemd,
cron wrapper) and every scheduled mission advances one bounded generation per
due tick with no session attached.
After every generation the orchestrator writes a user-facing report to
reports/generation-<n>.md inside the mission directory, and the same report
can be rendered on demand from current state:
python3 -m multi_loop report <mission-id>It summarizes progress, evidence paths, granted/used authority, items that need the user's decision (policy-blocked candidates, failures, schedule errors), and what happens next — rendered deterministically from mission state, no LLM involved.
The legacy deterministic onboard command remains available for scripts. The
interactive path is the main-loop agent:
- The user states the mission.
- The orchestrator explains relevant configured capabilities and capabilities that need setup.
- The user answers mission-critical questions: success criteria, time horizon, constraints, available resources, autonomy level, approval policy, schedule, and preferred tools.
- The orchestrator creates the mission with those clarifications saved.
- The first generation runs as a dry/local pass unless the user approves broader tools or external side effects.
Use this for a legacy non-interactive dry setup:
python3 -m multi_loop onboard --mission "Run a company" --defaultsRuntime state is stored under .multi-loop/runs/<mission-id>/:
mission.json: mission state, generations, candidates, scores, selected lineage.ledger.jsonl: durable mission history.events.jsonl: event stream for monitoring/debugging.artifacts/: candidate outputs and generation synthesis.results/: structured candidate run results..run.lock: exclusive run lease. A generation holds this lock for its whole duration, so a scheduled tick, a detached MCP run, and a manual CLI run can never produce a duplicate generation on the same mission; concurrent callers raiseMissionBusy(the scheduler reports this as analready_runningskip). The lock is process-held, so a crashed runner releases it automatically.
A derived SQLite index lives at .multi-loop/index.db. It is rebuilt from the
JSON state on demand (the JSON files remain the source of truth) and powers
cross-mission ledger/mission search and candidate lineage queries via the
search and lineage commands and MCP tools.
multi-loop can also run as an MCP server. The MCP package is optional so the
core CLI and tests stay dependency-free:
pip install -e ".[mcp]"
python3 -m multi_loop.mcp_serverIf installed as a package, the console script is available too:
multi-loop-mcpThe server exposes the mission runtime directly:
main_loop_open,main_loop_list,main_loop_context,main_loop_pause,main_loop_resume,main_loop_record_turn,main_loop_checkpoint, andmain_loop_compactprovide durable host-agent sessions.mission_draft_update,mission_draft_validate, andmission_confirmlet the host agent scope a mission conversationally and commit it only after explicit user confirmation.generation_prepare,candidate_claim,candidate_artifact_write,candidate_submit_result, andgeneration_finalizeare the host-execution protocol. Codex can claim work, execute it with its own tools, store evidence, submit an idempotent result, and let multi-loop deterministically select and synthesize the generation. No nested model is invoked.onboardbuilds an onboarding plan and can create the mission.capability_setup_planandcapability_setup_applydrive interactive capability configuration on a draft session: plan the required config/approval changes, show them to the user, and apply them only with aconfirmation_quote.capability_add_commandpersists a user-approved command as a brand-new capability (with itsside_effect_class) and attaches it to the draft.mission_capability_setup_planandmission_capability_setup_applyare the same plan/apply pair for an already-created mission. None of these embed credentials.create_mission,mission_status,list_missions, andapprove_capabilitymanage persisted mission state.mission_reportrenders the user-facing executive report for a mission — what the host agent should show the user instead of raw status.mission_readinessis the operator's prep instrument: for a draft session or a created mission it classifies every required capability (ready,needs_setup,needs_approval,unknown) with concrete fixes, checks that scheduled missions have a real unattended runner, and returns blockers, notices, and next actions. Run it before confirming, before the first generation, and after any capability or approval change.mission_configuregives the operator audited authority over every mutable mission setting after creation: success criteria, clarifications, budget, schedule (null clears it), execution profile (runner, runner command, verification, workspace, autonomy level), and the selected capability list. The mission statement and side-effect approvals are deliberately excluded; each applied patch is validated atomically and recorded as amission_configuredevent plus ledger entry.mission_pause,mission_resume, andmission_triggercontrol mission schedules over MCP, mirroring the CLI'spause/resume/trigger.run_generationruns one generation. It detaches by default and returns arun_idimmediately.run_status,run_tail,run_result, andrun_listmonitor detached runs.tickruns scheduled mission ticks that are currently due.list_backendsanddoctorreport local runner/capability and storage health.capability_search,capability_describe, andcapability_listare the on-demand discovery bridge: search returns matching capability cards, describe returns one full card (includingavailable,requires_env, andmissing_env), and list enumerates all cards. The same surface is available from the CLI viamulti-loop capabilities [--search Q | --describe NAME | --available].toolset_listandtoolset_resolvework with named capability bundles. Toolsets compose viaincludes(e.g.companyfolds inresearch,outreach, andmedia), and resolution accepts a mix of toolset names, capability names, andall/*, returning a deduped capability list. The CLI mirrors this withmulti-loop toolsets [--resolve "company,agent_loop"].searchandlineagequery the derived SQLite index:searchfinds ledger entries (or mission statements withmissions=true) across all missions, andlineagereturns a candidate loop's ancestry. The CLI mirrors these withmulti-loop search "<text>" [--missions]andmulti-loop lineage <loop-id>.
Detached MCP run logs live under .multi-loop/mcp-runs/<run-id>/ with
events.jsonl, status.json, and result.json. Mission state remains under
.multi-loop/runs/<mission-id>/.
multi-loop tui opens multi-loop's own agent environment — the product surface,
not a third-party chat pointed at files:
- Dashboard — every mission with generation progress, schedule state, and next-run time; selecting a mission renders its executive report inline.
- Chat — the operator room. The app assembles a fresh state snapshot every
turn and feeds it to the engine (codex headless with the multi-loop MCP
tools), so the operator already knows the mission state; you never explain or
point it anywhere.
/approve <capability>and/revoke <capability>are handled locally and written straight to the permission ledger. - Settings — schedule, runner, and authority grants per mission.
A serve loop ticks scheduled missions inside the app: when a generation finishes, its executive report is pushed into the chat feed automatically.
pip install -e ".[tui]"
multi-loop tuiThe engine is deliberately swappable: the TUI owns presentation and context assembly, the harness owns policy and durability, and codex is just inference plus tools behind the chat pane.
With the MCP server registered in Codex, the Codex CLI (ChatGPT OAuth) is the executive-director agent: you state the mission in a codex chat, and it drives draft → confirm → capability setup → run → report through the MCP tools while multi-loop keeps ownership of policy, ledgers, and evidence.
# ~/.codex/config.toml
[mcp_servers.multi-loop]
command = "/path/to/multi-loop/.venv/bin/multi-loop-mcp"
default_tools_approval_mode = "approve" # multi-loop's own policy gates side effectsAuto-approving the MCP call layer is safe because the harness, not the host
agent, enforces the side-effect policy: outward actions still require a
recorded approve_capability grant, and every grant/use/revocation lands in
the permission ledger.
The program.md idea from autoresearch maps well to multi-loop, but it should be
generalized into mission operating files instead of one hardcoded research prompt.
Possible files:
program.md: the meta-loop operating procedure.mission.md: the user's mission, clarifications, constraints, and success criteria.portfolio.md: the current set of candidate loops and experiments.fitness.md: scoring rubrics and thresholds.capabilities/: searchable capability cards and policy metadata.ledger.tsvorledger.jsonl: durable experiment history.
These files become editable "organization code." The user and agents improve how the autonomous organization behaves by editing the program files, while the Python harness enforces the loop mechanics.
- Should candidate runs execute in separate worktrees by default, then merge selected artifacts back into a mission workspace?
- Should fitness be a single numeric score, a rubric object, or both?
- How much autonomy should mutation have before asking the user?
- Should multi-loop be exposed as a separate MCP tool, or as an extension of the
existing
orchestrateserver?