.md

Workflows

Workflow templates describe an automation as a node graph — triggers wired to steps — stored as JSON. This page walks the dev loop: scaffold a template, validate it, test it against a development runner, then deploy it to production with a hot-swap so live traffic isn't interrupted.

For CI/CD pipeline automation, see CI/CD integration.

Note

Before you start. Workflow commands (except a local workflow validate) talk to the dcupl cloud, so they need project credentials — configure them once with dcupl config set (see Cloud Sync). A runner is the managed environment in the cloud that executes a deployed workflow. You deploy and test against a runner — list them with dcupl workflow runners list. The list also shows app-runners; only runners of type workflow-runner run workflows. The dev and prod runners on this page are example runner keys: nothing marks a runner as dev or prod. --runner takes a runner's uid or its runnerKey.

Watch out

Runtime budgets are enforced at execution time. The defaults are 10s total per workflow, 5s per request node, and 500ms per script node (your project's plan can set other values). A node that exceeds its budget is terminated.

The dev loop

You edit a *.workflow-v3.json file locally, exercise it against a runner, and deploy it with a hot-swap.

01
Scaffoldfrom a schema example
02
Editwire triggers + steps
03
Validatelocal or against a runner
04dev
Testdeploy + exercise
05prod
Deployhot-swap, no downtime
zsh — workflow dev loop

scaffold from the example shape — no guessing: dcupl schemas get TemplateV3 --example --json | jq -r '.example' > my.workflow-v3.json

the agent / you edit my.workflow-v3.json, then validate: dcupl workflow validate --file my.workflow-v3.json --local-only — output: ✓ valid (0 warning(s))

find an available dev runner: dcupl workflow runners list --json | jq -c '.[]' — output: {"uid":"<dev-uid>","runnerKey":"dev","type":"workflow-runner","url":"<runner-url>","health":"ok"} {"uid":"<prod-uid>","runnerKey":"prod","type":"workflow-runner","url":"<runner-url>","health":"ok"} {"uid":"<app-uid>","runnerKey":"apps","type":"app-runner","url":"<runner-url>","health":"ok"}

test on the dev runner; input.json holds the request body, e.g. {"orderId":"123"}: dcupl workflow test --file my.workflow-v3.json --runner <dev-uid> --input input.json — output: Execution <executionId> — workflow <projectId>-import-products • trigger [ok, 1ms] → 1 item(s) • fetch [ok, 412ms] → 1 item(s) • map [ok, 3ms] → 1 item(s) • respond [ok, 2ms] → 1 item(s)

deploy to prod — waits for the hot-swap: dcupl workflow deploy --file my.workflow-v3.json --runner <prod-uid> --yes — output: ✓ deployed <projectId>-import-products (uid <uid>, v <hash>) — live ✓

1 · Scaffold & edit

Start from the example shape rather than a blank file, then wire up triggers and steps within the runtime budgets above. See Schemas for more on schemas get. Take the example field of the --json output: without --json, the command prints the schema's TypeScript source before the example, and the file is not valid JSON.

dcupl schemas get TemplateV3 --example --json | jq -r '.example' > my.workflow-v3.json

Or scaffold a complete read-transform-write template with dcupl generate workflow --name <key>. In a workspace (it needs dcupl.config.json) it writes <key>.workflow-v3.json to workflows/ in your baseFolder (default dcupl/), which dcupl files push syncs; the file passes workflow validate --local-only as written. Set its dcuplFilesApiKey variable before you deploy it. See Scaffolding.

2 · Validate

Validate locally or against a runner's environment.

# Validate locally, no runner needed
dcupl workflow validate --file my.workflow-v3.json --local-only

# Validate against a specific runner's environment
dcupl workflow validate --file my.workflow-v3.json --runner <uid>

3 · Find your runners

List them to pick a workflow runner to test on and one to deploy to.

dcupl workflow runners list        # columns: uid, runnerKey, type, url, health
dcupl workflow runners get --id <uid>

4 · Test on a dev runner

This deploys the template to the runner, then exercises it. A full run (without --node) needs a trigger-request node, or it stops with NO_REQUEST_TRIGGER: it calls that trigger with the first of its methods and the --input file as the body (not for GET), and prints the node-by-node trace. A trigger with auth needs no extra key: dcupl sends the trigger's own API key. When a node fails, the command prints the trace and exits 1 with WORKFLOW_RUN_ERROR. The schema example fetches https://api.example.com/products (the apiUrl variable), so point apiUrl at a real endpoint before you test it.

# --input takes a path to a JSON file (the request body), not inline JSON
echo '{"orderId":"123"}' > input.json

dcupl workflow test \
  --file my.workflow-v3.json \
  --runner <dev-uid> \
  --input input.json
--node <id>Exercise a single node instead of a full run
--input <path>JSON file: the request body for a full run, or the inputData for --node
--state <path>JSON file: $state seed for --node
--wait / --no-waitWait for the hot-swap before triggering (default on)
--swap-timeout <ms>How long to wait for the swap (default 30000)
Watch out

The test deploy is real.workflow test performs the same deploy as workflow deploy, just without its confirmation prompt (dcupl still validates the template before it deploys it): the template replaces whatever that runner serves under the same key, and it stays deployed after the run. Point --runner at a runner nothing depends on. The output doesn't print the deployed workflow's uid; to remove the test deployment, look it up with dcupl workflow list and run dcupl workflow undeploy --id <uid> --yes.

5 · Deploy to a prod runner

Deploy waits for the hot-swap to complete by default. Remove a deployed workflow with dcupl workflow undeploy --id <uid> --yes.

dcupl workflow deploy \
  --file my.workflow-v3.json \
  --runner <prod-uid> \
  --yes
Flag Default Purpose
--yes—Skip the confirmation prompt
--waittrueWait for the hot-swap before returning
--no-wait—Return immediately, don't wait for the swap
--swap-timeout <ms>30000How long to wait for the swap

Inspecting workflows

Once a workflow is deployed, these commands help you check its state and debug runs. To debug a failed run, find it in the history, then trace it node by node.

Command What it shows
dcupl workflow listAll workflows
dcupl workflow get --id <uid>A workflow's details
dcupl workflow template --id <uid>Deployed template — drift check vs. the runner
dcupl workflow status --id <uid>Live status
dcupl workflow history --id <uid>Past runs (executionId, status, startedAt, durationMs, error)
dcupl workflow trace --id <uid> --run <executionId> | --lastNode-by-node state for a run
dcupl workflow run <key> --runner <uid> [--body <json> | --input <path>]Trigger an already-deployed workflow without redeploying (--node for one node)
# Find the run
dcupl workflow history --id <uid>
# => executionId  status  startedAt  durationMs  error

# Inspect node-by-node state
dcupl workflow trace --id <uid> --run <executionId>

# or trace the most recent run
dcupl workflow trace --id <uid> --last

workflow template is useful for catching drift — if the template on the runner no longer matches your local file, redeploy.