Skip to content

Orchestration Board

The Board tab in the command center provides a visual task orchestration interface at optimal.miami. It merges kanban tasks from Supabase with live agent sessions from the StateHub into a unified view.

Layout

The board uses a three-column kanban layout:

ColumnTask statusesSession states
Queuedbacklog, readyidle
Activein_progress, claimedrunning
Reviewreview, blockedawaiting_review, completed, failed

Epic Swimlanes

Tasks are organized into collapsible epic swimlanes. Each epic swimlane shows:

  • Epic title
  • Progress indicator (e.g., "3/7 done") counting completed children
  • Collapsible section containing stories and direct tasks

Stories within an epic can themselves contain sub-tasks, forming a three-level hierarchy: epic > story > task.

Ungrouped tasks (those without a parent epic) appear in a separate "Ungrouped" section at the bottom.

Task Cards

Task cards display:

  • Status dot (color-coded by state)
  • Title
  • Project or source repo
  • Type badge (epic, story, task) with distinct colors (peach for epic, mauve for story, blue for task)
  • Priority badge (P1--P4)

Clicking a task card opens a detail panel (slide-in on desktop, bottom sheet on mobile) showing the full description, children list, metadata, and a launch agent button.

Agent Session Cards

Agent session cards display:

  • Status dot (color-coded by state)
  • Label and agent type icon
  • Agent type and tmux session name
  • Last activity timestamp
  • Truncated prompt (expandable)
  • Quick action buttons

Quick Actions on Session Cards

ActionWhen visibleWhat it does
Stoprunning, awaiting_reviewSends SIGINT via /api/agents/stop
Restartcompleted, failedRe-launches the session
Resumeawaiting_reviewTransitions back to running
Dismisscompleted, failedRemoves the session
Attachalways (if tmux session exists)Opens a terminal tab attached to the tmux session

Status Dots

Color-coded dots indicate the state of tasks and sessions:

ColorStates
Bluerunning, in_progress, claimed
Greencompleted, done
Yellowawaiting_review, review
Redfailed, blocked
Dim (gray)idle, backlog, ready, and other states

Session State Machine

Every agent session follows a deterministic state machine with 5 states:

idle --> running --> awaiting_review --> completed
                                    --> failed
StateMeaning
idleSession created, agent not yet started
runningAgent is actively working
awaiting_reviewAgent finished or paused, waiting for human input
completedWork finished successfully
failedAgent errored or was cancelled

Transitions

FromEventTo
idlestartrunning
runninghook.to_review, agent.prompt_readyawaiting_review
runningprocess.exitcompleted
runningprocess.exit_error, user.cancelfailed
awaiting_reviewhook.to_running, user.resume, agent.tool_userunning
awaiting_reviewprocess.exitcompleted
awaiting_reviewprocess.exit_error, user.cancelfailed
completedstartrunning (restart)
completeduser.requeueidle
failedstartrunning (retry)
faileduser.requeueidle

State transitions happen automatically via lifecycle hooks (see Hook System) or can be triggered manually by dragging session cards between columns on the board.

Session Discovery

A background scanner runs every 30 seconds, listing all tmux sessions via tmux list-sessions. It:

  1. Auto-registers any tmux session with an agent- prefix that is not already tracked
  2. Checks non-prefixed sessions for the OPTIMALOS_SESSION_TMUX environment variable
  3. Infers agent type from session name (claude -> claude-code, openclaw -> openclaw, otherwise shell)
  4. Marks tracked sessions as ended if their tmux session has disappeared

Session Persistence

Sessions are stored in ~/.optimalos/sessions.json with debounced writes (500ms). On server restart, sessions are restored from disk. Completed and failed sessions older than 24 hours are pruned on load.

On shutdown (SIGINT/SIGTERM), sessions are flushed synchronously to prevent data loss.

Agent Launcher

The board includes a launch modal accessible from the toolbar or task detail panel.

Launch API

POST /api/agents/launch
Authorization: Bearer <token>
Content-Type: application/json
json
{
  "agent_type": "claude-code",
  "prompt": "Fix the login timeout bug",
  "task_id": "task-uuid",
  "session_name": "agent-login-fix",
  "depends_on": ["other-task-uuid"],
  "working_dir": "/home/oracle/.openclaw/workspace/optimalOS",
  "interactive": false
}
FieldRequiredDescription
agent_typeYesclaude-code, openclaw, or shell
promptYes (unless interactive)The prompt or command to run
task_idNoLink to a kanban task
session_nameNoCustom tmux session name (auto-generated if omitted)
depends_onNoArray of task IDs this session depends on
working_dirNoWorking directory (defaults to $HOME)
interactiveNoLaunch Claude Code in interactive mode (claude-code only)

Agent Types

Agent types are config-driven — the catalog is loaded from config.agents in ~/.optimalos/config.json rather than hardcoded. Common types shipped in the default catalog:

TypeCommand
claude-codeclaude --print '<prompt>' (or bare claude in interactive mode).
openclawopenclaw agent --message '<prompt>'.
shellRuns the prompt directly as a shell command.

Custom agent types (Kimi, Codex, Aider, anything PTY-friendly) can be added by extending config.agents with a new entry that supplies a command template. See optimalOS/src/agents/catalog.ts.

The launcher injects OPTIMALOS_SESSION_TMUX and OPTIMALOS_HOOK_PORT environment variables into the tmux session. For Claude Code agents, it also installs hook scripts in ~/.claude/settings.json that curl lifecycle events back to /api/hooks/ingest.

Stop API

POST /api/agents/stop
Authorization: Bearer <token>
Content-Type: application/json
json
{
  "session_id": "session-1"
}

Sends Ctrl+C to the tmux session and transitions the session state to failed.

Dependency Chains

Tasks can declare dependencies on other tasks via depends_on. When a session's linked task completes:

  1. The StateHub checks all idle sessions for unmet dependencies
  2. If all dependencies are satisfied, the session auto-starts (idle -> running)

This allows multi-step workflows where each step triggers the next automatically.

Drag-and-Drop

Session cards support two drag mechanisms:

  • Pointer Events drag (works on mobile and desktop) -- uses pointerdown/pointermove/pointerup with a 5px threshold to distinguish taps from drags
  • HTML5 drag-and-drop fallback for desktop

Dropping a session card on a different column triggers a state transition via PATCH /api/hooks/sessions/:id.

Filters

A filter bar at the top of the board provides:

  • Type filter: Show all, or filter to epics, stories, or tasks only
  • Priority filter: Show all, or filter to P1, P2, P3, or P4

Filters are client-side and applied immediately without server requests.

Real-Time Updates

The board connects to the WebSocket State Hub at /ws/state on load. When a state change arrives:

  1. Session cards are patched individually in the DOM (no full re-render)
  2. Cards move between columns as states change
  3. Status dots and activity timestamps update in place

Multiple browsers or devices viewing the board all stay in sync without polling.

Built by Carlos Lenis in Miami