---
title: "POST /v1/ai/workflow/chat/stream"
method: POST
path: "/v1/ai/workflow/chat/stream"
---

# POST /v1/ai/workflow/chat/stream

`POST /v1/ai/workflow/chat/stream`

Issue a caddie-v3 chat session (Socket.IO). Returns sessionToken + socketUrl.

## Request body

- union
  - object
  - ChatParams
    - `agentVersion` 'v1' | 'v2' | 'v3' | 'both' — Optional - agent version toggle; "v3" routes to the caddie service (open to every org)
    - `apiKeyOverride` string — Optional - override the LLM API key for this request (eval/testing use only)
    - `conversationId` string — Stable conversation identifier (generated client-side, persists across session→workflow transition)
    - `definition` WorkflowDefinition — Definition is the inline workflow graph to analyze. Same shape as a saved workflow's definition. Unlike the ephemeral-run endpoint there is no trigger restriction — analysis is read-only and method-agnostic.
      - `blockExpansions` object — Set on run snapshots only (not workflow DB)
      - `inputSchema` WorkflowInput[]
        - `description` string
        - `key` string
        - `required` boolean
        - `type` string — "string", "number", "boolean", "object", "array"
      - `nodes` object, required
      - `sensitivePropKeys` string[] — Legacy: kept for old runs; no longer populated for new workflows
      - `triggerNodeIds` string[] — TriggerNodeIDs lists the node IDs that are trigger (root) nodes. Every workflow declares this — single-trigger workflows ship ["root"] (the legacy node id), multi-trigger workflows list every trigger node id. Treating single-trigger as a forest-of-1 removes the two-path branching throughout the BE + FE; older rows without the field are backfilled by migration 000282 and the field-missing path stays as a read-side safety net (see FindTriggerNodeIDs) but is no longer exercised by saves. "root" is also a runtime alias for "the trigger that fired this run" — {{root.X}} variable references resolve to the firing trigger regardless of which trigger fired. Don't repurpose the literal "root" as a trigger id on a multi-trigger workflow.
      - `variableDefs` VariableDef[] — VariableDefs is a snapshot of the workflow's declared variables at run creation time. The canonical source lives on the workflows row (Workflow.VariableDefs column). Snapshotted into the run definition so the worker can resolve {{$vars.x}} lookups and route variable-action writes to the right scope without an extra DB round trip.
        - `default` unknown
        - `description` string
        - `lifetime` 'persist' | 'reset'
        - `name` string
        - `type` 'number' | 'text' | 'boolean' | 'list' | 'object'
    - `description` string — Optional - for generating new workflow
    - `enabledDeepAgents` string[] — Optional - per-conversation allowlist of deep agents Caddie may delegate to. Pointer distinguishes absent (nil) from present ([]: none / [a,b]: only those). This is only ever NARROWING: the signed claim is the org's setting INTERSECTED with this (v1/ai.narrowDeepAgents), so sending an agent the org disabled does not enable it. The web chat currently omits it.
    - `images` ChatImageAttachment[] — Optional - images attached to the message (base64 for LLM, IPFS for storage)
      - `base64` string
      - `ipfsUrl` string
    - `lastEventIndex` integer — Last received event index for replay (reconnection)
    - `message` string — Optional on reconnect, required for new sessions
    - `modelOverride` string — Optional - override the LLM model for this request (eval/testing use only)
    - `name` string — Optional - for generating new workflow
    - `preferredMode` 'planning' | 'building' | 'repair' | 'conversation' — Optional - user's preferred mode hint; overrides auto-classifier when set
    - `requestId` string — Client-generated UUID4 for persistent session tracking (optional for legacy/inline mode)
    - `sessionId` string — Optional - metadata: which create-page session started this conversation
    - `temperatureOverride` number — Optional - override the LLM temperature for this request (eval/testing use only)
    - `templateSearchMode` 'lightweight' | 'hybrid' — Optional - template search mode toggle (defaults to lightweight)
    - `timezone` string — Optional - user's IANA timezone (e.g. "America/New_York") for time-aware responses
    - `workflowId` string — Optional - metadata: which workflow this conversation is about

## Response `200`

sessionToken + socketUrl for the caddie-v3 Socket.IO connection

- object

## Other responses

- `400` — Bad Request

---

[API](https://skmtc.dev/b3os/apis/b3os-workflow-api.md) · [All operations](https://skmtc.dev/b3os/apis/b3os-workflow-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/b3os/b3os-workflow-api/revisions/a8c7af3c66a1/schema)
