Skip to main content

Modes

Modes define the different behaviors a Harness can run. Each mode layers its own instructions and tool overrides on top of a shared backing agent, so the same agent can act as a planner in one mode and an executor in another. The Harness keeps exactly one mode active at a time, carries the thread and state across switches, and handles the transition between them.

Every Harness needs at least one mode — the modes array is required, and the Harness throws at construction if it's empty. A single-purpose Harness still defines one mode; multiple modes are how you give a session more than one behavior to switch between.

A mode supplies three things that change how the agent behaves:

  • Instructions: layered on top of the backing agent's own instructions while the mode is active.
  • Tools: either replacing or adding to the backing agent's tools (see Mode tool overrides).
  • Model: an optional defaultModelId to bootstrap model selection when the session enters the mode.

Because every mode shares the same backing agent, thread, and state, switching modes changes how the agent behaves without losing conversation context.

Quickstart
Direct link to Quickstart

Import the Harness class and create a new instance with your agent and modes:

src/mastra/harness.ts
import { Harness } from '@mastra/core/harness'
import { myAgent } from './agents'

const harness = new Harness({
id: 'multi-mode',
agent: myAgent,
modes: [
{
id: 'plan',
name: 'Plan',
metadata: { default: true },
instructions: 'Reason about the task before making changes.',
},
{ id: 'build', name: 'Build', instructions: 'Implement the approved plan.' },
],
})

await harness.init()

Defining modes
Direct link to Defining modes

Each mode requires an id. When a top-level agent is provided, modes layer instructions and tool overrides on the shared agent. Each mode can also specify a defaultModelId to bootstrap model selection:

src/mastra/harness.ts
import { Harness } from '@mastra/core/harness'

const harness = new Harness({
id: 'multi-mode',
agent: myAgent,
modes: [
{
id: 'plan',
name: 'Plan',
metadata: { default: true },
defaultModelId: 'anthropic/claude-sonnet-4-6',
instructions: 'Reason about the task before making changes.',
},
{
id: 'build',
name: 'Build',
defaultModelId: 'anthropic/claude-sonnet-4-6',
instructions: 'Implement the approved plan.',
},
],
})

Mode tool overrides
Direct link to Mode tool overrides

Modes support two strategies for tool configuration. Use tools to replace the backing agent's tools entirely, or additionalTools to layer extra tools on top:

// Replace — agent sees only these tools in plan mode
const planMode = { id: 'plan', tools: { planTool } }

// Augment — agent keeps its own tools plus these
const buildMode = { id: 'build', additionalTools: { deployTool } }

You can't set both tools and additionalTools on the same mode.

Mode transitions
Direct link to Mode transitions

A mode can declare a transitionsTo target. When the submit_plan built-in tool runs in that mode, the Harness transitions to the target mode on approval:

const planMode = {
id: 'plan',
name: 'Plan',
transitionsTo: 'build',
instructions: 'Reason about the task and submit a plan.',
}

On plan approval, the Harness automatically switches to build mode. On rejection, the agent remains in plan mode to revise.

Switching modes
Direct link to Switching modes

Call switchMode() to change the active mode. The Harness aborts any in-progress generation, saves the current model to the outgoing mode, loads the incoming mode's model, and emits mode_changed and model_changed events:

await harness.switchMode({ modeId: 'build' })

Querying modes
Direct link to Querying modes

The Harness exposes the full mode catalog, while the Session tracks which mode is active. Use harness.listModes() to read every configured mode, harness.session.mode.get() for the active mode ID, and harness.session.mode.resolve() for the active mode's full definition:

// List all configured modes
const modes = harness.listModes()

// Get the current mode ID
const modeId = harness.session.mode.get()

// Get the full mode object
const mode = harness.session.mode.resolve()