On this page

On this page

Plugin guides

Workboard plugin

The Workboard plugin adds an optional Kanban-style board to the Control UI: agent-sized work cards, assignment to agents, and a link back to the card's task, run, and Control UI session. A separate Sessions board groups existing sessions into editable columns using rules over Gateway-owned facts.

Workboard is intentionally small: it tracks local operating work for one OpenClaw Gateway. It is not a replacement for GitHub Issues, Linear, Jira, or other team project management systems.

Enable it

Workboard is bundled but disabled by default:

  1. Open Plugins in the Control UI, or use /plugins relative to the configured Control UI base path. For example, a base path of /openclaw uses /openclaw/plugins.
  2. Open the Workboard plugin, select Lifecycle, and turn on the enabled switch. Because Workboard is included with OpenClaw, it does not need an Install action.
  3. Wait for the lifecycle action to finish, then open the Workboard tab.

The Workboard tab appears in the Control UI nav after the plugin runtime loads. While it is disabled, the tab stays hidden from navigation. Opening the /workboard route directly while the plugin is disabled or blocked by plugins.allow/plugins.deny shows a plugin-unavailable state instead of card data.

The equivalent CLI workflow is:

bash
openclaw plugins enable workboardopenclaw dashboard

Enablement applies to a running Gateway automatically. If it is offline, start it before opening the dashboard. See Apply changes and inspect.

Configuration

Workboard has no plugin-specific config. Enable/disable it with the standard plugin entry:

json5
{  plugins: {    entries: {      workboard: {        enabled: true,        config: {},      },    },  },}
bash
openclaw plugins disable workboard

Board appearance

While Workboard is open, its sidebar entry expands to show both Cards and Sessions boards, with the open board highlighted. Select a nested board to open it. Sidebar labels use the board name; boards with the same name include their kind in parentheses, such as Planning (cards) and Planning (sessions). Boards you create in the Control UI are pinned in the sidebar immediately. Right-click a board, or focus its link and press Shift+F10 or the context-menu key, to Pin to sidebar, Unpin from sidebar, or Delete board…. Deleting asks for confirmation naming the board and requires write access. The default board and boards that still contain cards cannot be deleted. Deleting the open board returns to the Workboard root page. You can also use Customize to manage pins; removed pins stay removed. Pinned boards remain available as top-level entries when you leave Workboard, and you can drag them to reorder them.

Choose New board, then Cards (the default) or Sessions. A Sessions board starts with the columns described below. A board's kind is permanent; create another board to use the other kind. Existing boards remain Cards boards.

Use Edit board to change a board's name, icon, and color. Reset to default clears the icon and color when you save; canceling leaves the saved board unchanged. For Sessions boards, the same dialog also edits column labels, colors, descriptions, column order, and the fallback column. Ask the Board agent to edit column rules. Saving only the name, icon, or color leaves the saved columns unchanged, including column edits made by another operator while the dialog was open.

For workboard.boards.upsert, omitting icon or color, passing null, or passing an empty string preserves the existing value, including for older clients. To clear appearance explicitly, send clearAppearance: ["icon", "color"], or list only the field you want to clear. Listed fields are cleared even if the request also supplies a replacement value for them. Other fields retain their ordinary update behavior. clearAppearance must be an array containing only "icon" and "color"; an empty array changes nothing. Clients using this argument need a Gateway version that supports explicit appearance clearing; older Gateways do not implement this reset.

Card lists share one prepared, claim-token-redacted snapshot per board scope and card revision. workboard.cards.list returns revision; repeat the same query with { sinceRevision: revision } for { unchanged: true, revision } when current. The revision includes the store epoch and, for scoped queries, the normalized boardId. Reconnects request a full snapshot. plugin.workboard.changed includes an event revision and a separate cardsRevision: session-fact notifications advance the event sequence without invalidating unchanged cards.

Sessions board

