Skip to main content
A workflow is the logic that a tool runs or a play executes per row. You author it in TypeScript with defineWorkflow from @cargo-ai/cdk (re-exported from @cargo-ai/workflow-sdk). Workflows authored in code and workflows drawn on the canvas compile to the same artifact and run identically — the code DSL is just a different authoring surface.

Define a workflow

  • input / output are Zod schemas — they become the workflow’s form fields and end variables.
  • uses declares the tools, agents, and connectors this workflow calls (see below).
  • The body is parsed, not executed. The SDK reads the function’s source and lowers it to workflow nodes; it never runs at build time. That’s why the body can’t be async and why only a subset of JavaScript is supported (see below) — anything that must run at runtime goes in a js() block.

Reference tools, agents, and connectors

Everything a workflow calls that isn’t a native action — a tool, an agent, or a connector — is declared once in the header’s uses map and called by key in the body. Keeping the reference in the header (not inline in the body) lets the deploy order the dependency and inject the real uuid.
  • Tools and agents are called directly — uses.<key>(input).
  • Connectors expose their actions — uses.<key>.<action>(input). Action names and their input/output are typed from the integration’s schema (run cargo-ai cdk types). The type comes from the integration slug, not the uuid — so the connector’s uuid can be a handle for a resource that doesn’t exist yet.
  • Pass a defineTool / defineAgent / defineConnector handle directly, or use toolRef / agentRef / connectorRef(uuid, slug) for a resource referenced by literal uuid.

What you can express in code

Supported statements: const / let (single identifier), if / else if / else, for…of, and return. Not supported: async/await, try/catch, throw, closures, nested function declarations, and destructuring assignments.

Built-in actions

ai() — inline AI value

Ask an LLM for a single value anywhere an expression fits:

js() — runtime JavaScript

Escape hatch for logic the parser can’t lower — the function you pass does run at runtime, as a script node, with access to upstream node outputs:
Use js() for transformations, parsing, and computation; keep orchestration (branches, loops, action calls) in the DSL where it compiles to inspectable nodes. python(...) is the same idea in Python.

humanReview() — human-in-the-loop gate

Posts a Slack message with Approve / Decline buttons and blocks the run until a reviewer clicks one (or the timeout fires — timeouts auto-decline):

memory.* — key-value state

Persist state across runs without a model. Each call is one node and returns { result }:
  • scope: "workflow" (default) is private to this workflow; "workspace" is shared across all workflows.
  • set, getOrSet, increment, and decrement require expiresIn ({ value, unit } with second / minute / hour / day).
  • increment / decrement are atomic counters — the safe way to rate-limit or cap sends.

split() and balance() — traffic shaping

Route bodies must be inline zero-argument arrows.

The action catalog

Cargo ships 120+ actions across enrichment, CRM, AI, communication, and logic. Three ways to browse what’s callable:
  • In code, cargo-ai cdk types writes the registry into .cargo-ai/, so a connector declared in uses (uses.<key>.<action>) autocompletes real action slugs and config shapes in your editor.
  • In the UI, the same catalog is the node palette in the tool editor — searchable by category, with per-field documentation inline.
  • Per integration, each page in the Integrations tab documents its actions, parameters, and credit costs.

Code covers a subset of the canvas

The code DSL is designed for linear and branching tool/play logic. It does not yet mirror the entire visual node palette. These are canvas-only today — build them in the tool editor if you need them:
  • Filter, Delay, and Variables nodes
  • Model actions — search, insert, update, upsert, remove, custom column
  • File search and Model ask standalone AI nodes
  • Allocate (lead routing)
Because both paths compile to the same node format, you can start a workflow in code and finish complex, canvas-only parts in the UI, or vice versa. But the CDK never reads UI edits back into your files — once you finish a workflow in the UI, re-deploying a changed code definition overwrites the canvas work. See Code and UI round-trips before mixing the two on one resource.

Retry and failure options

Every connector, tool, and agent call accepts a second options argument:

Deploying workflow changes

A workflow is deployed as part of the tool or play that owns it (cargo-ai cdk deploy). You can also push a Workflow SDK module to an existing workflow directly: