# Background Tasks

Long-running work can run in the background so the conversation stays responsive. Two execution surfaces support this: **background shell tasks** and **detached subagents**.

## Background Shell Tasks

Pass `background: true` to the `bash` tool to detach a shell command from the foreground turn. The tool returns a `task_id` immediately and the conversation continues.

```
User: run the full test suite
AI: [calls bash with background=true]
     → task_id: abc12345, status: running
AI: Tests are running in the background. I'll check on them shortly.
```

Use `bash_background_status` to poll progress and `bash_task_output` to retrieve full stdout/stderr once complete. Both are READ-tier tools (auto-allowed).

See [Built-in Tools](tools.md) for the full parameter reference.

## Detached Subagents

Pass `detach: true` to the `run_agent` tool to launch an isolated AI session that runs independently. The parent turn ends immediately with a run ID.

Use `agent_run_status` to check progress or wait for the completion notification. Detached agents are not available in exec mode or nested subagents.

See [Built-in Tools](tools.md) for the full parameter reference.

## Live subagent progress (#1460)

**Foreground subagents (CLI)** render a compact live-status surface instead of per-tool breadcrumbs:

- On launch: `▶ agent-id (model) prompt preview…`
- While running: tool calls accumulate silently (no per-call noise)
- On completion: `✓ agent-id done · 4.2s · 3 tools` (success) or `✗ agent-id: failed · 1.1s · timeout` (failure)

**Detached subagents (CLI)** emit a themed completion notification from the background poller when they finish: `✓ [agent <id8>] "label" done · <duration>s · <tool_count> tool(s) · <summary_preview>` or `✗ [agent <id8>] "label" failed · <duration>s · <error_preview>`. The label is the explicit `description` field if set at launch, otherwise the prompt prefix. Runs with an explicit description also show stable labels in `/agent list`.

**Web UI** displays each active sub-agent as an inline card that updates in-place via `subagent_event` SSE frames. Cards transition from `subagent-running` to `subagent-completed`, `subagent-failed`, or `subagent-cancelled` once the agent finishes, with a footer showing duration and tool count.

The `/agent status <id>` REPL slash command surfaces a `Model:` line showing the model the run was launched with when the caller supplied one at launch (#1459).

## Hook inheritance for subagents (#1493)

Runtime hooks (`pre_tool`, `post_tool`) apply inside subagents under a defined contract:

**Foreground subagents** receive the parent session's resolved hook config directly. No independent config reload occurs. The same hook rules that govern the parent govern every tool call the subagent makes.

**Detached subagents** snapshot the resolved hook config at launch time. Changes to hook configuration after a detached run starts do not affect the in-flight run. Each retry of a failed detached run takes a fresh snapshot.

Hook dispatch includes subagent correlation IDs:

| ID | Description |
|----|-------------|
| `parent_conversation_id` | Conversation ID of the parent session |
| `parent_tool_call_id` | Tool call ID of the `run_agent` invocation in the parent |
| `child_agent_id` | Foreground agent ID (set for foreground subagents) |
| `detached_run_id` | Detached run ID (set for detached subagents) |

These IDs are available in hook command environment variables (prefixed `ANTEROOM_HOOK_`) and in webhook payloads, allowing hook scripts to distinguish parent and child tool calls in audit logs.

## Lifecycle audit events (#1459)

Detached subagent runs emit four structured audit events:

| Event | Severity | When |
|-------|----------|------|
| `subagent.spawned` | info | When the run is created (in both `start()` and `retry()`) |
| `subagent.completed` | info | When the run exits successfully |
| `subagent.failed` | warning | When the run reports an error or the collector crashes |
| `subagent.cancelled` | warning | When the run is cancelled by an operator, the parent, or process shutdown |

Payload always includes `run_id` and `conversation_id`; `model` is
included when the caller supplied one; `parent_run_id` appears on
`spawned` events for retries and on every terminal event in a retry
chain.

Operator-initiated cancel via `/agent cancel <id>` emits exactly one
`subagent.cancelled` event even when the collector is still running —
the in-flight collector detects the operator intent via a sentinel and
suppresses its own duplicate emission.

## Completion Notifications

Both surfaces announce completion automatically. The CLI renders a one-line notice:

- **Shell tasks**: `[bg] Task <id> completed (exit 0, 45s)`
- **Detached agents** (success): `✓ [agent <id8>] done · <elapsed>s · <N> tools · <summary>`
- **Detached agents** (cancelled): `⊘ [agent <id8>] cancelled · <elapsed>s`
- **Detached agents** (failure): `✗ [agent <id8>] failed · <elapsed>s · <error_preview>`

The `[agent <id8>]` bracket prefix is rendered in the theme chrome color; the status symbol and trailing detail use the theme success/error/muted colors respectively.

The web UI surfaces the same events via SSE.

## Execution Surface Routing

Anteroom advises the AI on which surface to use based on expected task duration:

| Duration | Suggested surface |
|---|---|
| < `background_suggest_seconds` | Inline (foreground) |
| >= `background_suggest_seconds` | Background shell task |
| >= `detach_suggest_seconds` | Detached subagent |

## Configuration

```yaml
cli:
  background_suggest_seconds: 30   # suggest background for tasks >= 30s
  detach_suggest_seconds: 120      # suggest detached subagent for tasks >= 2min
```

Set either to `0` to disable the suggestion for that surface.

Detached subagent limits and governance are configured under `safety.subagent` (#1459):

```yaml
safety:
  subagent:
    max_concurrent: 5   # concurrent detached runs per conversation
    max_total: 10       # maximum concurrent detached runs across the whole process
    max_depth: 3        # max nesting depth for foreground sub-agents
    max_iterations: 15  # tool-call budget per sub-agent turn
    timeout: 120        # seconds before a detached run is killed
```

See [config reference](../knowledge/config-reference.md#safetysubagent) for the full field table, and [audit log](../security/audit-log.md) for the `subagent.*` event taxonomy.
