Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Flow schema

ScaiFlow flows conform to JSON Schema draft 2020-12 at https://scailabs.com/schemas/scaiflow/v2.json.

The schema is hand-mirrored in three places (all kept in lockstep — CI fails if they drift):

  • JSON Schemapackages/flow-schema/schema/v2.json — the canonical reference.
  • Pydanticpackages/flow-schema/python/scaiflow_schema/models.py — server-side validation.
  • TypeScriptpackages/flow-schema/typescript/src/index.ts — canvas + client typing.

Top-level shape#

jsonc
{
  "$schema": "https://scailabs.com/schemas/scaiflow/v2.json",
  "id": "flow_<random>",                  // required, opaque string
  "name": "Untitled Flow",                // required
  "version": "1.0.0",                     // required, semver
  "scaicore_target": "0.2",               // ScaiCore language version
  "metadata": { /* see below */ },
  "nodes": [ /* see Node */ ],
  "edges": [ /* see Edge */ ],
  "variables": [],                        // flow-level state slots
  "config": { /* see FlowConfig */ },
  "tests": []                             // optional test fixtures
}

metadata#

jsonc
{
  "author": "alice@acme.example",
  "created": "2026-04-01T...",            // ISO-8601
  "description": "What this flow does."
}

All fields optional.

Node#

jsonc
{
  "id": "node_<random>",                  // required
  "type": "llm_flexible",                 // required, NodeKind enum
  "label": "Classify Intent",             // required
  "position": { "x": 400, "y": 200 },     // required
  "config": {},                           // per-kind shape; see Node kinds
  "inputs": [ /* Port[] */ ],
  "outputs": [ /* Port[] */ ]
}

NodeKind enum (closed)#

text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
entry_api, entry_webhook, entry_schedule,
llm_rigid, llm_guarded, llm_flexible,
logic_decision, logic_loop, logic_parallel,
tool_plugin, tool_http,
data_variable_set,
checkpoint,
queue_publish, queue_consume,
hitl_review, hitl_decision, queue_escalation,
compute_provision, compute_exec, compute_file_upload, compute_file_download, compute_destroy,
subflow_call

See Node kinds reference for the per-kind config shape.

Port#

jsonc
{ "id": "in_message",
  "label": "message",
  "type": "string" }

type is free-form ScaiCore type syntax: string, int, float, bool, object, enum, or a user-declared type name.

Edge#

jsonc
{
  "id": "edge_<random>",                  // required
  "type": "sequential",                   // required, EdgeKind enum
  "source": { "node": "node_a", "port": "out" },     // required
  "target": { "node": "node_b", "port": "in" },      // required
  "condition": "confidence > 0.7"        // required when type === "conditional"
}

EdgeKind enum: sequential, conditional, data.

Variable#

jsonc
{ "name": "intent",
  "type": "string",
  "default": null }

name and type required. Flow-level state slots — currently advisory (the compiler emits them; runtime enforcement TBD).

FlowConfig#

jsonc
{
  "core_identity": { /* required */
    "name": "My Core",
    "description": "Optional",
    "models": [ /* ModelDecl[] — minItems: 1 */ ]
  },
  "plugins": [],                          // string[]; plugin names this flow uses
  "capabilities": [],                     // string[] OR object[]; capability flags + structured bunker block
  "bunker": { /* optional BunkerCapability */ },
  "scaiqueue": { /* optional ScaiQueueConfig */ },
  "hitl_mode": "explicit_publish",        // legacy, deprecated; M3 uses single @checkpoint with hitl_target
  "publish_as_model": false,
  "model_visibility_group_ids": []
}

ModelDecl#

jsonc
{
  "role": "primary",                      // ^[a-z][a-z0-9_]*$, unique within models[]
  "ref": "scaigrid",                      // provider key
  "model": "openai/gpt-4o",               // model identifier
  "temperature": 0.5,                     // 0.0–2.0, optional
  "modalities": ["text", "structured_output"],     // default ["text"]
  "system_context": "...",                // optional
  "fallback": [                           // optional
    { "ref": "openai", "model": "gpt-3.5-turbo" }
  ]
}

First entry is the implicit primary default for any LLM node that doesn't specify llm_role.

ScaiQueueConfig#

jsonc
{
  "scope": "support",                     // required, slug
  "queues": [
    {
      "slug": "review",                   // required
      "display_name": "Review queue",
      "description": "Where reviews go",
      "consumer_mode": "fifo",            // fifo | priority | deadline | broadcast
      "max_retries": 5,                   // 0–100
      "purpose": "review"                 // intake | processing | review | escalation | completed | dead-letter | custom
    }
  ]
}

Queue/HITL nodes that omit scope inherit from flow.config.scaiqueue.scope at compile time.

BunkerCapability#

jsonc
{
  "lifecycle": "ephemeral",               // ephemeral | session | persistent | appliance
  "image": "python-3.12",                 // required
  "cpu_millicores": 1000,                 // 100–64000, default 1000
  "memory_mb": 1024,                      // 128–131072, default 1024
  "disk_mb": 2048,                        // 512–524288, default 2048
  "gpu_count": 0,                         // 0–8
  "gpu_type": "...",                      // optional
  "network_profile": "registry",          // isolated | registry | allowlisted | unrestricted | transit
  "network_allowlist": ["*.example.com"]  // used when network_profile=allowlisted
}

TestCase#

jsonc
{
  "name": "Refund request",               // required
  "description": "Optional",
  "input": { "message": "I want a refund" },     // required
  "expect": { "intent": "complaint" },           // optional shallow == match
  "expect_expressions": []                       // optional free-form assertions
}

Strictness#

  • additionalProperties: false at most levels — unknown keys are rejected on save.
  • $schema at the top level is allowed (editor pointer convention).
  • Pydantic + JSON Schema + TypeScript are kept in lockstep by packages/flow-schema/python/tests/test_models.py — drift fails CI.

Validation#

bash
1
scaiflow validate my-flow.flow.json

Or via the REST API: POST /v1/flows/validate — see Preview router.

Updated 2026-05-18 16:05:21 View source (.md) rev 3