Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kapso.ai/llms.txt

Use this file to discover all available pages before exploring further.

Use the Kapso CLI to keep workflows and functions in a local repository. You can edit the generated definition.json directly, or use @kapso/workflows to author the workflow in JavaScript or TypeScript. The Platform API stores workflow definitions as JSON with snake_case config keys. The JavaScript library uses idiomatic camelCase inputs and compiles them to the same JSON shape before kapso push.

Start a local repo

# 1. Create a local workspace
mkdir kapso-workflows
cd kapso-workflows

# 2. Install the Kapso CLI and workflow library
npm init -y
npm install -g @kapso/cli
npm install --save-dev @kapso/workflows

# 3. Link this directory to your Kapso project
kapso login
kapso link --project <project-id>
kapso pull

# 4. Install Kapso agent skills
npx skills add gokapso/agent-skills
kapso link binds the current directory to one Kapso project. kapso pull downloads source files for workflows and functions.

Repository layout

After pulling, the repo includes project binding metadata and one directory per source object.
kapso.yaml
.kapso/project.json
.kapso/remote-map.json

functions/
  send-slack-message/
    function.yaml
    index.js

workflows/
  support-router/
    workflow.yaml
    definition.json
    workflow.js
Commit the files you want to version. Keep .kapso/remote-map.json in shared repos because it stores the last pulled remote state for dirty-file and stale-update checks.

Choose JSON or code

Both paths are supported:
  • Edit definition.json when you want the exact Platform API graph payload.
  • Edit workflow.js or workflow.ts when you want a boring code API for constructing the graph.
  • Keep or ignore generated definition.json as a team decision. The CLI works either way.
kapso pull creates workflow.js next to definition.json when no workflow source file exists. After you edit that source file, future pulls preserve it and update only the remote-owned JSON/YAML files.

Build with code

import { START, Workflow } from "@kapso/workflows";

const workflow = new Workflow("support-router", {
  name: "Support Router",
  status: "draft"
});

workflow.addTrigger({
  type: "inbound_message",
  phoneNumberId: "<phone-number-id>"
});

workflow.addNode(START, {
  position: { x: 100, y: 100 }
});

workflow.addNode("intro", {
  type: "send_text",
  message: "Hi {{vars.customer_name}}, how can we help?"
}, {
  position: { x: 360, y: 100 }
});

workflow.addNode("wait_reply", {
  type: "wait_for_response",
  saveResponseTo: "latest_reply",
  timeoutSeconds: 300
}, {
  position: { x: 620, y: 100 }
});

workflow.addNode("classify", {
  type: "decide",
  decisionType: "ai",
  providerModel: "gpt-5-mini",
  conditions: [
    { label: "billing", description: "Billing, invoices, or payments" },
    { label: "technical", description: "Product or technical support" }
  ]
}, {
  position: { x: 880, y: 100 }
});

workflow.addEdge(START, "intro");
workflow.addEdge("intro", "wait_reply");
workflow.addEdge("wait_reply", "classify");

export default workflow;
Build the workflow JSON before pushing:
kapso build
If a pulled workflow.js file is unchanged, kapso push uses workflow.yaml and definition.json. Once you edit workflow.js or add workflow.ts, kapso push compiles that source before uploading.

Push changes

Preview changes before writing to Kapso:
kapso push --dry-run
Push one workflow:
kapso push workflow support-router
Push one function:
kapso push function send-slack-message
Push everything in the local repo:
kapso push
Workflows and functions are matched by slug. If a remote object with the same slug exists but your repo does not have a pull baseline, run kapso pull first.

Node reference