Use a Sessions board to see where your conversations stand without creating cards. By default, it includes sessions from all configured agents with activity in the last 72 hours and excludes archived sessions, automation (cron) sessions, system sessions, dock conversations, and each agent's home session. Subagent sessions remain included. Set scope.includeAutomation: true to include automation and system sessions, or scope.includeHome: true to include home sessions. The Board agent can set these options. Existing boards use the same defaults without a migration. Each session appears in exactly one column. Open a tile to continue its conversation; the tile also shows its agent, run state, observer headline when available, pull requests, and recent activity. Message previews are plain text: Markdown formatting and HTML are removed, link labels are retained, and whitespace is collapsed before the 400-character limit. Tiles link up to four pull requests, ordered by open, draft, merged, then closed state, with a count for any additional pull requests. The agent filter narrows the displayed sessions without changing the saved board scope.

Dock conversations stay excluded even when automation is included.

People filter: Choose Everyone (the default), Involving me, or a person beside the agent filter. Involving me shows sessions you own or previously prompted; a person selects their profile associations. The choice is remembered per viewer, device, Gateway, and board. It does not change the shared board, rules, or the Board agent. API clients can pass view: { involvingMe?: boolean, involvingProfileId?: string, includePeople?: boolean } to workboard.sessionsBoard.read; includePeople returns the people facet for the picker.

Columns are rules over Gateway-owned run state, observer health, and pull-request state. Run state comes from the live run registry and queued inputs; a saved running status without an active run is idle. Health comes from the Gateway session observer: live digests for sessions someone is watching in the Control UI, and a terminal digest when an observed run ends. Sessions nobody watches have no health, so they match only run and pull-request rules. Reads follow the current caller's session visibility; board specs and pins follow the Gateway's trusted-operator model. Interactive edits are admitted under the caller's live authority immediately before the write. Draft and incognito sessions never enter a Sessions board or its facts reads.

New Sessions boards use these columns, in this order:

Column Rule
Needs input Observer health is waiting-on-user.
Stuck Observer health is stuck or failed, or run state is failed.
Working Run is active.
In review A pull request is open or draft.
Merged A pull request is merged.
Done Observer health is done. This is also the fallback column.

Placement uses an operator pin when its column still exists, then the first matching column in saved order, then the fallback column. match accepts one rule or an any-of array such as Stuck's [{health:["stuck","failed"]},{run:["failed"]}], with every field within a rule required to match. Values within a field are alternatives. Column names and descriptions help people understand the board; match rules decide placement.

Drag a session into another column, or ask the Board agent to move it, to pin its placement. Pins remain in effect when session facts change. If a pinned column is removed, the board applies its rules again. Tile tooltips distinguish by rule and pinned.

Facts update live from session changes, with automatic board rereads at most once every five seconds. Category-only session updates and card-only changes do not reload Sessions boards. The Gateway selects the authorized roster once and reuses immutable facts for unchanged sessions. The board keeps one frozen snapshot per board and people view, replacing only rows whose facts changed. Live run state, background previews, and time-dependent subagent state remain current; profile, configuration, topology, and access changes refresh authorization. Age-window and unavailable-PR retry deadlines still refresh the snapshot. Tool callers obtain their own caller-scoped roster; sharing never expands session visibility. workboard.sessionsBoard.read returns a revision; repeat the same query with { sinceRevision: revision } for { unchanged: true, revision } when current. Reconnects and view changes request a full snapshot. The Workboard change event's sessionsRevision advances for board edits, operator pins, and session fact invalidations independently of cardsRevision.

Pull-request facts come from the Gateway's shared PR owner, independently of which sessions appear in a Control UI sidebar. Reads use prepared Gateway facts without waiting for Git or pull-request requests. Missing snapshots load through that owner's bounded background loader and announce a board change when ready. If PR facts become unavailable or GitHub rate limits requests, the Gateway's selected-facts owner retains the last ready PR list for board cards and column rules while updating run state and health. Unavailable PR reads retry per session, starting after one minute and doubling to a 15-minute maximum; a successful read resets the delay. Redaction changes omit retained PR titles until fresh source text is available, without changing known PR states or their retry schedule. An inline warning distinguishes stale PR facts from facts not loaded yet and identifies GitHub rate limiting. A failed facts read keeps the last known facts and placement; sessions with no known facts use the fallback column with reason facts-unavailable. A session whose available facts match no rule also uses that reason while its pull-request facts are unknown. Opening a board starts any needed background refresh. Shared snapshots reuse prepared facts until a publication, redaction change, board age-window expiry, or a pull-request retry becomes due; failure fallback retains the last known facts. If redaction rules change during a facts outage, the board discards retained text while keeping known run, health, and PR states.

