Templating

Most task configuration fields support templates. Before a task processes an event, its configuration is rendered against the event data — so endpoints, query parameters, table names, and other fields can pull values out of the incoming event.

Flowgen uses Handlebars syntax: {{ path.to.value }}.

Where templating runs

For every incoming event, the task’s configuration is cloned and re-rendered with the event as input. This happens before the task’s handler runs, so templates always see the current event:

event arrives → render(config, event) → handler(event)

A task’s static YAML thus becomes a per-event configuration. Connectors that load credentials, schemas, or queries do so against the rendered config.

Available variables

VariableDescription
event.dataEvent payload. JSON shape depends on the source (HTTP body, script return value, query result, etc.).
event.metaKey-value metadata that travels with the event (correlation_id, user auth, custom keys set by scripts).
event.idOptional event identifier set by the source (e.g., a message ID).
event.subjectSubject string set by the producing task.
env.*Environment variables of the flowgen process.

Examples

HTTP endpoint with a path parameter:

- http_request:
    name: lookup
    endpoint: "https://api.example.com/users/{{event.data.user_id}}"
    method: GET

Routing key derived from event metadata:

- nats_jetstream_publisher:
    name: publish
    subject: "orders.{{event.meta.region}}.created"

Pulling a secret from environment:

- http_request:
    name: enrich
    endpoint: "https://api.example.com/data"
    headers:
      Authorization: "Bearer {{env.PARTNER_API_TOKEN}}"

Composing a key prefix from event data:

- nats_kv_store:
    name: cache_user
    operation: put
    key: "users.{{event.data.id}}"
    value: "{{event.data}}"

Type preservation for object and array values

When a template is exactly {{ path }} (no surrounding text, no helpers), flowgen reads the value from the data tree directly instead of converting it to a string. This means objects, arrays, booleans, and numbers retain their original types:

- nats_jetstream_publisher:
    name: forward
    # The whole event.data object is published as-is, not stringified.
    payload:
      from_event: false
      object: "{{event.data}}"
- gcp_bigquery_job:
    name: load
    operation: create
    # source_uris stays a list, not a string representation of one.
    source_uris: "{{event.meta.source_uris}}"

If you need a stringified value, embed the template inside other text: "key.{{event.data.id}}" always renders as a string.

Booleans and numbers in fields that expect them

Numeric and boolean fields (such as port, enabled, max_results) accept template strings that resolve to a number or boolean. The renderer parses the substituted result as JSON and re-typed it before deserialising the config:

- http_request:
    name: paged
    endpoint: "https://api.example.com/items"
    headers:
      X-Page-Size: "{{event.data.page_size}}"

What templating does not do

  • It does not run on every field — fields excluded from rendering (binary blobs, sensitive secrets, raw bytes) stay as-is. Most string and structured fields are rendered.
  • It does not loop or iterate. Use the iterate task for fan-out over arrays.
  • It does not call functions or helpers (no {{#if}}, {{#each}}, etc.). For conditional logic, use a script task to compute the value, then template against the script’s output.
  • It does not silently default missing variables — referencing a missing path produces a runtime error.

Templates and resource files

Resource-loaded content (SQL queries, prompts, HTML templates) is also rendered. See Resources for inline-vs-file-vs-cache trade-offs.

- gcp_bigquery_query:
    name: daily_report
    query:
      resource: queries/daily_report.sql
    parameters:
      report_date: "{{event.data.date}}"

The SQL file itself can use the same {{ event.data.x }} syntax — flowgen renders the loaded content against the event before executing the query.