Skip to main content

Modes

A mode is a named overlay on a session that changes how the agent works: which tools it may call, an extra piece of system prompt, and per-mode limits. An app declares its modes under runtime.modes; the session is always in exactly one mode at a time. The classic pair is Plan (read-only: investigate and propose) and Build (full access: implement) - but modes are general, and you can define whatever set fits the app.

Two things can change the active mode:

  • The user, via the mode picker in the composer.
  • The agent itself, mid-turn, with the change_mode tool - but only when the app opts in with runtime.agent_can_switch_mode: true (see below).

Declaring modes​

yaml
runtime:
default_mode: plan # which mode a fresh session starts in
agent_can_switch_mode: true # let the agent switch modes itself (opt-in)
modes:
plan:
label: Plan
description: "Read-only: investigate and propose."
icon: lightbulb
system_prompt: "You are in PLAN mode. Investigate and propose; do not edit."
tool_grants:
- module: filesystem
tools: [read, glob, grep]
build:
label: Build
description: "Full access: implement the plan."
icon: wrench

Each mode (ModeDef) accepts, all optional:

FieldWhat it does
labelHuman name shown in the picker (defaults to the mode id, capitalised).
descriptionOne line explaining the mode.
icon, accentUI hints for the picker.
system_promptExtra system prompt appended for this mode - "you are in PLAN mode, do not edit".
tool_grantsThe tools this mode allows (same shape as capabilities.grant). Omit it for full access.
max_turns, timeoutPer-mode overrides of the runtime defaults.
behavior_profileSwitch the behavior profile for this mode.

runtime.default_mode names the starting mode; if omitted, the first declared mode is the default.

How tool_grants filters tools​

A mode's tool_grants is a ceiling on what the agent may call while in that mode:

  • Present → the agent is restricted to exactly those tools. Everything else is blocked for that mode (a blocked call returns a clear "not available in this mode" error to the agent). This is how Plan stays read-only.
  • Absent → the mode does not restrict; the agent keeps its full tool surface. This is how Build gets full access.

The final tool surface is the intersection of three things: the app's grants, the agent's own agents[].modules allowlist (if any), and the active mode's tool_grants. Meta-tools (ask_user, change_mode, …) are always available regardless of mode.

Letting the agent switch modes​

Set runtime.agent_can_switch_mode: true and the agent is given a change_mode tool automatically. The system also tells the agent, each turn, which modes exist and that it can switch - you do not write that into the prompt yourself; it is generated from the real declared modes.

The agent calls change_mode(mode: "build"). Then:

  1. The user sees a confirmation bar above the composer ("the agent is switching from Plan to Build") with a short window to cancel. If they cancel, the switch is refused and the agent is told so; the mode is unchanged.
  2. Otherwise the switch applies, mid-turn: from the next step of the same turn, the agent runs under the new mode's tools and limits - so it can finish planning and then immediately start building, without waiting for a new message.

This is opt-in per app because a mode switch changes the whole turn (which tools are allowed, the prompt). Leave agent_can_switch_mode off and only the user can switch.

Don't trap the agent

If Plan is read-only and you want the agent to be able to leave it, you must set agent_can_switch_mode: true. change_mode itself is never blocked by a mode's tool_grants (it's a meta-tool), so a read-only mode can't strip the agent's only way out.

A working app​

Plan/Build for a coding agent. Compiles as-is (the brain uses a Digitorn gateway model - no API key of your own needed):

yaml
app:
app_id: coder
name: Coder
runtime:
entry_agent: main
default_mode: plan
agent_can_switch_mode: true
modes:
plan:
label: Plan
description: "Read-only: investigate and propose."
icon: lightbulb
system_prompt: "You are in PLAN mode. Investigate and propose; do not edit."
tool_grants:
- module: filesystem
tools: [read, glob, grep]
build:
label: Build
description: "Full access: implement the plan."
icon: wrench
agents:
- id: main
system_prompt: "You help with code. In Plan, investigate and propose. When the plan is ready, switch to Build and implement it."
brain:
provider: openai
backend: openai_compat
model: mimo-v2.5-free
config:
api_key: placeholder
tools:
modules:
filesystem: {}
bash: {}
capabilities:
default_policy: auto