When the Control UI host supports a session dock, Board agent opens a conversation beside the board. Its first use creates and saves a dedicated conversation named Sessions board · <board name>. This is a dock conversation: it stays out of session lists, Involving me views, and people counts. Open it from the Board agent button. Its human creator, sharing, and sandbox rules are the same as an ordinary conversation.

For boards with an older Board agent conversation, the next Board agent use creates a new dock conversation and saves its reference. The old conversation keeps its history and remains an ordinary session that you can archive; its creation surface and provenance are not rewritten.

The Board agent is the only model used by the board, invoked on demand to change columns, rules, scope, or pins using these tools:

Tool Arguments and behavior
workboard_sessions_board_read Optional boardId; returns board, columns, sessions, and any warning.
workboard_sessions_board_update Optional boardId, plus columns or scope. columns replaces the complete ordered list; retain ids when renaming labels.
workboard_sessions_board_move Optional boardId, required sessionKey and columnId; pins that session's placement.

These three tools are available to every agent once the plugin is enabled; unlike the card tools they need no tools.allow entry, so the Board agent works out of the box. Omit boardId only when exactly one Sessions board exists. The dock attaches page context to the conversation, but plugin tools do not receive that context as a structured argument. With several Sessions boards, the agent must pass the board id from that context or from workboard_boards.

Specs allow 2–12 columns with unique lowercase slug ids (1–48 characters), labels (1–60), and descriptions (1–400). Exactly one column must have fallback: true. Optional colors use the board palette. scope accepts agentIds, includeArchived, includeAutomation, includeHome, and a positive maxAgeHours. The include options default to false. Rules can match health, run (active, idle, failed), pullRequest (none, open, draft, merged, closed), and archived. Unknown pull-request state does not count as none.

The Gateway methods are workboard.sessionsBoard.read (operator.read) and workboard.sessionsBoard.update and .move (operator.write). All require boardId. Update takes a patch object with the spec fields, including the dock's agentSessionKey; move additionally requires sessionKey and columnId. Create with workboard.boards.upsert and kind: "sessions", or with workboard_board_create. Changing an existing board's kind is rejected.

Workboard stores board specs and operator pins in SQLite. Session status, observer digests, and pull-request state remain owned by the Gateway. On plugin startup, older automatic placements are removed; operator pins are preserved. Boards whose rules still match the previous defaults receive the new run-based rules; only the old default column order is reordered. Customized rules, labels, descriptions, and custom column order are preserved. Sessions boards never hold cards: card creation, capture, and dispatch reject a Sessions board destination. Deleting one removes its pins without deleting any sessions or its Board agent conversation.

Card fields

Field Values
status triage, backlog, todo, scheduled, ready, running, review, blocked, done
priority low, normal, high, urgent
labels free-form strings
agentId optional assigned agent
linked refs optional task, run, session, or source URL
execution optional metadata for a Codex/Claude run started from the card (engine, mode, model, session, run id, status)

Cards also carry compact metadata:

Metadata Values
card state attempts, comments, links, proof, artifacts, automation settings, attachments, worker logs, worker protocol state, claims, diagnostics, notifications, template id, archive state, stale-session detection
recent events created, edited, moved, linked, specified, decomposed, claimed, heartbeat, execution_updated, attempt_started, attempt_updated, comment_added, link_added, proof_added, artifact_added, attachment_added, diagnostic, notification, dispatch, orchestration, protocol_violation, archived, unarchived, stale

This metadata lets an operator see how a card moved through the board without opening the linked session. It is local operating context, not a replacement for session transcripts or GitHub issue history.

The plugin and Control UI use one Workboard card contract. Control UI refreshes therefore preserve workspace provenance and authority, claim state, diagnostic actions, and notification sequence numbers instead of projecting a smaller UI-only copy of the card. Unknown diagnostic kinds, diagnostic severities, and notification kinds are ignored until both surfaces support them. They are never rewritten into another valid state.

