Agentic Board

    Drop a live agent Kanban board into your app. Agents pick up cards, work them live with a streaming execution view, and advance lanes automatically — no polling glue code required.

    Install

    bash
    npm install @cadraos/sdk

    Full example

    A self-contained page that creates the adapter from environment variables and renders a live board. Cards show their agent execution stream automatically — keyed on card.executionId.

    AgentBoardPage.tsx
    import { useMemo } from 'react';
    import {
      KanbanBoard,
      createDefaultKanbanAdapter,
    } from '@cadraos/sdk/kanban';
    
    export default function AgentBoardPage() {
      const adapter = useMemo(
        () =>
          createDefaultKanbanAdapter({
            baseUrl: import.meta.env.VITE_CADRA_API_URL as string,
            apiKey: import.meta.env.VITE_CADRA_API_KEY as string,
            orgId: Number(import.meta.env.VITE_CADRA_ORG_ID),
          }),
        [],
      );
    
      return (
        <div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
          <KanbanBoard
            adapter={adapter}
            pollIntervalMs={10000}
            enableCreate
            enableEdit
            enableAdvance
            onCreateCard={async () => {
              const title = window.prompt('Card title');
              if (!title) return null;
              return { title, type: 'generate_campaign_plan' };
            }}
            onRetryCard={(card) => {
              adapter.transitionCard({ id: card.id, targetLane: 'handler' });
            }}
            onError={(message) => {
              console.error('[KanbanBoard]', message);
            }}
          />
        </div>
      );
    }

    Environment variables

    Prefer a short-lived token or tokenProvider in the browser over a raw apiKey. The adapter accepts all three — swap apiKey for tokenProvider: async () => (await fetch("/api/token")).json().then(r => r.token) when you have a server-side token endpoint.

    .env
    # Vite
    VITE_CADRA_API_URL=https://your-instance.cadraos.com
    VITE_CADRA_ORG_ID=123
    VITE_CADRA_API_KEY=sk-cad-xxxxxxxxxxxx
    
    # Next.js (public)
    NEXT_PUBLIC_CADRA_API_URL=https://your-instance.cadraos.com
    NEXT_PUBLIC_CADRA_ORG_ID=123
    # Keep the raw API key server-side only — use a /api/token route in the browser

    Host-owned data (AgentBoard)

    For multi-tenant deployments where your backend owns the card data, use AgentBoard with a BoardConfigClient and a custom AgentBoardCardSource. The source interface gives you full control over every read and write — the board component stays purely presentational.

    HostOwnedBoard.tsx
    import { useMemo } from 'react';
    import {
      AgentBoard,
      AgentBoardCardSource,
      BoardConfigClient,
    } from '@cadraos/sdk/kanban';
    
    // Implement the card source against your own API
    const myCardSource: AgentBoardCardSource = {
      async listCards(boardConfigUuid, input) {
        const res = await fetch(`/api/boards/${boardConfigUuid}/cards`, {
          method: 'POST',
          body: JSON.stringify(input ?? {}),
        });
        return res.json();
      },
      async getCard(cardId) {
        const res = await fetch(`/api/cards/${cardId}`);
        return res.json();
      },
      async createCard(boardConfigUuid, input) {
        const res = await fetch(`/api/boards/${boardConfigUuid}/cards`, {
          method: 'POST',
          body: JSON.stringify(input),
        });
        return res.json();
      },
      async updateCard(cardId, patch) {
        const res = await fetch(`/api/cards/${cardId}`, {
          method: 'PATCH',
          body: JSON.stringify(patch),
        });
        return res.json();
      },
      async transitionCard(input) {
        const res = await fetch(`/api/cards/${input.id}/transition`, {
          method: 'POST',
          body: JSON.stringify(input),
        });
        return res.json();
      },
      // Optional: stream live execution output for a card
      async createRunStream(executionId) {
        return new EventSource(`/api/executions/${executionId}/stream`);
      },
    };
    
    export default function HostOwnedBoardPage() {
      const configClient = useMemo(
        () =>
          new BoardConfigClient({
            http: {
              baseUrl: import.meta.env.VITE_CADRA_API_URL as string,
              apiKey: import.meta.env.VITE_CADRA_API_KEY as string,
            },
          }),
        [],
      );
    
      return (
        <AgentBoard
          configClient={configClient}
          boardConfigUuid={import.meta.env.VITE_BOARD_CONFIG_UUID as string}
          cardSource={myCardSource}
        />
      );
    }

    Next steps

    Read the full /docs/guides/kanban-boards guide for lane configuration, card type schemas, agent assignment, and permission rules. The complete prop reference is at /docs/api/kanban.