Each node has a stable id, a type, and optional display/position options. Edges reference node IDs.
workflow.addNode("node_id", { type: "send_text", message: "Hello" });
workflow.addEdge("node_id", "next_node");
The table below shows the library shape and the Platform API node_type.
NodeAPI node_typeLibrary config
Startstartworkflow.addNode(START, { position })
Send textsend_text{ type: "send_text", message, phoneNumberId?, toPhoneNumber?, delaySeconds?, providerModel?, aiFields? }
Send templatesend_template{ type: "send_template", templateId, parameters?, phoneNumberId?, toPhoneNumber?, providerModel?, aiFields? }
Send interactivesend_interactive{ type: "send_interactive", interactiveType, bodyText?, buttons?, listSections?, ctaUrl?, flowId?, phoneNumberId?, toPhoneNumber? }
Wait for responsewait_for_response{ type: "wait_for_response", saveResponseTo?, timeoutSeconds? }
Decidedecide{ type: "decide", decisionType: "ai" / "function", conditions, providerModel? } or { functionSlug } for function decisions
Functionfunction{ type: "function", functionSlug, saveResponseTo? }
Webhookwebhook{ type: "webhook", url, method?, headers?, bodyTemplate?, saveResponseTo?, providerModel?, aiFields? }
App actionpipedream{ type: "pipedream", appSlug, actionId, accountId?, configuredProps?, saveResponseTo? }
Agentagent{ type: "agent", systemPrompt, providerModel?, functionTools?, webhooks?, mcpServers?, resources? }
Call workflowcall{ type: "call", workflowSlug, saveErrorTo? }
Handoffhandoff{ type: "handoff", reason?, contextData? }
Set variableset_variable{ type: "set_variable", variableName, variableValue, valueType? }
Rawany{ type: "raw", nodeType, config } for fields not yet modeled by the library
Use rawConfig on typed nodes when you need an extra Platform API field that the library has not modeled yet:
workflow.addNode("send", {
  type: "send_text",
  message: "Hello",
  rawConfig: {
    experimental_field: true
  }
});

References by slug

Local source should use stable slugs where possible:
  • Function nodes use functionSlug.
  • Function decision nodes use functionSlug.
  • Agent function tools use functionSlug.
  • Call workflow nodes use workflowSlug.
During kapso push, the CLI resolves those slugs to remote IDs before calling the Platform API. Direct Platform API requests should use function_id and workflow_id.

API definition shape

A workflow definition is a graph:
{
  "nodes": [
    {
      "id": "start",
      "type": "flow-node",
      "position": { "x": 100, "y": 100 },
      "data": {
        "node_type": "start",
        "config": {},
        "display_name": "Start"
      }
    }
  ],
  "edges": []
}
When using the Platform API directly:
  • Use snake_case config keys.
  • Use GET /workflows/{workflow_id}/definition to read the expanded graph.
  • Use PATCH /workflows/{workflow_id} to update metadata and graph collections.
  • Include the latest lock_version to avoid overwriting remote changes.
  • The update response returns workflow metadata, not the expanded definition. Refetch the definition when you need the saved graph.
Example update:
curl -X PATCH "https://api.kapso.ai/platform/v1/workflows/<workflow-id>" \
  -H "X-API-Key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow": {
      "lock_version": 3,
      "definition": {
        "nodes": [
          {
            "id": "start",
            "type": "flow-node",
            "position": { "x": 100, "y": 100 },
            "data": { "node_type": "start", "config": {} }
          },
          {
            "id": "intro",
            "type": "flow-node",
            "position": { "x": 360, "y": 100 },
            "data": {
              "node_type": "send_text",
              "config": {
                "message": "Hi {{vars.customer_name}}",
                "phone_number_id": "<phone-number-id>"
              }
            }
          }
        ],
        "edges": [
          { "source": "start", "target": "intro", "label": "next" }
        ]
      }
    }
  }'
Inside definition, nodes and edges are replacement sets when present. If you send only one node in definition.nodes, every other node is removed. Omit definition.nodes or definition.edges when you want that collection to remain unchanged.

Sync behavior

The CLI protects local and remote work during sync:
  • kapso pull refuses to overwrite dirty local remote-owned files.
  • kapso pull --diff shows blocked incoming diffs without writing files.
  • kapso pull --overwrite replaces local edits in remote-owned files with the remote version.
  • kapso pull preserves authored workflow.js and workflow.ts files.
  • kapso push checks the last pulled remote version before updating existing objects.
  • Remote-only workflows and functions are reported, not deleted.
  • Local-only workflows and functions are created on push.

Build with AI

The setup block above installs the Kapso agent skills. For AI-assisted edits, point your coding assistant at the workflow directory and ask it to edit workflow.js or workflow.ts. Kapso docs are available to AI tools through the MCP endpoint:
https://docs.kapso.ai/mcp