Skip to content

Vocabulary

This page introduces the words the rest of the documentation uses. No YAML syntax here — that lives in Authoring Flows. Read this once and the rest reads at full speed.

A flow is the unit of work: a YAML file describing how data moves through a pipeline as a directed acyclic graph — a sequence (or tree) of steps that begins with a typed input, ends with a typed output, and transforms data along the way.

graph TD
    input([typed input]) --> products[fetch products]
    input --> stock[fetch stock]
    products --> join[join]
    stock --> join
    join --> filter[filter active]
    filter --> output([typed output])

A flow is portable: the same flow runs against dev, staging, or production environments without YAML edits. The flow describes what to do; the environment describes which services to do it against. A single run of a flow is an invocation — its own UUIDv7 ID, its own log, its own output. Invocations are independent and can run in parallel.

A flow is a sequence of steps. Each step is one of:

  • An operation — invokes an operator with a with: block of inputs.
  • A control-flow constructif:, for-each:, switch:. Branches or iterates.
  • A transformerjoin: (relational join), delta: (change detection), filter: (SQL-like array filtering).
  • A built-in verblog:, return:, halt:, set:, $var:.

Steps may be named or unnamed. A named step’s output lands in the payload under that name ($fetch: makes its output available as ${fetch}). Unnamed steps are used when you only care about the side effect — a log: line, an if: condition.

An operator is the verb: a typed, named, versioned function that takes structured input and returns structured output. Examples: zenvara/http, zenvara/mssql, zenvara/sftp, zenvara/claude. Each name is provider-qualified — the part before the / is the publisher.

An operator can have multiple actions. The HTTP operator has get, post, put, delete; the MSSQL operator has query, execute, bulk-insert. A flow step picks an operator and an action: invoke: http.get, invoke: mssql.query.

Every operator carries a metadata file (definition.yaml) declaring its actions, typed inputs, typed outputs, and per-action documentation. The Operator Catalog is built from those files.

The payload is the data carried between steps — a map of typed values, each one of five types: Boolean, String, Number, Array, Object. There is no untyped “any”.

Each step’s output is merged back into the payload under the step’s assigned name. After $fetch: runs, the payload contains a fetch entry, and later steps reference fields on it as ${fetch.body}, ${fetch.statusCode}. The payload accumulates as the flow runs; the only data that leaves the flow is what the output: block declares.

graph LR
    p1["payload<br/>{ city }"] -->|$weather| p2["payload<br/>{ city, weather }"]
    p2 -->|$report| p3["payload<br/>{ city, weather, report }"]

A connection is the typed configuration for one external service: a database, an SFTP, an API, a mail server. Each has a type: (which operator family it belongs to), an optional kind: (production, staging, development, sandbox), and the parameters that operator needs.

Connections live under config/connections/{name}/. Credentials inside a connection are always references${secret:db/warehouse:password}, never the password itself. The platform refuses to load a connection containing a plain credential.

An environment is a profile of connections. It maps short aliases (db, sftp, audit) onto named connections (warehouse-prod, archive-sftp). A flow asks for db; the environment decides which real connection that resolves to today.

graph LR
    flow["Flow asks &quot;db&quot;"] -->|env: dev| dev["db → warehouse-dev"] --> devhost[dev DB host]
    flow -->|env: prod| prod["db → warehouse-prod"] --> prodhost[prod DB host]

Same flow, two invocations, two completely different real services. Environments live under config/environments/{name}/ and can extend: other environments.

A secret is a credential kept out of source. Connection and flow YAML reference secrets as ${secret:path} (whole-value) or ${secret:path:key} (sub-key, when one entry has multiple fields like host/username/password).

Secrets are resolved at flow start in a single async batch. If any secret a flow references cannot be resolved, the flow fails before any operator runs — there is no half-failed state. Two providers: an encrypted file (AES-256-GCM, single-host) or HashiCorp Vault.

A trigger is what kicks a flow off. The platform supports cron schedules, HTTP webhooks, AWS SQS, mail, filesystem watch, log monitoring, and flow-to-flow invocation. A flow can have multiple triggers — fired by a cron at 09:00 and by a webhook on demand and by a file landing in an SFTP directory. The flow body does not change based on which trigger fired it; the difference shows up only in the source payload key.

A branch is versioning and staging without git surgery. When git-backed storage is enabled, every change to a flow, environment, connection, or secret is committed automatically. Branches let you stage changes safely before promoting to production.

URLs carry the branch as a path segment: /api/v1/main/flows/... runs against production; /api/v1/staging/flows/... runs against the staging branch. Where git versioning is disabled, the alias live resolves to whatever the production branch is.

EntityYou write this when…Lives at
Flow…describing a pipeline: what runs, in what order, with what inputs and outputs.flows/{name}/definition.yaml
Connection…pointing at one external service: a database, an SFTP, an API.config/connections/{name}/definition.yaml
Environment…bundling connections into a runnable profile (dev, staging, prod).config/environments/{name}/definition.yaml
Secret…storing a credential a connection or flow needs at runtime.auth/secrets.enc (or HashiCorp Vault)