SWIRLS_

Swirls Docs

Define, run, and deploy AI-powered workflows.

Swirls is a workflow engine for AI applications. Define workflows in .swirls files, run them locally or in the cloud.

A complete workflow in one file

This workflow accepts a contact form submission, summarizes it with an LLM, and sends a confirmation email.

form contact_form {
  label: "Contact Form"
  enabled: true
  schema: @json {
    {
      "type": "object",
      "required": ["name", "email", "message"],
      "properties": {
        "name": { "type": "string", "title": "Name" },
        "email": { "type": "string", "title": "Email" },
        "message": { "type": "string", "title": "Message" }
      }
    }
  }
}

graph process_form {
  label: "Process Form"

  root {
    type: code
    label: "Normalize"
    code: @ts {
      const { name, email, message } = context.nodes.root.input
      return { name: name.trim(), email: email.toLowerCase(), message: message.trim() }
    }
  }

  node summarize {
    type: ai
    label: "Summarize"
    model: "google/gemini-2.5-flash"
    kind: object
    schema: @json {
      { "type": "object", "required": ["text"], "properties": { "text": { "type": "string" } } }
    }
    prompt: @ts {
      const { name, email, message } = context.nodes.root.output
      return `Summarize in one sentence:\n\nFrom: ${name} <${email}>\n\n${message}`
    }
  }

  node notify {
    type: email
    label: "Send confirmation"
    to: @ts { return context.nodes.root.output.email }
    subject: @ts { return "We received your message" }
    text: @ts {
      return `Thanks for reaching out. Summary: ${context.nodes.summarize.output.text}`
    }
  }

  flow {
    root -> summarize
    summarize -> notify
  }
}

trigger on_contact {
  form:contact_form -> process_form
  enabled: true
}

Get running in 5 minutes

What you get

  • .swirls files: declarative, versionable workflow definitions with full editor support
  • AI-native nodes: ai, code, http, email, switch, stream, and more
  • Type-safe TypeScript blocks with LSP-powered IntelliSense
  • Triggers: connect forms, webhooks, and schedules to graphs
  • Streams: persist and query graph outputs with SQL
  • Human-in-the-loop: pause workflows at any node for review and approval
  • Local execution: run graphs on your machine with the CLI
  • Cloud deployment: managed infrastructure, no ops required

When to use Swirls

  • AI content pipelines: draft, review, and publish content with LLM nodes and human review gates
  • Lead enrichment and scoring: enrich form submissions via HTTP, score with an LLM, route to CRM
  • Support ticket triage: classify urgency with a switch node, draft responses with an LLM
  • Automated reporting: schedule graphs to query data streams and deliver formatted summaries
  • Form-driven workflows: collect structured input, process it with AI, notify via email or webhook

Quick reference

Code node: run TypeScript, read upstream outputs via context.nodes.

node normalize {
  type: code
  label: "Normalize email"
  code: @ts {
    const { email } = context.nodes.root.input
    return { email: email.trim().toLowerCase() }
  }
}

AI node: prompt an LLM and get a typed response.

node classify {
  type: ai
  label: "Classify intent"
  model: "google/gemini-2.5-flash"
  kind: object
  schema: @json {
    { "type": "object", "required": ["intent"], "properties": { "intent": { "type": "string" } } }
  }
  prompt: @ts {
    return `Classify the intent of: ${context.nodes.root.input.message}`
  }
}

Switch node: route execution based on a TypeScript expression.

node route {
  type: switch
  label: "Route by urgency"
  cases: ["urgent", "normal", "low"]
  router: @ts {
    const body = context.nodes.root.output.body.toLowerCase()
    if (body.includes("urgent")) return "urgent"
    if (body.length > 500) return "normal"
    return "low"
  }
}

flow {
  root -> route
  route -["urgent"]-> handle_urgent
  route -["normal"]-> handle_normal
  route -["low"]-> handle_low
}

Next steps

  • Quickstart: get a workflow running in 5 minutes
  • Language: learn the .swirls file format
  • Platform: run locally or deploy to the cloud

On this page