Skip to content

Automation & Headless Mode

BMO’s unified automation engine covers unattended execution for CI, scripts, and scheduled tasks. Use bmo run for one-shot non-interactive prompts, bmo recipe run for reusable YAML recipes, and bmo service when you need a long-lived background process or HTTP API server. Hooks stay separate as shell callbacks; they are not part of this engine.

The canonical config surface for structured automation is options.automation: use jobs for cron-backed work and rules for event-driven follow-ons. options.reactions, options.activations, and feature-specific managed schedule blocks are not accepted as public config surfaces; express that work as canonical automation jobs or rules.

For unattended background stewardship, compaction is one built-in automation target. Canonical automation jobs can run builtin://compaction, canonical rules can enqueue compaction jobs with compaction_idle_gate = true, and the nap controller can originate idle wakeups while the autopilot service or the scheduler daemon is running. See Compaction.

This repo can also reconcile a daily docs-refresh job through the canonical automation engine. Configure it as an options.automation.jobs entry that points at the docs-refresh recipe.

[options.automation]
[[options.automation.jobs]]
id = "daily-review"
enabled = true
cron = "0 0 9 * * *"
recipe_path = "recipes/daily-review.yaml"
[[options.automation.rules]]
id = "arena-log"
on = ["arena.accepted"]
[[options.automation.rules.actions]]
type = "notify"
channel = "log"

Use options.automation for new scheduled or event-driven work.

Use the shared inspect family when you need to see whether canonical options.automation.rules are wired, degraded, or actively producing recent follow-on activity.

Terminal window
bmo config show-activation-reactions
bmo config show-activation-reactions --format=json

When the HTTP service is running, the live app-backed HTTP view is:

Terminal window
curl -s "$BMO_HTTP/v1/posture/activation-reactions"
curl -s "$BMO_HTTP/v1/posture/activation-reactions?session_id=$SID"

The TUI exposes /activation-reactions. Native agent and MCP parity use get_activation_reactions_status and bmo_get_activation_reactions_status. The CLI command is truthful about process boundaries: it is a config-only out-of-process view and does not claim access to the live in-process recent ring.

--auto-approve-tools approves ordinary tool permission requests without an interactive prompt. Session mode, tool policy, convergence admission and signed-effect authority still determine which actions may execute. Use it when you have authorized unattended file and shell operations within that boundary.

Terminal window
bmo run --auto-approve-tools "Review the PR diff and print a short summary"

bmo run skips the TUI and exits when the prompt completes. Add --auto-approve-tools for unattended runs that should not stop on permission prompts.

What you should see: BMO prints the response to stdout and exits. Progress, logs, and diagnostics use stderr. Check echo $? for the exit code (see table below). For script-safe output, prefer --output-format=json --quiet.

Recovery: If bmo run modifies files unexpectedly, use git diff to inspect changes and reverse only the affected files or hunks. In CI, run BMO in a clean checkout to limit blast radius.

With no --work-class, BMO uses the default recovery frontier. For an unattended source implementation task, declare --work-class repair:

Terminal window
bmo run --work-class repair --force-session-mode code --auto-approve-tools \
--max-turns 80 "Implement the bounded change and run its focused test"

repair declares open-ended source mutation work. It does not grant extra read or mutation authority, replenish exhausted allowance, or establish verifier success. Review the actual source changes and focused verification evidence. When a run hands off unresolved work, inspect its bounded result and remaining obligation before continuing; a fresh session does not erase that obligation. See the CLI command reference for the supported work-class and run-budget options.

Terminal window
bmo run --session-id <session-id> "Continue where we left off"

This starts a new process using the existing session. For persisted lifecycle admission, configure a stable BMO_LIFECYCLE_AUTHORITY_ATTESTATION_KEY before the original run, then use the same key and data directory when resuming. BMO preserves the admission record and refuses unverifiable authority. A key introduced after the original run cannot authenticate its process-local signature. Resume does not restore spent allowance. See Environment variables for the key’s scope.

