Kanban API

    Components, hooks, adapters, and types for the SDK's Kanban module. All symbols import from @cadraos/sdk/kanban except client.kanban, which is a resource on CadraClient from @cadraos/sdk.

    client.kanban

    Low-level REST methods exposed on every CadraClient instance. Use these directly when you need full control, or let the higher-level components call them for you.

    MethodSignatureDescription
    getBoard() => Promise<KanbanBoard>Auto-provisions the org board on first call
    listCards(input?: ListCardsInput) => Promise<CardList>Optional lane / type / limit / offset filters
    createCard(input: CreateCardInput) => Promise<KanbanCard>Never auto-retried on network failure
    getCard(cardId: string) => Promise<KanbanCard>cardId is the integer PK as a string, NOT the execution UUID
    updateCard(cardId: string, patch: { title?; description?; sharedContext? }) => Promise<KanbanCard>Partial patch — omitted fields are left unchanged
    transitionCard(input: TransitionCardInput) => Promise<KanbanCard>Manual lane move; validates against allowed transitions
    getCardRun(executionId: string) => Promise<AgentExecution>Poll fallback; use streamCardRun for live updates
    streamCardRun(executionId: string) => ExecutionStreamControllerAttach .on() listeners then call .connect()
    typescript
    const board  = await client.kanban.getBoard();
    const cards  = await client.kanban.listCards({ lane: 'review', limit: 20 });
    const card   = await client.kanban.createCard({ title: 'Q4 report', lane: 'todo' });
    
    const stream = client.kanban.streamCardRun(card.executionId!);
    stream.on('textDelta', ({ delta }) => process.stdout.write(delta));
    stream.on('complete', ({ execution }) => console.log(execution.status));
    await stream.connect();

    KanbanBoard

    Full-featured board component. Requires a KanbanAdapter and renders lanes, cards, and a run-stream drawer. For agent-config-driven boards see AgentBoard.

    PropTypeDescription
    adapterKanbanAdapter (required)Data-access layer; use createDefaultKanbanAdapter or supply your own
    onCreateCard(lane: KanbanLane) => CreateCardInput | null | undefinedReturn input to create, or null/undefined to cancel
    onRetryCard(card: KanbanCard) => voidCalled when the user clicks Retry on a failed card
    onError(message: string) => voidSurface adapter or transition errors in your own UI
    onCardCreated(card: KanbanCard) => voidFires after the card is persisted and visible in the board
    enableCreateboolean (default true)Show the "New card" button in each lane header
    enableEditboolean (default true)Allow editing card title / description from the drawer
    enableAdvanceboolean (default true)Show Approve / Advance button for human-gate lanes
    pollIntervalMsnumberBackground poll interval for cards without an active stream
    classNamestringCSS class applied to the board root element

    AgentBoard

    Extends KanbanBoard with agent-config-driven lane/transition resolution. Fetches board configuration via BoardConfigClient and derives the card source from the resolved config. All KanbanBoardProps (except adapter) pass through.

    PropTypeDescription
    configClientBoardConfigClient (required)Resolves board config by UUID; see BoardConfigClient section
    boardConfigUuidstring (required)UUID of the board configuration to load
    versionnumberPin to a specific config version; defaults to the active version
    cardSourceAgentBoardCardSource (required)Defines how cards are fetched for this board's data domain

    CardDrawer

    Slide-over drawer that shows card detail, the live agent run stream, and transition controls. Used internally by KanbanBoard but can be mounted standalone when you manage selection state yourself.

    PropTypeDescription
    cardKanbanCard | null (required)Card to display; null closes the drawer
    adapterKanbanAdapter (required)Used to stream the card's agent run
    onClose() => voidCalled when the drawer requests to be dismissed
    onRetry(card: KanbanCard) => voidCalled when the user clicks Retry on a failed run
    onUpdate(cardId: string, patch: { title?; description?; sharedContext? }) => void | Promise<void>Persist card edits; awaited before optimistic state is committed
    onAdvance(cardId: string) => void | Promise<void>Called when the Approve / Advance button is clicked
    canAdvanceboolean (default true)Controls visibility of the Advance button
    transitionsKanbanTransition[]Override allowed transitions shown in the move menu
    lanesKanbanLane[]All lanes — used to resolve lane labels in the drawer
    onTransition(cardId: string, toLane: string) => void | Promise<void>Called when a manual lane move is confirmed
    onRunTerminal(status: 'completed' | 'failed') => voidFires when the streamed run reaches a terminal state; trigger a board refresh here
    onError(message: string) => voidStream or transition error handler
    classNamestringCSS class applied to the drawer panel

    useKanbanBoard

    Core hook that powers KanbanBoard. Use it directly when you need custom board UI while keeping the SDK's state management.

    UseKanbanBoardOptions

    PropTypeDescription
    adapterKanbanAdapter (required)Data-access layer for all board operations
    autoLoadboolean (default true)Fetch board + cards on mount; set false to defer
    onError(message: string) => voidCalled on any adapter error
    onCardCreated(card: KanbanCard) => voidFires after a card is created and added to local state
    onTransition(card: KanbanCard, toLane: string) => voidFires after a successful lane transition
    pollIntervalMsnumberBackground poll interval in milliseconds

    UseKanbanBoardResult

    PropertyTypeDescription
    boardKanbanBoard | nullRaw board record; null until first load completes
    lanesKanbanLane[]Ordered lane definitions for the board
    cardsKanbanCard[]All cards, flat — use cardsByLane for column rendering
    cardsByLaneRecord<string, KanbanCard[]>Cards keyed by lane slug; ready for column rendering
    selectedCardKanbanCard | nullCurrently open card (drives CardDrawer open state)
    isLoadingbooleanTrue during initial board + card fetch
    errorstring | nullLast error message, or null when healthy
    refresh() => voidFull reload; shows loading state
    silentRefresh() => voidReload without toggling isLoading (post-run sync)
    openCard(cardId: string) => voidSet selectedCard by card ID
    closeCard() => voidClear selectedCard
    createCard(input: CreateCardInput) => Promise<KanbanCard>Create and optimistically insert into cards state
    updateCard(cardId: string, patch: { title?; description?; sharedContext? }) => Promise<void>Persist patch and update local state on success
    transitionCard(input: TransitionCardInput) => Promise<void>Move card to a new lane and update local state
    handleRunTerminal(status: 'completed' | 'failed') => voidPass to CardDrawer's onRunTerminal; triggers silentRefresh

    createDefaultKanbanAdapter

    Factory that builds a KanbanAdapter backed by the Cadra REST API. Pass either a pre-configured CadraClient or the raw connection fields — not both.

    typescript
    import { createDefaultKanbanAdapter } from '@cadraos/sdk/kanban';
    
    // Option A — reuse an existing CadraClient
    const adapter = createDefaultKanbanAdapter({ client });
    
    // Option B — supply connection fields directly
    const adapter = createDefaultKanbanAdapter({
      baseUrl: 'https://api.cadraos.com',
      tokenProvider: async () => await getSessionToken(),
      orgId: 42,
    });

    DefaultKanbanAdapterConfig

    FieldTypeDescription
    clientCadraClientPre-configured client; takes precedence over the fields below
    baseUrlstringCadra API base URL (e.g. https://api.cadraos.com)
    apiKeystringStatic API key for server-side usage
    tokenstringStatic bearer token (not refreshed)
    tokenProvider() => Promise<string>Async token getter; called before each request
    orgIdnumberOrganisation ID scoping all board operations

    KanbanAdapter

    Interface you implement to connect the board to a custom backend. Return the same shapes as the default REST adapter — the components and hook only care about this contract.

    MethodSignatureDescription
    getBoard() => Promise<KanbanBoard>Fetch or provision the board
    listCards(input?: ListCardsInput) => Promise<CardList>Return cards, honouring any filter input
    createCard(input: CreateCardInput) => Promise<KanbanCard>Persist a new card and return it
    getCard(cardId: string) => Promise<KanbanCard>Fetch a single card by integer PK string
    updateCard(cardId: string, patch: { title?; description?; sharedContext? }) => Promise<KanbanCard>Apply a partial patch and return the updated card
    transitionCard(input: TransitionCardInput) => Promise<KanbanCard>Move card to new lane; validate transitions server-side
    createRunStream(executionId: string) => ExecutionStreamControllerOptional. If absent the drawer falls back to polling via getCardRun

    BoardConfigClient

    Resolves and caches board configurations by UUID. Used by AgentBoard but also useful when you need to inspect config details before rendering.

    MethodSignatureDescription
    getActive(uuid: string) => Promise<ResolvedBoardConfig>Fetch the currently active (published) version of a board config
    getPinned(uuid: string, version: number) => Promise<ResolvedBoardConfig>Fetch a specific version; useful for canary / A-B rollouts
    clearCache() => voidEvict all cached resolutions; call after a config publish

    Types

    Illustrative shapes for the consumer-facing types. Full definitions — including every optional field — ship with the package .d.ts.

    typescript
    // @cadraos/sdk/kanban — key consumer types
    
    interface KanbanCard {
      id: string;              // integer PK serialised as string (use for getCard, updateCard)
      executionId?: string;    // agent run UUID (use for streamCardRun / getCardRun)
      currentLane: string;     // slug of the lane this card is currently in
      title: string;
      description?: string;
      type?: string;           // card type tag (e.g. "task", "approval")
      sharedContext?: Record<string, unknown>; // arbitrary metadata passed to the agent
      // run summary fields populated after the agent run completes
      // ...
    }
    
    interface KanbanLane {
      id: string;
      slug: string;
      label: string;
      order: number;
      // ...
    }
    
    interface KanbanTransition {
      fromLane: string;
      toLane: string;
      label?: string;
      requiresApproval?: boolean;
      // ...
    }
    
    interface CreateCardInput {
      title: string;
      lane?: string;           // defaults to the board's entry lane
      description?: string;
      type?: string;
      sharedContext?: Record<string, unknown>;
      // ...
    }
    
    interface TransitionCardInput {
      cardId: string;
      toLane: string;
      reason?: string;
      // ...
    }
    
    interface ListCardsInput {
      lane?: string;
      type?: string;
      limit?: number;
      offset?: number;
      // ...
    }