Lights-Out Operation
This is the repo-local operator runbook for unattended governed execution.
If you want the scheduler reference, read Lights-Out Scheduling. If you want the end-to-end path from zero to a running continuous session, start here.
This guide is repo-local only. It assumes one governed repository with agentxchain.json and one project-owned .planning/VISION.md. If you are coordinating multiple repositories, use agentxchain multi and the Multi-Repo Coordination docs instead of trying to stretch this flow across child repos.
Choose the right loop owner
AgentXchain ships two related lights-out surfaces:
agentxchain run --continuous --vision <path>: one process owns the loop directlyagentxchain schedule daemon: the daemon owns cadence and advances schedule-owned continuous sessions
Use run --continuous when you want a foreground proof run or a single process in a tmux/session manager. Use schedule daemon when you want repo-local polling, daemon health, and schedule-owned session continuity.
1. Preflight the repo before turning anything on
Do not daemonize a repo you have not validated. The minimum preflight is:
agentxchain doctor
agentxchain connector check
agentxchain status
Confirm these inputs before you go further:
.planning/VISION.mdexists and reflects the product direction for this repo- your runtime binding is real for the roles that will execute unattended work
- approval policy is intentional: use auto-approval only where your governance rules allow it
- budget stance is explicit for both per-run and continuous session spend
If you need human review before vision-derived work enters execution, set triage_approval: "human" in the continuous config instead of pretending the repo is safe for full auto-approval.
2. Configure one schedule-owned continuous session
Add a schedule entry in agentxchain.json:
{
"schedules": {
"vision_autopilot": {
"enabled": true,
"every_minutes": 60,
"auto_approve": true,
"max_turns": 10,
"initial_role": "pm",
"trigger_reason": "Repo-local lights-out execution",
"continuous": {
"enabled": true,
"vision_path": ".planning/VISION.md",
"max_runs": 50,
"max_idle_cycles": 5,
"triage_approval": "auto",
"per_session_max_usd": 25.0
}
}
}
}
What matters here:
every_minutescontrols when the daemon may start or restart the sessioncontinuous.vision_pathis required when continuous mode is enabledper_session_max_usdis the cumulative session cap; when hit, the session stops cleanly instead of blockingtriage_approval: "human"pauses vision-derived work at the intake approval boundary instead of auto-approving it
For the field-by-field reference, see Lights-Out Scheduling and CLI Reference.
3. Prove the loop once before starting the daemon
Run one bounded continuous session in the foreground first:
agentxchain run --continuous --vision .planning/VISION.md --max-runs 1 --session-budget 5.00
That command is the safety floor. It proves:
- the vision file resolves correctly
- the intake lifecycle can seed or consume work
- the configured adapter/runtime can complete a governed run
- status surfaces continuous-session truth for this repo
Skipping this proof and going straight to schedule daemon is lazy. If the repo cannot complete one bounded run in the foreground, the daemon will not save you.
3a. Use a truthful mixed-runtime proof shape
Do not fake a “fully lights-out” proof by binding every phase to remote review_only roles and then acting surprised when requires_files gates never pass.
The production-valid mixed-runtime shape is:
- local authoring roles satisfy repo-local gate files
- a
review_onlyapi_proxyQA role validates and requests completion - the repo already contains the final QA gate files before the QA review turn begins
That is the real contract today. A review_only api_proxy QA role can validate and request completion, but it cannot create gate files.
If you want the repo-owned live proof harness for this exact shape, run:
node examples/live-governed-proof/run-continuous-mixed-proof.mjs --json
That harness drives the real run --continuous CLI surface, uses a real Anthropic-backed api_proxy QA turn, and validates the continuous session, intake provenance, review artifact, and recorded spend.
4. Start the daemon
Once the bounded proof run is clean, start the scheduler:
agentxchain schedule daemon --poll-seconds 60
Or for a persistent shell session:
tmux new-session -d -s agentxchain-daemon 'agentxchain schedule daemon --poll-seconds 60'
What happens next:
- When the schedule becomes due, the daemon starts a schedule-owned continuous session.
- Later polls advance the same session even if the schedule is not due again yet.
- The daemon checks queued work first.
- If nothing is queued, it seeds work from
.planning/VISION.md. - Each run still goes through the real intake lifecycle: plan → start → governed run → resolve.
This is why schedule daemon is the correct unattended owner for schedule-driven operation: it owns heartbeat, status, and later-poll continuation without inventing a second scheduler.
5. Observe the system while it runs
Use these commands while the daemon is active:
agentxchain status
agentxchain status --json
agentxchain schedule status
agentxchain schedule list
agentxchain events --follow
Watch for:
- active
continuous_sessionstate owner_type: "schedule"and the owning schedule idruns_completedversusmax_runscurrent_vision_objectivecontinuous_blocked,continuous_running,continuous_completed, orcontinuous_failed
agentxchain status is the run/session truth surface. agentxchain schedule status is the daemon heartbeat surface. Do not confuse them.
6. Handle blocked and failed states correctly
When the session pauses for a real blocker:
agentxchain status
agentxchain unblock <id>
Rules that matter:
- blocked continuous sessions stay paused, not fake-completed
- after
agentxchain unblock <id>, the next daemon poll resumes the same session - session-budget exhaustion is a terminal stop, not a blocker; start a new session if you want to continue
- non-blocked executor failure leaves the session
failedfor inspection instead of pretending the intake intent completed
If you need the full recovery matrix, use Recovery. This page keeps the operational path short; the recovery page is the canonical blocked-state map.
7. Inject explicit human priority when the vision queue is wrong
Vision seeding is fallback discovery, not authority. Human priority wins.
Inject urgent work like this:
agentxchain inject "Fix the broken release-note sidebar ordering" --priority p0
Or stage lower-priority work without approval:
agentxchain inject "Investigate docs stack migration options" --priority p2 --no-approve
Important behavior:
- injected
p0work preempts new vision seeding - the continuous loop yields with
priority_preemptedand the daemon consumes the injected item first - non-
p0items join the intake queue in normal priority order
For the intake boundary and queue semantics, see Continuous Delivery Intake.
8. Know how the loop stops
Continuous mode stops for specific reasons:
max_runsreachedmax_idle_cyclesreached because no queued or vision-derived work was foundper_session_max_usdor--session-budgetreached- blocked human escalation that you have not resolved yet
- operator
SIGINT
SIGINT behavior is intentional:
- first
Ctrl+C: finish the current in-flight work, then stop - second
Ctrl+C: hard-abort
For daemon-owned operation, stop the daemon the same way you stop any foreground process or session-manager job.
9. Minimum operating discipline
If you want unattended execution without lying to yourself, keep this floor:
- Validate the repo with
doctorandconnector check. - Run one bounded
run --continuous --max-runs 1proof first. - Set a real session budget.
- Watch
status,schedule status, andevents --follow. - Use
inject --priority p0when human judgment needs to override vision seeding. - Use
unblockto resolve true blockers; do not hack state files.
That is the stable repo-local lights-out story today.