Depute Logo

Run Controls

Let users pause, resume, or stop a running agent.

Install

npx ax-depute@latest add run-controls
pnpm dlx ax-depute@latest add run-controls
yarn dlx ax-depute@latest add run-controls
bunx ax-depute@latest add run-controls

Overview

Minimal execution steering — pause, resume, stop, retry. Intentionally kept simple. Extend via the actions slot for additional controls.

Interactive StorybookView all states, toggle props, and test edge cases.

Basic usage

<Run Controls
  state="running"
  onPause={() => agent.pause()}
  onStop={() => agent.kill()}
/>

With local state

import { useState } from 'react';
import type { RunState } from '@/types/ax-common';

export function ExecutionWrapper() {
  const [state, setState] = useState<RunState>('running');

  return (
    <Run Controls 
      state={state} 
      showLabel={true}
      onStart={() => setState('running')}
      onPause={() => setState('paused')}
      onStop={() => setState('stopped')}
      onRetry={() => setState('running')}
    />
  );
}

Props

PropTypeDefaultDescription
stateRunStateRequiredCurrent execution state ('idle' | 'running' | 'paused' | 'completed' | 'failed' | 'stopped').
onStart() => voidundefinedCallback fired when user clicks start or resume.
onPause() => voidundefinedCallback fired when user clicks pause.
onStop() => voidundefinedCallback fired when user clicks stop (cancel execution entirely).
onRetry() => voidundefinedCallback fired when user clicks retry after a failure state.
showLabelbooleanfalseWhether to display a text label showing the current state next to the pulsing indicator.
actionsReactNodeundefinedSlot for additional custom action buttons (e.g., an Undo button).

When to use

  • An agent is actively running and the user needs the ability to intervene at any time — pause, steer, or hard-stop
  • The execution is long-running (multi-step, multi-tool) and the user may need to inspect progress before the agent continues
  • Your product has compliance or safety requirements that mandate a human escape hatch during autonomous operation

When not to use

  • The agent run is fully instantaneous (< 1 second) — there is no execution window in which a control is meaningful
  • The agent is running fully headless/background with no synchronous user session; surfacing controls the user cannot act on is confusing
  • You're only displaying results after an agent has already completed — use Artifact Card to present the output, not Run Controls

Accessibility

  • Buttons use native <button> elements — no div onClick wrappers
  • Each button has an explicit aria-label (e.g., "Pause agent run", "Stop agent run") independent of any icon or visual state
  • Active state is communicated via aria-pressed where applicable (e.g., paused state on the pause button)
  • The pulsing status indicator is marked aria-hidden="true" — status is conveyed via aria-live text, not animation
  • All state transitions (running → paused, paused → running) are announced via aria-live="polite"

Solution Patterns

Run Controls is the central execution steering wheel, usually placed immmediately before or right next to an agent's Tool Trace:

Plan Card → Approval Gate → [Run Controls] → Tool Trace → Artifact Card

It controls whether the Tool Trace continues to append new events or pauses execution.

Design rationale

Why a hard stop? When an agent is running autonomously, the human supervisor must always have an immediate, unambiguous way to halt it — not a "cancel this step" or "skip this action," but a full stop. The same instinct behind the physical emergency stop button on industrial machinery applies here: the safest systems always prioritize the human's ability to exit over the system's ability to complete. Run Controls makes that affordance obvious and persistent throughout the execution lifecycle.

Why derive controls from state? The controls are not a static button group. They derive from the state prop — so if the agent has already completed, the stop button disappears. If it has failed, the retry button appears. This isn't just DX convenience: it prevents the class of bug where a developer shows a stop button on a completed run, or a resume button on a failed one. The UI cannot express an impossible transition because impossible transitions have no visual representation.

On this page