CodeMeaning
0Agent completed successfully
1Agent error (model error, tool failure)
2Autopilot configuration error before the agent workflow starts

Lifecycle-hook vetoes currently surface as agent workflow failures (1) unless a more specific runtime exit code is introduced.

Terminal window
bmo run "Summarize the last 20 commits" | tee summary.txt

In CI, pin to a known BMO version and run in a fresh checkout. --auto-approve-tools removes ordinary permission prompts within the admitted execution boundary. Review instructions derived from untrusted inputs, such as PR titles or commit messages, before allowing unattended execution.

.github/workflows/review.yml
- name: AI code review
run: |
bmo run --auto-approve-tools "Review the diff in this PR. Output findings to findings.md"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Verify it worked: Check the CI step exit code and the findings.md artifact. Exit code 0 means success; 1 means an agent error occurred (see exit codes above).

A recipe is a runnable YAML workflow (on-demand or scheduled); a skill is an in-session instruction set (SKILL.md) that shapes how the agent behaves. Both are first-class agent entrypoints.

Recipes are reusable YAML workflows with instructions, optional parameters, and runtime settings:

~/.config/bmo/recipes/daily-review.yaml
title: Daily Review
description: Summarize today's git activity
prompt: Review my git log from today and summarize key changes.

Run with:

Terminal window
bmo recipe run daily-review --auto-approve-tools

You can also use bmo run --recipe daily-review. Pass parameters with --param key=value (or -p key=value), repeatable:

Terminal window
bmo run --recipe deploy-check -p env=staging -p region=us-east-1 --auto-approve-tools

bmo run --recipe does not accept --max-turns; set recipe turn budgets in the recipe settings. When both settings.preset and settings.max_turns are set, the preset supplies the run budget.

What you should see: BMO loads the recipe, substitutes parameters, runs the prompt, and exits. Simple recipe responses appear on stdout; pipeline recipes persist declared outputs and report stage progress separately.

Verify it worked: Check exit code 0 and review any files the recipe was expected to create or modify.

Recipes and skills as agent entrypoints. A recipe run is a first-class agent run: one prompt, one execution, optional parameters. Schedule a recipe with bmo schedule add ... to run that agent on a cron; use bmo recipe run or bmo run --recipe for on-demand runs. Skills (see Agent Skills) extend the agent’s instructions in-session; combine them with recipes or scheduled jobs when you want repeatable, scriptable agent behavior.

For headless execution, --auto-approve-tools approves ordinary tool permission requests for that run. Convergence admission and signed-effect authority remain in force. Review the allowed file and shell operations before enabling unattended execution.

Terminal window
bmo run --auto-approve-tools "Review the current repo and keep the docs in sync"
bmo service start autopilot --listen 127.0.0.1:8080 --auth local

Plain bmo run "<prompt>" executes once and exits. Use bmo service start autopilot when you need the long-lived composed runtime (HTTP API + scheduler), or bmo service start http when you only need the HTTP API server.

What you should see: bmo run executes the prompt, writes the response to stdout, uses stderr for progress and diagnostics, and exits when the run completes. bmo service start autopilot stays attached until you stop the managed service.

Recovery: For a one-shot run, inspect git log and git diff after it finishes. For long-lived services, send SIGINT (ctrl+c) or SIGTERM, or stop the managed runtime with bmo service stop autopilot.

Automation entrypoints
shared run substrate session runner, tool policy, stdout, artifacts, and run history

CLI

  1. bmo run
  2. optional recipe
  3. params
  4. stdout

Best for one prompt in CI or a shell script.

Scheduler

  1. cron
  2. job
  3. recipe
  4. history

Best for repeatable unattended stewardship.

Rules

  1. event
  2. action
  3. notify
  4. artifact

Best for event-driven follow-ons from canonical automation config.

Hooks

  1. shell
  2. veto
  3. log
  4. exit

Separate callbacks around runs, not canonical automation jobs.

Automation paths share the run substrate, while hooks stay outside the canonical automation engine.