Skip to content

Your First Flow

A flow is a YAML file under flows/{name}.flow.yaml in the configured Storage.Directory. The simplest useful one echoes its input back, which makes it perfect for verifying run paths end-to-end.

The filename is the identity. flows/hello.flow.yaml is the flow named hello. Sub-folders are organisation only and never become part of the name — flows/billing/invoice-sync.flow.yaml is still just invoice-sync. There is no name: field inside the file; declaring one is an error.

Save this as flows/hello.flow.yaml:

Terminal window
status: active
input:
message: !str Hello from Zenvara
output:
echo: !str
message: !str
steps:
- return:
echo: "Parameters received successfully"
message: "${message}"

The platform picks the file up on the next request — no restart needed.

These show up everywhere:

  • Typed input and output. !str, !int, !bool, !obj, !str-list and friends declare a real signature. The value after the tag is the default; omit the value to make the field required.
  • ${message} references a payload key. Each step’s output is merged back into the payload, so later steps reference earlier steps the same way.
  • return: ends the flow and produces the typed output contract. Anything you produce that is not declared in output: is dropped.

The fastest check is a POST to the flow’s run endpoint. live is the branch alias that resolves to production on Git-disabled installs:

Terminal window
curl -X POST http://localhost:5000/api/v1/live/flows/hello/runs \
-H "Content-Type: application/json" \
-d '{"message":"Hi there"}'

Flows run asynchronously by default, so this hands you back a run id rather than the result — plain text, not JSON:

Terminal window
Flow hello Started with Id 019f9b1b-a0e5-7051-a9d7-0e4b39097926

That id is how you read the logs and the output afterwards; see Running Flows.

To block until the flow finishes and get its typed output back, use the synchronous endpoint with wait: true. Note the body keys are lowercase:

Terminal window
curl -X POST http://localhost:5000/api/v1/live/cicd/run-flow \
-H "Content-Type: application/json" \
-d '{"name":"hello","parameters":{"message":"Hi there"},"wait":true}'
Terminal window
{
"runId": "019f9b2e-0bae-7f5f-a78c-455f99322522",
"status": "Completed",
"output": "{\"echo\":\"Parameters received successfully\",\"message\":\"Hi there\"}"
}

output carries the declared output contract, JSON-encoded as a string. status is one of Started, Completed, Failed or Timeout.

There are three equivalent ways to run a flow — from a human, a script, or an AI agent. See Running Flows for all three.

  • Add a real connector. Try http.get to fetch a URL or filesystem.read to load a file. See the Connector Catalog.
  • Wire up an environment. Flows run against an environment that bundles typed connections — see Connections & Environments.
  • Schedule or trigger it. Add a triggers: block (cron, webhook, filesystem watch, mail, log monitor, SQS, flow-to-flow) — see Triggers & Scheduling.
  • Write a longer flow. The Authoring Flows section is the full guide.