# FlashBoards SDK 0.1 — Experimental

One experimental 0.1.x product line, not SDK generations 1–4. `formatVersion`, `sdkVersion` and `request.version` are compatibility markers: keep discovered values unchanged, never substitute 0.1. Discover capabilities, not version-based assumptions.

Use packages for reusable behavior; use existing direct actions for one-off edits. When advertised, format-3 tools provide named actions and optional panels. Format-2 panels use events, including hidden invocation, not independent action authoring. Format-1 alignment toolbars are separate.

## Connect and discover

External agents: follow [MCP connection](https://flashboards.yaroflasher.com/help/mcp), then `list_skills` → `get_skill` with `skillId:"flashboards-sdk"`; [API help](https://flashboards.yaroflasher.com/help/api.md) defines its envelope. The AI-SDK sidebar has these skill tools. The Hermes-backed sidebar receives this guide in server instructions, without native `get_skill`. Reading, connection or package sharing grants no board authority.

Discover `{"operation":"describe"}` through `extensionsRequest`, then one relevant section at a time. `tool-installations` exposes version-4 installation requests. Live schemas, limits, availability, consent and receipts override prose. Version-2 panels and version-3 tools address the separate legacy slot; inspect before intentional `put` replacement.

## Send through the actual transport

- Local AI-SDK sidebar: in Agent mode, call `requestBoardAction` with `action:"extensionsRequest"` and `args` equal to the `ExtensionOperation` object, for example `{"action":"extensionsRequest","args":{"operation":"describe"}}`.
- Hermes-backed sidebar: use its existing `flashboards-actions` fenced action-plan envelope with an action named `extensionsRequest` whose `args` are exactly the operation. Use only action names the server currently advertises; do not claim a native skill tool or browser access.
- MCP: choose a live tab with `list_board_sessions`, read `get_board_snapshot`, then call `execute_board_action` with `action:"extensionsRequest"`, `args` equal to the operation, the current outer `expectedBoardId`, and `sessionId` when needed. This is a live local-board browser bridge, not headless server execution against an arbitrary board.
- Public API: use the same `execute_board_action` operation through the API envelope, with the current `expectedBoardId` and any needed `sessionId`. Read its response `result` and inner receipt; transport `ok` alone is insufficient.

Wait for the sidebar browser result; a proposal is not an applied edit. Headless behavior still needs an open, hydrated, authorized local-board tab. Pilot/admin-tester access and human **Settings → Plugins** consent gate writes/invocation. If unavailable, report why and ask for the human Settings/connection step; never synthesize consent, change roles or bypass admission. Guests have declared bounded capabilities, no arbitrary DOM, network, filesystem, shell or paid generation. Direct actions keep their own contracts.

## Author and verify

### Custom tools, only when advertised

Discover `{operation:"describe",section:"tool-artifact"}` before authoring a tool, then `section:"tool-steps"` for read/effect steps and `section:"tool-context"` for its separately bounded context schema. The format-3 manifest uses `kind:"custom-tool"`, `sdkVersion:2`, an ID/name, `stateVersion`, capabilities, 1–16 declared actions and function-body strings in `program.init` and `program.action`. The action receives `(state,invocation,context)`, where invocation contains `actionId`, primitive-object `args` and an initially null `response`. Return `{state,read:{kind:"board.items",offset,limit,expectedRevision?}}` for a page or `{state,effects:[],result?}` for a terminal result. A terminal effect instead uses `{state,effects:[effect]}` without a result. Reads resume in fresh realms; only JSON state survives, and private state commits at an authorized terminal step.

`board.items.read` returns up to 32 ID/kind/label/selection/geometry summaries, never note bodies or media URLs. Continue from `nextOffset` with `expectedRevision`. `selection.replace` and `viewport.focus` require declared capabilities and captured selection or latest-page IDs. `notes.read` exposes the captured selected note or an unavailable reason; `notes.write` requires it and edits only that note through `note.update` (title, content, fontSize, textColor, backgroundColor; 2 KiB body, 256-byte title). Changes use normal Undo and pending persistence. Tool capabilities do not inherit event-panel capabilities. At most eight reads and two seconds per invocation; 2 KiB args/result and 16 KiB state/step.

`board.layout` requires `selection.geometry` and one `layout` effect with 1–32 unique `{id,left,top}` positions for the exact captured selection. Other, stale or paged IDs cannot expand authority. Host layout uses normal Undo; changed edits report pending persistence, no-ops unchanged. `changedIds` lists directly positioned items.

`prompts.read` pages this browser's Recent (20 prepared attempts) and Saved with `prompts.page/text`; `promptCollections.read` pages collections and snapshot text. Omit `collectionId` for collection summaries; with one, use `part:"groups"` or `part:"entries"` for separate bounded pages. Entries include group names. Follow returned `nextOffset` because encoded-size limits can shorten a page. Recent is not complete server or account history. `promptCollections.write` changes names, groups and entries; `promptCollections.add` also needs `prompts.read` to copy full source text in the host. Pin continuations and effects to the library revision. Collection writes report `persistence:"saved"` in the tool and outer panel receipts; collections outlive tool removal and stay out of package export.

`promptCollections.export` prepares one/all JSON; a person downloads from the panel header or Plugins Settings, even for a headless tool. Guests get no file or URL access. Import this [portable example](../../../lib/extensions/promptCollectionsTool.example.json) in Settings; it exceeds the agent install limit.

For an installed tool, discover `section:"tool-installations"` and use `operation:"panel"`, `request.version:4`. `install` needs artifact JSON and `enabled`; it returns installation ID and entry revision. `list` uses registry revision for continuation. `get` returns metadata and a context token only when enabled and authorized. `invokeAction` uses installation ID, entry revision, token, action ID and args. `update`/`enable`/`remove` use entry CAS. `present` selects one optional panel; null hides it without uninstalling. Up to eight IDs may be installed. Definitions survive board switches, while private state/context reset. Agent execution needs human Plugins consent. Inspect uncertain receipts before retry.

Version-3 `get|put|describe|invokeAction` retains legacy single-slot replacement, not version-4 targeting. Its `put` limit is 8 KiB. Event-based panels and legacy named-action tools share that slot, separate from the installed-tool roster.

Optional `panel` contains floating placement, CSS and `render`/`reduce` bodies. Reduce returns `{state}` or `{state,call:{actionId,args}}`, using the same action runner, not event-based panel effects. The installed-tool editor is pinned to its target and revision; export downloads its current editor bytes. An imported file transfers neither consent nor usable context. Private state is transient, not durable board data or exported state. General document mutations, public observation/lifecycle and media/model/generation access are not part of this slice. If this version is unavailable, do not emulate it through private application state.

### Existing event-based panels

Format-2 panels use `program.init/render/reduce` function-body strings. `init` returns state, `render` HTML, and `reduce` returns `{state,effects}` or a bounded `result` with no effects. Discover the event schema; `notes.read` does not grant `notes.write`.

For a panel action, obtain a fresh token through `operation:"panel",request:{version:2,action:"describe"}`, then invoke with `request:{version:2,action:"invoke",contextToken,event}`. The token is single use and bound to captured local-board authority. Inspect the full receipt.

Panel `put` validates and renders before installation. Its Hide control removes presentation, not installed behavior. Format-2 panels have no separate activation; format-1 toolbars keep their own draft and human activation rules.

Preserve full mutation receipts. `applied`/`pending` is not durable saving; unknown outcomes require inspection, never automatic replay. Verify board state and save status. Package export/sharing transfers bytes, not consent, ownership or invocation permission.
