Skip to content

Multi-Agent Orchestration

Run multiple AI agents on one project in parallel, without them stepping on each other. luvus coordinates the team through a shared task board: every worker can run in an isolated git worktree or an explicit shared workspace task tab. Path leases coordinate intended edits, quality gates verify work before it counts, and a merge gate integrates finished worktree branches without touching your checkout.

Concept What it is
Task A unit of work: title, the file globs it will touch, dependencies, and an optional quality-gate command. Gets an id like t1.
Automation A durable one-time or recurring definition. Each due occurrence creates a fresh ORCH task and starts its configured agent. Future work owns no pane, lease, or worktree before it is due.
Lease A reservation on file paths. Two workers can’t hold overlapping globs, so conflicting work can’t be assigned.
Worker A task-owned pane. Worktree mode uses a dedicated branch and checkout; workspace mode uses a dedicated task tab in an existing shared checkout.
Quality gate A command (e.g. cargo test) that runs when a task is marked done. It must pass before the task can merge.
Merge gate Integrates a finished branch into luvus/integration inside a dedicated worktree, never your working checkout. A conflict blocks the task instead of corrupting anything.

Task lifecycle: queuedclaimed/runningdone when the gate passes. A failed gate enters review; fixing the work and retrying the gate returns it to done. Only done or a merge-conflict blocked task can enter merging, then finish as merged or return to blocked on conflict. Only one task integrates at a time. An interrupted integration restores its prior done or blocked state after restart. Branch-backed dependents wait for merged, so they never start before their dependency is available in the integration history. Each named server session owns its own orch.json ledger inside that session’s Luvus directory.

Automation definitions and bounded run history live in the selected server session’s automations.json. The detached server owns their deadlines, so closing the TUI does not pause them. Stopping the server does; on restart Luvus reconciles persisted ORCH provenance before starting anything and applies the definition’s missed-run policy. A scheduled agent cannot survive its owning server, so an in-progress task from the previous server lifetime is recorded as failed instead of being left running or launched twice. A task whose durable provenance was saved before its worker started resumes that same pending run. An active-agent target is different: it creates no ORCH task and is bound to one live terminal lifetime. Restarting the server disables that definition instead of sending its prompt to a restored or unrelated pane.

For schedule syntax, access profiles, missed-run policies, UHP requests, and a copyable example, see Agent Automation.

Every new task is bound to the project of the selected workspace. Git worktrees from one repository share a project identity, while unrelated repositories have independent task queues and path leases. task next only selects work from its workspace’s project, so changing the focused workspace cannot launch an older task in the wrong repository. Commands run inside a Luvus pane infer its workspace. Callers outside a pane must pass --workspace-id when multiple repositories or multiple non-Git projects are open; use luvus workspace list to discover the stable id. When the focused workspace belongs to the session’s only Git repository, an incidental non-Git launch-directory workspace does not make that repository ambiguous. Legacy tasks use the same rule when acquiring project metadata.

task start validates the task’s path lease before it creates a worktree or workspace worker pane. If another task already holds an overlapping path, start returns lease_conflict and leaves the queued task untouched. After a server restart, leases follow workers that were restored to new pane IDs; leases with no live task owner are discarded so stale reservations cannot block the queue. Overlapping paths conflict only inside the same project. If older persisted state contains two already-running workers with overlapping paths, Luvus keeps the existing holder and marks the unprotected task blocked.

When an agent is selected, Luvus queues a short private-runner command and Enter as one submission before it marks the task running. The runner reloads the claimed task and passes its complete briefing directly to the agent process, so long or multiline prompts never cross the shell’s terminal-input line buffer. A queue failure closes the new pane and leaves the task unclaimed without closing any pre-existing worker. Any workspace, worktree, or branch created only for that failed attempt is removed, and the previous workspace selection is restored. Multiline prompts and progress notes remain structured in both task storage and the briefing delivered to the agent.

Open the ◇ orch tab with Ctrl+Space o. It shows every task (status · id · title · dependencies · mode · worker location once started) and the active leases, live. Navigate with j/k, the wheel, or click a row. On a wide terminal, the selected task’s branch, paths, gate, output, and notes stay visible in a detail panel.

The header switches between Tasks and Automations BETA. The automation view shows the definition state, retained schedule, next UTC deadline, target agent, target mode, and target workspace. Use e to pause or re-enable the selected definition, r to request one run without advancing its schedule, and D to delete an idle definition. Press o or Enter to inspect its trigger, timezone, next five occurrences, execution policy, task template, and bounded run history; click outside that detail popup or press Esc to close it. Armed definitions also appear in the sidebar’s Active agents section as scheduled; the placeholder is replaced by the normal live agent row when a new ORCH task starts. An active-agent definition instead delivers into its already-visible agent row. Clicking a scheduled placeholder or a Mission Control automation row opens the same read-only detail. Mission Control shows aggregate armed, live, review, and failed automation health without polling usage data.

