bonsai

Agents and modes

bonsai distinguishes agents (user-facing personas in the main conversation) from subagents (scoped delegations that return only a conclusion). Both can be extended with markdown definitions — no source changes.

Agent modes

An agent mode picks the persona, tool registry, and view:

Custom agents with surface: [mode] join the Shift+Tab persona cycle. A user-facing agent always runs on the active session model; model/fallback_model assignments apply when the same definition is invoked as a subagent.

Subagents

A subagent runs a focused sub-task in its own fresh conversation with its own prompt and tool registry, then returns only its conclusion to the parent — internal turns never enter the main context, so delegations like “map how X works” keep the parent lean. The parent’s model sees a byte-stable Subagents index in its prompt and delegates through the agent tool on its own; you can also nudge it (“use the explore subagent to find where sessions are persisted”).

Built-ins (read-only, reserved ids):

Subagent Purpose Budget
explore breadth-first codebase orientation; returns file:line conclusions 12 turns / 450 s
review read-only review of current uncommitted changes 12 turns / 450 s
research depth-first investigation and synthesis 36 turns / 900 s
security-review read-only audit of effects, auth/untrusted-data boundaries, dependencies 12 turns / 450 s

Mechanics:

Defining your own

Drop a markdown file with YAML frontmatter into an agents/ directory (standard resource precedence: .bonsai/agents/ > .claude/agents/ > .agents/agents/ > $BONSAI_HOME/agents/; project files need workspace trust; built-in ids are reserved):

---
name: api-explorer
description: Maps HTTP routes and handlers, returns file:line
tools: [read, grep, symbol_search]
surface: [subagent]          # [mode] for Shift+Tab, or [mode, subagent] for both
# model: f                   # a shortcut letter, or codex:openai/gpt-5.5
# effort: low
# fallback_model: anthropic:anthropic/claude-sonnet-4-6
# fallback_effort: medium
---
You are a read-only API exploration subagent. Locate route/handler definitions
with grep and symbol_search and report them as `file:line` with method + path.
Do not modify anything.
Field Required Meaning
name yes definition id; match the filename; built-in ids reserved
description yes one line for /agents and the model’s Subagents index
surface no [subagent] (default), [mode], or [mode, subagent]
tools no grant scope; omit for the read-only default. Grantable: the read-only core plus write, edit, apply_patch, bash, terminal, rename_symbol, skill, question, webfetch. Unknown names are ignored and reported by /agents.
model / effort no model selector when invoked as a subagent — a shortcut letter (follows the live binding) or a full /model selector; omit to inherit the parent model
fallback_model / fallback_effort no backup used when the primary is unavailable or fails after normal retries
enabled no default true; disabled definitions stay visible but can’t run
view / color no presentation for a mode-surface agent
max_turns no custom-subagent turn cap (1–500)
permission unsupported recognized for compatibility but rejected until agent-scoped permission profiles are enforced

Model resolution order: a live /subagents override (session-scoped) → modelfallback_model → the parent model. Provider failover is sticky for the rest of one delegated run and applies only to provider errors — never to cancellation, permission or tool failures, timeouts, or budget exhaustion. Built-in read-only lanes cap reasoning effort at medium (downshift only).

/agents new opens a composer wizard (details → tools → prompt → review, with Ctrl+G prompt generation); /agents init writes an example file.

Self-review

Before the coding agent reports a task done, it can run a self-review pass: the uncommitted diff (scoped to changes this run actually made — peer-session edits are subtracted) is handed to a fresh read-only reviewer subagent, and the critique comes back as harness evidence — “a reviewer examined your changes; fix anything genuinely wrong, then confirm.” If something is wrong the agent fixes it in place; otherwise it confirms and stops. At most once per user message; skipped when nothing changed or the diff is trivial.

/self-review auto | on | ask | off | status:

Mode Runs
auto (default) follows autonomy — on at balanced and above
on always
ask prompts each time (skipped when noninteractive)
off never

Set a startup default with BONSAI_SELF_REVIEW=auto|on|ask|off. Reviewer disposition (fixed / none-needed / rebutted) and finding counts are recorded and surfaced in the completion report.

Reviewer model. By default the reviewer runs on the parent model. Pin a different one — cheaper, or independent for less correlated blind spots — with /self-review model, which opens the model picker; /self-review model default clears it. The choice persists under the self-review built-in-subagent settings id (the same store as /subagents assignments), so it survives a restart. Self-review is not a delegatable subagent — it never appears in the /subagents picker and the model can’t call it — which is why its model lives under /self-review, next to its mode toggle.

Where this lives in the code

Concern Location
Personas & prompts src/agent/persona.rs, src/agent/prompts.rs
Subagent registry & live view src/subagent.rs
Delegation tool, catalog, runner src/tool/agent/
Custom definitions src/resource/agent.rs (discovery: src/resource/discovery.rs)
Self-review src/self_review.rs, src/agent/self_review.rs