Guides
Quickstart
Documentation

Waiflo reference

Everything you need to define, version, and execute multi-step AI workflows. Plain JSON, REST API, zero vendor lock-in.

Top-level schema

A Waiflo file is a plain JSON document with three top-level keys. It is designed to be committed to Git, reviewed in a pull request, and deployed as any other artifact.

{
  "lang_name":  "my_pipeline",      // unique identifier for this pipeline
  "steps":      [ ... ],             // reusable step definitions
  "workflows":  [ ... ]              // DAGs that wire steps together
}
FieldTypeDescription
lang_namestringUnique name for the pipeline. Used as the file name on disk. required
stepsStep[]Array of step definitions. Each step is an atomic, reusable unit. required
workflowsWorkflow[]Array of workflow definitions (DAGs). Each workflow wires steps into an execution graph. optional

Steps

A step is the atomic unit of a pipeline. It has a type, typed I/O schemas, and its full configuration in one object — no hidden state, no magic inheritance.

Common fields

FieldTypeDescription
ws_namestringUnique identifier within the file. Used to reference the step in workflows. required
ws_typestringOne of: prompt · api · transform · tool · script required
ws_inputs_schemaJSONSchemaJSON Schema object describing expected inputs. optional
ws_output_schemaJSONSchemaJSON Schema object describing the expected output. optional

Step types

prompt
LLM call. System prompt, {{var}} template substitution, typed output schema. Streams via SSE.
ws_llm
ws_system_prompt
ws_prompt_template
ws_output_schema
api
HTTP call. URL and body support {{input}} substitution. Returns parsed JSON or raw text.
ws_api.method
ws_api.url
ws_api.headers
ws_api.body
transform
Data reshape between steps. Filter, compute, or derive fields from upstream outputs.
ws_transform_fn
— coming soon
tool
MCP tool call (Google Maps, Asana, Gmail…) via ws_tools array.
ws_tools: [
  "maps_search"
]
script
Custom code execution in a sandboxed runtime with bound inputs.
ws_script
— coming soon

prompt — LLM fields

The ws_llm object configures which model to call. ws_prompt_template supports Mustache triple-stache {{{var}}} for raw injection and {{var}} for HTML-escaped values.

FieldTypeDescription
ws_llm.providerstringLLM provider. Currently: anthropic.
ws_llm.modelstringModel ID e.g. claude-sonnet-4-20250514.
ws_llm.temperaturenumber0–1. Defaults to 0. optional
ws_system_promptstringSystem prompt string. Injected before the user turn.
ws_prompt_templatestringUser turn template. Supports {{input_var}} and {{ws_output_schema}} substitutions.
{
  "ws_name":             "classify",
  "ws_type":             "prompt",
  "ws_llm":              { "provider": "anthropic", "model": "claude-sonnet-4-20250514", "temperature": 0 },
  "ws_system_prompt":    "You are a classifier. Reply with JSON only.",
  "ws_prompt_template":  "Classify: \nSchema: ",
  "ws_inputs_schema":    { "required": ["input_text"] },
  "ws_output_schema":    { "properties": { "label": { "type": "string" } } }
}

api — HTTP fields

URL and body templates support {{input_var}} substitution resolved from inputs at runtime.

FieldTypeDescription
ws_api.methodstringHTTP method: GET · POST · PUT · PATCH · DELETE.
ws_api.urlstringURL string. Supports {{input_var}} template substitution.
ws_api.headersobjectStatic or templated headers object. optional
ws_api.bodyobjectRequest body. Object or string. optional

Workflows

A workflow is a named directed acyclic graph (DAG) of step references. The runtime resolves execution order from depends_on declarations.

FieldTypeDescription
wf_namestringUnique workflow name. required
wf_nodesNode[]Ordered array of node objects, each referencing a step by step_id. required

Node fields

FieldTypeDescription
step_idstringReferences a ws_name defined in the steps array.
depends_onstring[]Array of step_id values that must complete before this node runs. Data passed downstream comes explicitly from ws_output_schema fields (no implicit aliases). optional
{
  "wf_name":  "triage_and_respond",
  "wf_nodes": [
    { "step_id": "classify_ticket" },
    { "step_id": "enrich_customer",  "depends_on": ["classify_ticket"] },
    { "step_id": "draft_response",    "depends_on": ["classify_ticket", "enrich_customer"] }
  ]
}

OpenAPI schema

Download the full Waiflo API OpenAPI YAML schema and import it into Postman, Insomnia, or your internal tooling.

GET /json_schemas/waiflo_api.openapi.yaml

Download waiflo_api.openapi.yaml

Execute API

The exec API runs a single step with provided inputs. No account required for guest use if ANTHROPIC_API_KEY is set in the server environment. Authenticated users bring their own encrypted API key.

POST /api/exec/step
Execute a step definition with inputs. For prompt steps returns SSE stream. For api steps returns JSON.
// Request body
{
  "step":   { ... },   // full step definition object
  "inputs": { ... }    // key-value map of inputs
}

// Response
// prompt step → SSE stream
data: {"type":"delta","text":"..."}
data: {"type":"final","output":{"label":"billing"}}

// api step → JSON
{ "output": { "status": 200, "body": { ... } } }

Auth API

JWT-based authentication. Tokens are valid for 7 days. Pass the token in the Authorization header for all authenticated endpoints.

POST /api/auth/register
Create a new account. Password must be at least 8 characters.
{ "email": "you@example.com", "password": "min8chars" }
// → { "token": "eyJ..." }
POST /api/auth/login
Obtain a JWT token for an existing account.
{ "email": "you@example.com", "password": "..." }
// → { "token": "eyJ..." }

Include the JWT token in all requests that require authentication.

Authorization: Bearer <token>

Design API

CRUD endpoints for managing workflow files on the server. PATCH endpoints use recursive deep merge — only the fields you send are updated. Built for autosave and AI-assisted pipeline builders.

GET /api/workflows
List all workflows for the authenticated user.
POST /api/workflows
Create a new workflow. Body is the full Waiflo JSON document.
PATCH /api/workflow/design/step
Patch a single step field. Uses recursive deep merge — unspecified fields are preserved.
{
  "workflow_name": "triage",
  "ws_name":       "classify",
  "patch":         { "ws_llm": { "temperature": 0.4 } }
}

Only ws_llm.temperature is changed. ws_llm.provider and ws_llm.model are preserved automatically.

Quickstart

Self-host with Docker. Zero external services — just a JWT secret and your Anthropic key.

1
Clone and configure
Two secrets to generate: one for JWT signing, one for API key encryption at rest.
git clone https://github.com/jpdesmontils/waiflo
cd waiflo && cp .env.example .env
# Set JWT_SECRET and MASTER_SECRET in .env
2
Start the server
Spins up the API and visual editor. Persists workflow files to a mounted volume — no database required.
docker compose up -d
# Editor available at http://localhost:3001/editor
3
Open the editor or call the API
Explore the visual editor without an account. Or register and start pushing workflows programmatically.
# Try the editor first — no account needed
open http://localhost:3001/editor

# Or go API-first
curl -X POST http://localhost:3001/api/auth/register \
  -d '{"email":"you@example.com","password":"secret"}'