Mouse controls follow the same validated actions as the keyboard and CLI:

  • click a task to select it;
  • select a task to inspect it in the wide details panel;
  • double click a task to jump to its worker pane, the same as Enter;
  • use o or Details in the context menu for longer output and note history;
  • click its worker label to jump to the worker pane;
  • right click a task for the actions valid in its current state;
  • click New task or New automation to open the contextual form, then click the Task/Automation tab, fields, and form actions;
  • choose worktree or workspace in the first start-worker step, then choose an agent in the second step;
  • when the board is empty, click the Worktree/Workspace labels in the Flow panel to compare their lifecycle diagrams. This is informational and does not change the next worker’s mode.

The task menu stays bound to the task that opened it, even if the board changes before an action is chosen.

Key Action
Tab switch between the Tasks and Automations views
a new: open Task creation from Tasks or Automation creation from Automations (Tab switches type, / moves fields, creates)
o / Enter inspect the selected automation when the Automations view is active
s start: choose worktree/workspace mode, then choose an agent
d done: runs its quality gate (pass → done, fail → held at review)
m merge into luvus/integration
jump to its worker pane
x release an active task and its path leases
q close the board without stopping tasks or workers

The form starts on a compact Task · Automation choice. The active board view selects its matching type by default. Task shows Title, Paths, Deps, Gate, a Manual/Now Start choice, and a three-row Prompt editor; Agent appears only for Now. Automation hides concrete dependencies and owns a registry-backed Agent, an explicit Run in choice for an isolated Worktree or the existing Workspace, an Access choice (Read only, Workspace, or Full access), Once later, Hourly, Daily, or Weekly, and Schedule, followed by a three-row Prompt editor. Use Tab to switch between Task and Automation, Down or Up to move between fields, Left/Right to change the selected Agent, Run in, Access, or Start value, and Shift+Enter to add a new line to either prompt. Plain Enter creates the task or automation. Pasted task prompts preserve line breaks, and long titles scroll horizontally with the active cursor instead of hiding the end. Agent choices come from the built-in adapters that declare at least one reviewed unattended launch profile. A selected agent/access combination that is not supported is rejected before Luvus creates a task, worktree, lease, or pane. Task and Automation retain independent drafts while the modal is open, so switching type and returning restores that type’s inputs, selections, and focused field.

Manual preserves ordinary task creation. Now creates and starts one ORCH task. Automations store a template and do not create the concrete task until it is due. The form detects the server user’s IANA timezone and shows it beside the Automation Start choice. Schedule input uses that local wall-clock time: YYYY-MM-DD HH:MM for Once, a minute from 00 through 59 for Hourly, HH:MM for Daily, and mon,fri HH:MM for Weekly. Changing Start fills Schedule with a valid editable value; the first typed character replaces that suggestion. CLI and UHP continue to require explicit UTC or timezone fields.

Calendar schedules retain their IANA timezone but persist each execution deadline as UTC. Across daylight-saving changes, Luvus keeps the requested wall-clock time, shifts a nonexistent time forward by the transition gap, and uses only the first occurrence of a repeated time. Preview deadlines before arming remote definitions when timezone behavior matters.

The current beta is time-triggered. ORCH task dependencies can make a task ready after another task completes, but they do not automatically trigger an Automation definition.