The open Workboard tab updates from plugin.workboard.changed invalidations. Each event contains only a store epoch and revision. The UI then rereads stored cards through the normal operator.read RPC. Multiple revisions coalesce into one follow-up read. Workboard defers that read while a card is being dragged, edited, or written, then resumes after the local interaction finishes. A reconnect always performs a reload from the store. There is no routine full-card poll, and Refresh remains available as manual recovery.

The Gateway shares one immutable workboard.cards.list payload per normalized board filter at each store revision, including concurrent reads. Card and board writes invalidate it before the next read; the existing change service also invalidates it when it observes a commit from another SQLite connection. Each response still includes all board summaries, so a change to another board invalidates the payload too. Claim tokens remain redacted, and the RPC response shape is unchanged.

When more than one board exists, the toolbar includes a Board filter backed by persisted board metadata rather than only the currently visible cards. Empty and archived boards therefore remain selectable. Cards without an explicit board id belong to the primary default board. Each board has a primary /workboard/<boardId> page that can be bookmarked, shared, or pinned in the sidebar. The previously shipped /workboard?board=<boardId> form remains a compatibility alias and redirects to that page while preserving other query parameters. Choosing All boards returns to /workboard.

A board can store an automationJobId reference to the automation job that owns its AI-categorization prompt, model, schedule, and run history. The board page shows an Automation link when that reference is present. Matching session events nudge the attached automation through the active Workboard service's scheduler authority, including after the worker's tool authority closes, with events for the same board coalesced for 60 seconds. If an attempt ends while its run is still active, the lifecycle sweep nudges the automation when it records the terminal outcome. The automation's schedule remains the backstop. Disabled and auto-disabled automations are never nudged. Deleting the board does not delete or otherwise mutate the operator-owned automation job.

Cards are stored in the plugin's own Gateway state and move with the rest of that Gateway's OpenClaw state (see Storage).

Starting work from a card

Unlinked cards without an active or unresolved task association can start work directly:

  • Run Claude / Run OpenAI starts a task-tracked agent run with an explicit engine, sends the card prompt, and marks the card running. Claude runs use anthropic/claude-sonnet-4-6. OpenAI runs use openai/gpt-6-astra.
  • Open Claude / Open OpenAI creates a linked Control UI session without sending the card prompt, for manual work that stays attached to the board. Opening it clears any schedule and moves a scheduled card to todo. Other cards keep their status.

Autonomous starts use the Gateway's task-tracked agent run path (default agent and model unless Claude/OpenAI is chosen explicitly). Workboard then links the resulting run id and session key back onto the card. Each linked execution also records an attempt summary (engine, mode, model, run id, timestamps, status, rolling failure count) so repeated failures stay visible.

The Control UI reads lifecycle from the card's linked session. Card status changes are persisted by the Gateway-side Workboard plugin using the linked run and session lifecycle (see Session lifecycle sync).

Agent tools

The card tools below are optional plugin tools. Enabling Workboard exposes only the three Sessions board tools to agents; an agent that should create, claim, or complete cards needs the card tools allowed for it. Add the plugin id to the agent's tool policy to allow every Workboard tool, or list individual tool names or a pattern such as workboard_*:

json5
{  agents: {    entries: {      main: {        tools: { alsoAllow: ["workboard"] },      },    },  },}

Without that entry the agent sees only workboard_sessions_board_* and cannot manage cards. Workers that Workboard starts from a card (Start or dispatch) do not need it: each worker run is granted workboard_heartbeat, workboard_complete, and workboard_block for its card.

