Skip to content

Your first workflow

Duckflux is a declarative, YAML-based DSL for orchestrating workflows. You describe what should happen and in what order — the runtime handles execution. No SDK required, no boilerplate, no vendor lock-in.

A workflow is just a YAML file. The only required field is flow.


flow:
- type: exec
run: echo "Hello, duckflux!"

That’s it. One step, one command. Save it as hello.flow.yaml and it’s ready to run.


Here’s a workflow that fetches some data, processes it, and sends the result to an HTTP endpoint:

id: data-pipeline
name: Data Pipeline
participants:
fetch:
type: exec
run: curl -s https://api.example.com/data
process:
type: exec
run: ./process.sh
input: fetch.output
notify:
type: http
url: https://hooks.example.com/result
method: POST
body: process.output
onError: skip
flow:
- fetch
- process
- notify

participants — named, reusable step definitions. Each participant has a type that determines how it runs:

TypeWhat it does
execRuns a shell command
httpMakes an HTTP request
mcpCalls an MCP server tool
workflowRuns another workflow file
emitPublishes an event

flow — the execution sequence, top to bottom. Each step completes before the next begins.

input — explicit input mapping. fetch.output is a CEL expression that reads the output of the fetch step. By default, outputs also chain implicitly to the next step — like Unix pipes.

onError: skip — if notify fails, the workflow continues instead of stopping. The default is fail.


Workflows can accept parameters:

id: deploy
name: Deploy
inputs:
env:
type: string
required: true
branch:
type: string
default: "main"
participants:
deploy:
type: exec
run: ./deploy.sh
input:
env: workflow.inputs.env
branch: workflow.inputs.branch
flow:
- deploy

Inputs are accessed in CEL expressions as workflow.inputs.<field>.


Duckflux doesn’t enforce a naming convention, but <name>.flow.yaml is the common pattern:

deploy.flow.yaml
review-loop.flow.yaml
ci.flow.yaml

The .flow.yaml double extension makes workflows easy to find with a single glob (**/*.flow.yaml).