The Rails on Modes

Making Amplifier's pipeline structural, not advisory

The Gap

Modes governed what an agent could do — never how it moved

Amplifier's mode system already gates what happens inside a mode — blocking deploy, requiring approval to write. But nothing governed how an agent moved between modes. The intended pipeline was documentation, not a guarantee.

So how open was that gap, really?

The gap was real, and it was the default

With allowed_transitions absent (default None) any mode could activate any other. With allow_clear defaulting to True, any agent could /mode off straight out of a workflow.

Those permissive defaults have real consequences for a real workflow.

A prose-only workflow can simply be skipped

Picture an intended plan → implement sequence written only in a mode body. Nothing stopped an agent from jumping straight to implement, or dropping to modeless mid-task.

A workflow you can't enforce isn't a workflow. Enter two fields.

# intended pipeline (prose only) plan implement # but nothing stopped either of: jump straight to implement /mode off (drop to modeless)

allowed_transitions is a whitelist of where you may go

In the mode tool's set handler, an unlisted target returns a hard transition_denied error — and active_mode is left unchanged. Forward movement is now constrained structurally.

That seals forward jumps. But there's still a back door.

allow_clear:false closes the back door

In the clear handler, mode(clear) / /mode off is rejected with a clear_denied error — forcing an explicit move to a valid next mode instead of a silent exit.

Both doors are shut. But does the enforcement actually bite?

The check runs before the gate policy — so it always bites

The gate_policy defaults to 'warn'. But the transition check runs before the gate policy is applied — so a denied jump is a hard transition_denied error, not a soft warning, even under that permissive default.

This is the moment advisory becomes structural.

  1. Transition check — denied? Hard error, stop.
  2. Then gate policy ('warn' default) applies.
  3. Result: hard denial regardless of gate.

The pipeline is now structural — and shipped

The merged worked example proves it: plan may only go to implement and can't clear until it does; implement may go back to plan and can exit when done. A workflow that can no longer be skipped.

And any author can adopt the pattern.

# plan mode allowed_transitions: [implement] allow_clear: false # implement mode allowed_transitions: [plan] allow_clear: true

The body narrates, the field enforces

The two enforcement fields complement prose, they don't replace it: the mode body tells the LLM which transition is appropriate; the frontmatter enforces which is permitted. “They are complementary — don't pick one.”

Optional and backward-compatible — the permissive defaults preserve every existing mode.

Sources

Research Methodology

Status: Merged & shipped — PR #6, latest tag v1.3.1

Data as of: 2026-03-04 (feature commits) — independently fact-checked (verdict: pass).

Repository: ramparte/amplifier-bundle-modes (upstream microsoft/amplifier-bundle-modes).

Feature: allowed_transitions & allow_clear mode-transition enforcement (merge commit 36b77c0, ancestor of HEAD and tag v1.3.1).

Commands run:

Verification: 50/51 tool-mode tests pass; all 23 transition/clear enforcement tests pass. The sole failure (TestClearedEvent) is an unrelated mode:cleared event-payload assertion, outside the enforcement paths.

Gaps: No PR body / GitHub metadata fetched via gh (offline, local git only); PR #6 title/number taken from the local merge-commit message. The illustrative “brainstorm→finish” jump is not the shipped example — the plan/implement pair (§9.5) is.

Primary contributor: Brian Krabach — authored all six enforcement commits (a7eb8fe..36b77c0) and merged PR #6.

More Amplifier Stories