Tool Purpose
workboard_list List compact cards with claim/diagnostic state; optional board filter.
workboard_read Return one card plus bounded worker context (notes, attempts, comments, links, proof, artifacts, parent results, recent assignee work, active diagnostics).
workboard_create Create a card with optional parents, tenant, skills, board, workspace metadata, idempotency key, runtime limit, retry budget.
workboard_link Link a parent to a child card. Children stay todo until every parent reaches done, then dispatch promotion moves them to ready.
workboard_claim Claim a card for the calling agent; moves backlog/todo/ready into running.
workboard_heartbeat Refresh the claim heartbeat during a longer run.
workboard_release Release the claim after completion, pause, or handoff; can move the card to a next status.
workboard_complete / workboard_block Structured lifecycle tools for final summaries, proof, artifacts, and created-card manifests (must reference cards linked back to the completed card) or blocker reasons.
workboard_attachment_add / workboard_attachment_read / workboard_attachment_delete Store small card attachments in plugin SQLite state, index on the card, expose in worker context.
workboard_worker_log / workboard_protocol_violation Record worker log lines and block a card when an automated worker stops without calling workboard_complete/workboard_block.
workboard_board_create / workboard_board_archive / workboard_board_delete Manage persisted board metadata (display name, description, archive state, default workspace).
workboard_sessions_board_read / workboard_sessions_board_update / workboard_sessions_board_move Read Sessions board placements, edit columns, rules, or scope, or pin a session in a column.
workboard_runs Return the persisted run-attempt history for a card.
workboard_specify Turn a rough triage/backlog card into a clarified todo card; records the spec summary on the card.
workboard_decompose Fan a parent orchestration card into linked children, inheriting board/tenant metadata; can complete the parent with a created-card manifest.
workboard_notify_subscribe / workboard_notify_list / workboard_notify_events / workboard_notify_advance / workboard_notify_unsubscribe Manage notification subscriptions. Event reads are replay-safe; advance moves the durable cursor so callers resume without losing or double-reading completed/failed/stale card events.
workboard_boards / workboard_stats Inspect board namespaces and queue stats.
workboard_promote / workboard_reassign / workboard_reclaim Recover or hand off stuck work.
workboard_comment / workboard_proof Add handoff notes or attach proof/artifact references.
workboard_unblock Move blocked work back to todo.
workboard_move Move a card to another status; claimed cards require the caller's agent claim scope.
workboard_dispatch Nudge dependency promotion or stale-claim cleanup without launching workers; worker launch uses Gateway or slash-command dispatch.

Proof statuses are worker-reported outcomes, not independent verification. A passed entry means the worker reports that its command or check succeeded. Consumers that need an independent quality gate should inspect the attached command, URL, or artifact and run their own verifier. workboard_proof returns the new record's proofId. When workboard_complete reports that same proof's terminal status, pass proofId so the pending record is resolved in place without losing its identity or timestamp. A proof that already has the same terminal status is reused unchanged. Completion proof without proofId remains append-only, so a later retry cannot rewrite older history merely because its command or note is identical.

Claimed cards reject agent-tool mutations from other agents unless the caller holds the claim token returned by workboard_claim. Every card returned by an agent tool or Gateway RPC call redacts metadata.claim.token to [redacted] (the token itself is returned once, top-level, only from workboard_claim), so Control UI operators and other agents can inspect claim state without ever seeing a usable token. Recovery goes through workboard_promote/workboard_reassign/workboard_reclaim, which do not require the token.

Dispatch

Dispatch is Gateway-local: it does not spawn arbitrary OS processes. Normal OpenClaw subagent sessions still own execution. One dispatch pass:

  1. Promotes dependency-ready cards.
  2. Blocks expired claims or timed-out runs.
  3. Marks board-configured triage cards as orchestration candidates.
  4. Claims a small batch of ready cards and starts worker runs through the Gateway subagent runtime.

Idle scans leave ready-card history unchanged. Existing dispatch counters and timestamps remain as historical values; new launches use the card's launch, attempt, and execution history.

Workers get bounded card context plus the claim token needed to heartbeat, complete, or block the card through the Workboard tools.

Workspace paths follow the caller's existing filesystem authority:

  • Gateway clients with operator.write can use configured agent workspaces.
  • operator.admin clients can use other host checkouts.
  • Sandboxed agent tools use their sandbox workspace access.
  • Unsandboxed workspace-only tools use their configured workspace root.

Workboard records that authority when a workspace is assigned and intersects it with the current caller's authority again at dispatch, so a persisted card cannot widen a later caller's access. Older cards with an explicit host workspace but no recorded authority must have that workspace re-saved before a full-host dispatch. Cards without a host path adopt the current caller's authority when first dispatched.

Workspace-bound dispatch accepts a directory or Git checkout only when its repository root exactly matches the target agent workspace. A worktree request is narrowed to that directory and persisted as a directory workspace, so the host does not materialize the checkout or execute repository setup code. The target worker must use a writable, non-shared Docker sandbox for that exact workspace, without elevated execution, persisted host/node exec overrides, or unclassified plugin and MCP tools. Workboard enumerates its registered tools instead of trusting a workboard_* prefix, and dispatch refuses a hot Docker container whose live mount/config hash is stale. Dispatch reports the incompatible target policy instead of starting a less-confined worker. Full-host dispatch may target other local checkouts and keeps normal managed- worktree setup.

