Lifecycle Hooks
BMO exposes hook planes:
runloophooks run inside the BMO engine around inference and tool uselifecyclehooks run around session and agent-turn envelope eventsoutcomeshooks run after arena accept, stitch, verified file merge, arena workflow step completion, andorchestrate_workflow/execute_dagterminals (advisory only)options.automation.rulesis the canonical in-process follow-on layer for structured automation. Use reaction-style actions (run_recipe,notify,enqueue_job) for lightweight glue and activation-style actions for typed orchestration.
Hooks are external shell callbacks. Structured automation rules are separate from hooks and stay in-process.
For the broader orchestration map, see Workflow map and Staged Workflow.
For contributors: Deeper event-graph semantics live in the repository topics
reactions.mdandactivation-graph.md.
Hooks are shell commands. Blocking behavior depends on the specific hook event; it is not uniform across the whole surface.
Configuration
Section titled “Configuration”[options.hooks.runloop] [[options.hooks.runloop.pre_tool_use]] type = "command" command = "check-tool-policy" timeout = 30
[[options.hooks.runloop.post_tool_use]] type = "command" command = "audit-log-tool"
[[options.hooks.runloop.pre_inference]] type = "command" command = "check-budget"
[[options.hooks.runloop.post_inference]] type = "command" command = "log-tokens"
[options.hooks.lifecycle] [[options.hooks.lifecycle.session_start]] type = "command" command = "notify-start"
[[options.hooks.lifecycle.session_end]] type = "command" command = "notify-end"
[[options.hooks.lifecycle.before_agent]] type = "command" command = "validate-context"
[[options.hooks.lifecycle.after_agent]] type = "command" command = "summarize-turn"
[options.hooks.outcomes] [[options.hooks.outcomes.arena_accepted]] type = "command" command = "jq . >&2" timeout = 30
[[options.hooks.outcomes.arena_stitched]] type = "command" command = "jq . >&2"
[[options.hooks.outcomes.arena_merged]] type = "command" command = "jq . >&2"
[[options.hooks.outcomes.arena_workflow_step_completed]] type = "command" command = "jq . >&2"
[[options.hooks.outcomes.workflow_completed]] type = "command" command = "jq . >&2"
[[options.hooks.outcomes.workflow_failed]] type = "command" command = "jq . >&2"Legacy flat keys such as [[options.hooks.pre_tool_use]] and
[[options.hooks.before_agent]] are still accepted as compatibility aliases,
but the nested runloop and lifecycle sections are canonical.
Runloop Hooks
Section titled “Runloop Hooks”These hooks are converted into the BMO engine runloop hook chain.
| Hook | Blocking | Description |
|---|---|---|
pre_tool_use | Yes | Runs before each tool call; exit 2 blocks the call and stderr becomes the tool result |
post_tool_use | No | Runs after each tool call; best-effort |
pre_inference | No | Runs before each LLM inference call; command failures are advisory |
post_inference | No | Runs after each LLM inference call; command failures are advisory |
Lifecycle Hooks
Section titled “Lifecycle Hooks”These hooks stay outside the BMO engine and wrap session or turn lifecycle.
| Hook | Blocking | Description |
|---|---|---|
session_start | No | Runs when a session is created; advisory, non-blocking |
session_end | No | Runs when a session is deleted; best-effort |
before_agent | Yes | Runs at the start of each agent turn; exit 2 blocks the turn |
after_agent | No | Runs at the end of each agent turn; best-effort |
Outcome hooks (arena, arena workflow, DAG tools)
Section titled “Outcome hooks (arena, arena workflow, DAG tools)”These run after the corresponding coordinator success paths, in a background goroutine (they do not delay accept/stitch/merge in the UI). Exit code 2 does not block BMO; it is logged like any other non-zero exit.
| Hook | Blocking | Description |
|---|---|---|
arena_accepted | No | After a successful arena candidate accept |
arena_stitched | No | After a successful arena prose stitch |
arena_merged | No | After a successful verified arena file merge (arena_merge / HTTP / MCP) |
arena_workflow_step_completed | No | After an arena workflow step is marked completed |
workflow_completed | No | After orchestrate_workflow or execute_dag finishes with all nodes completed |
workflow_failed | No | After those tools finish with failures, skipped nodes, or an executor error |
Stdin JSON includes schema_version (currently 1), event (e.g. arena_accepted, arena_merged, workflow_completed), session_id, and event-specific fields (user_message_id, model_key, candidate_id, assistant_message_id, candidate_ids, merge_signature, merged_paths, workflow_id, step_id, phase, workflow_run_id, workflow_tool, workflow_source, etc.). See the generated configuration reference for the full field list.
Hook Entry Fields
Section titled “Hook Entry Fields”| Field | Required | Description |
|---|---|---|
type | Yes | Always "command" |
command | Yes | Shell command to execute |
timeout | No | Timeout in seconds (default: 30) |
Hook Input
Section titled “Hook Input”Hooks inherit the normal BMO process environment. BMO-specific hook context is
passed on stdin as JSON.
Runloop hook input includes event-specific fields such as:
- inference hooks:
hook_event,model - tool hooks:
hook_event,tool_name,tool_id,arguments
Lifecycle hook input includes event-specific fields such as:
session_start:hook_event,session_id,cwd,titlesession_end:hook_event,session_id,cwdbefore_agent:hook_event,session_id,cwd,prompt_previewafter_agent:hook_event,session_id,cwd,completed,error_preview
Team Lifecycle Hooks
Section titled “Team Lifecycle Hooks”For team quality gates, use team_hooks instead:
[[options.team_hooks.teammate_idle]]type = "command"command = "validate-output"
[[options.team_hooks.task_completed]]type = "command"command = "run-acceptance-tests"| Hook | Description |
|---|---|
teammate_idle | Runs when a teammate finishes its turn; exit 2 blocks idle and re-injects stderr |
task_completed | Runs when a task is marked completed; exit 2 blocks completion |
Use Cases
Section titled “Use Cases”- Audit logging — record every tool call to a file or external system
- Budget checks —
pre_inferencehook records or warns on budget state before inference - Policy gates —
pre_tool_usehook blocks destructive operations in production environments - Notifications —
session_start/session_endhooks send Slack or webhook messages
Related
Section titled “Related”- Configuration — hook tables, automation rules, and compatibility aliases
- Workflow map — how hooks sit alongside staged workflows, mesh, and compaction
- How BMO thinks and acts — system-level coordination model