Say you want an auth module and an API layer that depends on it:

  1. a → Title OAuth token module, Paths src/auth/**, Gate cargo test auth, Prompt Implement the token parser and cover rollback behavior, .
  2. a → Title API layer, Paths src/api/**, Deps t1, .
  3. Select t1 and press s. luvus creates a worktree on branch luvus/t1, opens a pane in it, and takes you there. Run your agent in that pane (or pass --agent via the CLI to launch one automatically).
  4. When the work looks finished: back to the board, d. The gate (cargo test auth) runs in the background. Pass and t1 is done. Fail and it’s held at review with the output saved on the task.
  5. Select t1, press m, and its branch merges into luvus/integration in an isolated worktree. The task moves through merging to merged and records the exact integration commit. A conflict aborts Git and marks the task blocked rather than leaving a half-merge.
  6. Once t1 is merged, t2 becomes claimable. Select it, press s, and repeat.

Your own checkout on main was never touched at any point.

Everything the board does is a command, which is how an orchestrator agent can run the whole loop itself:

Terminal window
# create + inspect
luvus task add "OAuth module" \
--prompt "Implement the token parser and cover rollback behavior." \
--paths "src/auth/**" --gate "cargo test auth" \
--workspace-id workspace_example
luvus task list · get t1
luvus task update t1 --prompt-file ./task-brief.md # editable until the task starts
luvus task update t1 --status running --note "learning: …"
# start workers (worktree remains the default)
luvus task start t1 --agent "claude"
luvus task next --start --agent "claude" --workspace-id workspace_example
# stage a worker without leaving the workspace, tab, or pane you are viewing
luvus task start t3 --agent "codex" --workspace-id workspace_example --no-focus
# run directly in an existing checkout (no branch or merge step)
luvus task start t2 --mode workspace --agent "codex"
# finish + merge
luvus task heartbeat t1 --context-used 0.6 # 60% of the model context window is used
luvus task done t1 # runs the quality gate
luvus task merge t1
# retry without deleting the previous pane, branch, worktree, or result
luvus task retry t1
luvus task start t1 --agent "claude" # worktree attempt 2 uses a new branch
# leases (usually automatic via task start)
luvus lease acquire "src/auth/**" --task t1
# schedule a weekday agent in a retained IANA timezone
luvus automation create "Morning review" \
--title "Review changes" --prompt "Review and report risks" \
--agent codex --workspace-id workspace_example \
--weekly mon,tue,wed,thu,fri --at 08:00 --timezone Asia/Makassar \
--mode workspace --access workspace
luvus automation list
luvus automation preview --daily 08:00 --timezone America/New_York
luvus automation run a1 --idempotency-key manual-review-1
# react to everything, live (newline-delimited JSON)
luvus events

For an unregistered agent, --agent accepts an executable followed by quoted arguments. Luvus parses that argv directly; shell pipelines and redirections are not evaluated. The task briefing is always appended as the final argument.

Inside a luvus pane, commands default to the calling pane via $LUVUS_PANE_ID, so a worker agent can luvus task heartbeat itself. --context-used is the fraction of the model’s context window already consumed: 0.6 means 60% consumed. It is not task-completion progress. Use task update --note for work progress and omit the heartbeat when context-window usage is unknown. The older --context spelling remains accepted for compatibility.

Luvus also puts the running server binary first in that pane’s PATH. A worker created by a debug server therefore reports through the matching debug CLI, while an installed server uses its matching release CLI. The existing PATH entries remain available after it.

Events on the bus: task.added · task.claimed · task.started · task.ready · task.gate_running · task.gate_passed · task.gate_failed · task.needs_compaction · task.done · task.merge_started · task.merged · task.merge_conflict · task.merge_failed · task.released · task.retried · lease.acquired · lease.released · automation.created · automation.updated · automation.enabled · automation.disabled · automation.rebound · automation.deleted · automation.run_queued · automation.run_materialized · automation.run_started · automation.run_updated · automation.run_finished · automation.run_failed.

task retry <id> accepts terminal done, failed, review, and blocked tasks. It archives a bounded attempt summary, releases leases, detaches the old worker, and queues a fresh attempt without closing the pane or deleting its branch, worktree, output, or notes. A retry is rejected once a dependent task has started, and merging or merged tasks remain immutable. Worktree retries use luvus/<task-id>-retry-<attempt> by default. Retrying an automation-owned task creates a new automation run from the original run’s captured contract while preserving the original records. Retrying from review or blocked finishes the superseded run as cancelled without closing its worker pane.

  • Only armed agent automations spawn unattended. Manual tasks still start only when you press s or run task start. Every automation stores one explicit agent, workspace, prompt, worker mode, access policy, and bounded schedule.
  • No arbitrary scheduled shell action. The scheduler launches only a reviewed built-in agent adapter through its separate one-shot automation profile; detection-only manifests and interactive task commands do not gain unattended execution authority.
  • No blind approval. Read only, Workspace, and Full access map to the selected agent’s native per-run flags. Luvus never types y or Enter into an unknown permission prompt and never rewrites the agent’s permanent config.
  • No background poller. Definitions cache the nearest UTC deadline and use the existing server wake path. No thread, timer, network request, or process scan is created per automation.
  • Worktree mode is isolated by default. Workers edit in their own worktrees and merges happen in a dedicated integration worktree.
  • Workspace mode is intentionally shared. It creates a task tab without a branch or nested workspace. Leases coordinate Luvus tasks but do not prevent agents or external tools from writing outside declared paths.
  • Conflicts can’t corrupt. The merge gate aborts cleanly on conflict and surfaces it (task → blocked).
  • Two layers of isolation. Leases prevent overlapping work from being assigned, and worktrees mean even a misbehaving agent’s clash only surfaces (safely) at merge time.
  • A context gate. Workers may report model context-window consumption via heartbeat. Above 85%, done is blocked until the agent compacts, hands off, or corrects a mistaken heartbeat to 85% or below, so there are no half-remembered finishes. This value is never work progress.
Symptom Fix
snot a git repo Worktree mode needs Git. Select workspace mode to run a branchless worker in the current directory.
sdeps not done A dependency task isn’t done yet.
slease conflict Another task owns an overlapping path. Finish or release that task before retrying. No worker was created.
dneeds compaction The worker’s model context window is over 85%. Compact if the agent supports it, hand off, or correct a mistaken report with luvus task heartbeat <id> --context-used <0..1>, then retry.
Stuck at review The gate failed. luvus task get <id> shows the output. Fix and d again.
blocked after m Merge conflict. Resolve in the task’s worktree, then m again.
Worker reports that Luvus server access was denied The agent or OS sandbox cannot reach the session socket. Approve that exact local Luvus command or adjust the agent’s own reviewed permission policy. Luvus does not silently disable the sandbox.
Agent/access combination is unsupported Choose an access level that the selected adapter explicitly supports. Luvus fails before creating any worker resources.
Scheduled worker still needs attention ORCH marks the automation task blocked and records the detected prompt. Resolve it in the visible pane; Luvus does not approve unknown requests automatically.

Clean up a finished worker with luvus worktree remove <path> (the branch is kept).