Workspace authority does not create a second card-lifecycle permission model. Callers that may mutate Workboard cards can manually move them through the same statuses on every surface. Read-only workspace access only prevents worker dispatch that needs writes.

Worker selection

Each pass starts at most 3 workers by default. Ready cards are ordered by priority, then position, then creation time. A pass starts only one card per owner/agent and skips owners that already have running or review work on the board. Archived cards, cards with an active claim, and cards not in ready status are never selected for worker starts (they can still be affected by the data side of dispatch: stale-claim cleanup, dependency promotion, timeout cleanup).

Session keys are fixed per board/card, so repeated dispatches route back to the same worker lane instead of creating unrelated sessions:

  • Assigned cards: agent:<agentId>:subagent:workboard-<boardId>-<cardId>
  • Unassigned cards: subagent:workboard-<boardId>-<cardId> (Gateway resolves the configured default agent)

If a worker cannot be started after a card is claimed, Workboard blocks the card, clears the claim, records the run-start failure, and appends a worker log line - visible in the Control UI, CLI JSON, agent tools, and card diagnostics.

Entry points

  • Control UI dispatch action
  • openclaw workboard dispatch
  • /workboard dispatch on a command-capable channel

All three use the Gateway subagent runtime when the Gateway is available. The CLI has one operator fallback: if the Gateway call fails with a connection/unavailable error (or an unknown method error for older Gateways), and no explicit --url/--token target and no configured remote Gateway (OPENCLAW_GATEWAY_URL or gateway.mode: remote) apply, the CLI runs data-only dispatch against local SQLite state - it can promote dependencies, clean stale claims, and block timed-out runs, but cannot start workers. Auth, permission, and validation failures from a reachable Gateway are not treated as unavailable. They surface as command errors, and so does any Gateway failure when an explicit --url/--token target was given.

Board metadata can set autoDecompose, autoDecomposePerDispatch, defaultAssignee, and orchestratorProfile. OpenClaw records this intent and exposes it in worker context. Actual specification/decomposition still runs through the normal Workboard tools.

CLI and slash command

bash
openclaw workboard list [--board <id>] [--status <status>] [--include-archived] [--json]openclaw workboard create "Fix stale card lifecycle" --priority high --labels bug,workboardopenclaw workboard show <card-id> [--json]openclaw workboard move <card-id> --status <status> [--json]openclaw workboard dispatch [--board <id>] [--json]

list text output hides archived cards by default (--include-archived overrides). --json always includes archived cards, matching the full-card contract used by existing scripts. show and move accept an unambiguous id prefix. list, create, show, and move access local plugin state directly. Stop the Gateway before local create or move; while it is running, use the Control UI or Gateway RPC for mutations. Only dispatch calls the running Gateway, with the fallback described above. Data-only dispatch also requires the Gateway to be stopped; a connection error alone does not establish that it stopped. Plugin loading can also initialize or upgrade the local database before choosing the subcommand. Do that preparation with the Gateway stopped, including when the requested command is list or show. Use the Control UI or Gateway RPC for online access when local state still needs preparation.

See Workboard CLI for full flags, JSON output, Gateway fallback behavior, id-prefix handling, dispatch selection rules, and troubleshooting.

/workboard list, /workboard show <card-id>, /workboard create <title>, /workboard move <card-id> --status <status>, and /workboard dispatch mirror the CLI. List and show are read operations for any authorized command sender. Create, move, and dispatch require owner status on chat surfaces, or a Gateway client with operator.write/operator.admin. Manual operator moves use the same claim-override behavior as Control UI drag-and-drop. Their worktree access still follows the same workspace boundary described above.

Session lifecycle sync

Cards can link to an existing Control UI session, or one created when you start work from the card. Linked cards show the session lifecycle inline: running, stale, linked idle, done, or failed. You can also capture an existing session from its header or the Sessions tab with Add to Workboard. The card links to that session, uses the session label or recent user prompt as title, and seeds notes from the recent user prompt plus the latest assistant response when available.

Capture keeps the destination board selected when you start the action. It reloads an inactive board's cards before reusing one, restores an archived exact match, and never infers session ownership from a provisional link.

Captured sessions show Open Workboard card and a linked-card chip. Both use the same card state, including after a browser reload. Opening a card outside the current agent filter switches the board to All agents without changing the selected chat agent.

Opening a card loads its linked session details independently of the sidebar's agent filter and pagination. While details are loading or unavailable, the card keeps its link and shows Session state unknown or Session unavailable. An ambiguous provisional link shows Session link ambiguous. Edit the card to select an exact session. Use Refresh to retry. To continue an existing session, select its exact link in Edit card and choose Open session. To start fresh, clear the link in Edit card. Clearing the link retains its task association, so Start remains unavailable while that task is active or unresolved. Changing a card's assignee does not change the owner of its existing session.

Bare global and unknown links do not identify a session owner. They show Session link ambiguous when opened. Use Edit card to select an explicit session. Workboard does not offer these bare links for new captures or links.

If an active linked session stops reporting recent activity, Workboard marks the card stale and stores that as metadata until the lifecycle clears it.

Lifecycle writes are owned by the Gateway-side Workboard plugin, so they do not depend on an open browser tab. Subagent completion hooks persist terminal outcomes immediately. Agent attempt hooks consult the linked session state: finishing a model attempt does not move a card into review or blocked while its run is still active. A bounded session sweep runs once per minute to reconcile terminal, active, idle, missing, and stale session state. Each store mutation emits the normal plugin.workboard.changed invalidation, so an open Workboard tab reloads the stored card instead of writing its own lifecycle projection.

Incognito sessions remain absent from session discovery. Explicitly linked Incognito cards use authorized exact-session metadata reads, without derived titles or message previews, to reconcile their terminal outcomes.

While a card is in an active work state, Workboard follows the linked session:

Linked session state Card status
active running
completed review
failed, killed, timed out, or aborted blocked

Manual review states win. Moving a card to review, blocked, or done stops auto-sync for that card until you move it back to todo or running.

Starting a card uses normal Gateway sessions. Workboard only stores card metadata and links. Conversation transcript, model selection, and run lifecycle stay owned by the regular session system. Use Stop on a live linked card to abort the active run - Workboard marks that card blocked so it stays visible for follow-up.

New cards can start from Workboard templates (bugfix, docs, release, pr_review, plugin). Templates prefill title, notes, labels, and priority. The template id is stored as card metadata.

Control UI workflow

  1. Open the Workboard tab in the Control UI.
  2. Create a card with a title, notes, priority, labels, optional agent, and optional linked session - or open Sessions and choose Add to Workboard for an existing session.
  3. Drag the card between columns, or focus its compact status control and use the menu or ArrowLeft/ArrowRight. During a drag, the source card dims and available drop columns gain an outline.
  4. Start an unlinked card when it has no active or unresolved task association.
  5. Open the linked session from the card while the agent works.
  6. Let lifecycle sync move running work into review/blocked, then manually move the card to done when accepted.

Session-board widgets

Workboard ships three native widgets for session dashboards (see Dashboards). The agent pins them with its dashboard tool using content: { kind: "plugin", pluginKind, props }, and they render as first-party UI with live data — no sandbox frame or capability grant:

  • workboard:card with props: { cardId } shows one card with its status control, priority, and assigned agent.
  • workboard:board with optional props: { boardId } shows the full Kanban board with draggable cards and status controls. Without boardId it shows every board. With boardId it shows only that board.
  • workboard:mini with optional props: { boardId, limit } shows per-status counts plus the top ready/running cards, and links to the full board page. Without boardId it aggregates every board. With boardId it scopes to that board (cards created without an explicit board id live on default).

Diagnostics

Diagnostics are computed from local card metadata. Built-in checks flag:

Kind Condition
stranded_ready Assigned todo/backlog/ready card not updated in over 1 hour.
running_without_heartbeat running card with no claim heartbeat or execution update in over 20 minutes.
blocked_too_long blocked card not updated in over 24 hours.
repeated_failures Card's tracked failure count reaches 2 or more.
missing_proof done card with no proof, artifacts, or attachments.
orphaned_session running card with a sessionKey but no execution metadata.
archived_but_active Archived card remains in any non-done lifecycle status.

Permissions

Gateway RPC methods live under workboard.*. Sessions board methods use the same read/write scopes as boards:

Scope Methods
operator.read cards.list, cards.export, cards.diagnostics, attachment list/get, notification event reads, boards.list, cards.stats, cards.runs
operator.read sessionsBoard.read
operator.write cards.diagnostics.refresh, create/captureSession/update/move/delete/comment/link/linkDependency/proof/artifact, attachment add/delete, worker log, protocol violation, claim/heartbeat/release/promote/reassign/reclaim/complete/block/unblock/start, cards.dispatch, cards.bulk, archive, boards.upsert/archive/delete, cards.specify/decompose, notification subscribe/delete/advance
operator.write sessionsBoard.update, sessionsBoard.move

workboard.cards.update, workboard.cards.move, workboard.cards.archive, and workboard.cards.delete accept an optional expectedUpdatedAt request field. Pass the finite numeric updatedAt from the card you read to guard the write. If the card has changed, the request fails with workboard_conflict and returns its latest card in error.details.card (error.details.type is workboard_card_conflict). Review that card before retrying. Omitting the field keeps the method's existing unguarded request behavior.

Control UI bulk actions use each card's observed revision and stop on a conflict. Remaining cards stay selected for review and retry; the batch does not silently retry against newer revisions or overwrite another client's changes.

No RPC method requires operator.admin. Browsers connected with read-only operator access can inspect the board but cannot mutate cards. An admin scope widens accepted Workboard host paths. It does not change the methods available.

Storage

Workboard stores durable data in a plugin-owned relational SQLite database under the OpenClaw state directory: boards, cards, labels, lifecycle events, run attempts, comments, dependency links, proof, artifact references, attachment metadata and blobs, diagnostics, notifications, worker logs, protocol state, and subscriptions all live in Workboard tables (not plugin key-value entries). A card export preserves the board narrative without inlining attachment blob contents.

Sessions boards add optional kind and sessions_spec columns to workboard_boards, plus workboard_session_placements for operator pins. Existing board rows are not backfilled; an absent kind still means a Cards board. Rolling back to a release without Sessions boards shows each Sessions board as an empty Cards board and ignores the placement table; cards created against it there are rejected once the newer release runs again. Session transcripts and the Board agent conversation remain in the normal session store.

SQLite opening, queries, and transactions run in a background database worker. Disabling or reloading the plugin drains admitted storage work before closing its connections.

Workboard instances invalidate cached card lists and board revisions using the physical database's in-process writer receipts, including commits through sibling instances. Card-list reuse checks that receipt; an unsettled receipt leaves the read uncached. A read overlapping a mutation can return its older snapshot; the next request observes the writer receipt and reloads it. Change notifications use owner publications; there is no timer polling SQLite for writes from other processes. If a worker reply fails after a possible commit, the owner discards cached facts and rereads them on the next use without replaying the mutation.

Installations with retained pre-July 2026 Workboard plugin-state KV data must upgrade through OpenClaw 2026.9.7 and run openclaw doctor --fix before upgrading to the latest version. Current Doctor reports this requirement without changing the legacy rows; current relational SQLite stores remain supported.

Troubleshooting

The tab says Workboard is unavailable

bash
openclaw plugins inspect workboard --runtime --json

If plugins.allow is configured, add workboard to it. If plugins.deny contains workboard, remove it before enabling the plugin.

Cards do not save

Confirm the browser connection has operator.write access. Read-only operator sessions can list cards but cannot create, edit, move, or delete them.

Starting a card does not open the expected session

Check the card's agent id and linked session, then open Sessions or Chat to inspect the actual run state.

Dispatch does not start a worker

Confirm there is at least one ready card without an active claim:

bash
openclaw workboard list --status ready

If the CLI reports data-only dispatch, start or restart the Gateway and retry - data-only dispatch updates local board state but cannot start subagent worker runs. Cards can also be skipped when another card for the same owner or agent is already running or waiting for review. Complete, block, or release that active work before dispatching more for the same owner.

Was this useful?