Workflow Structure

Workflows are defined in YAML files with the following structure:

name: workflow-name
description: What this workflow does

# Optional: Trigger that starts the workflow
trigger:
  type: trigger.type
  with:
    key: value

# Required: Steps to execute
steps:
  - id: step-id
    action: action.name
    with:
      key: value

Fields

Field Required Description
name Yes Unique identifier for the workflow
description No Human-readable description
trigger No Event that starts the workflow automatically
steps Yes Array of steps to execute

Triggers

Triggers define events that automatically start a workflow.

Available Triggers

Trigger Description
cron.schedule Run on a schedule (cron expression)
http.webhook Run when a webhook is received
github.push Run on GitHub push events
github.pull_request Run on GitHub PR events
github.issue.opened Run when a GitHub issue is opened
telegram.message Run on incoming Telegram messages

See Integrations for detailed trigger configuration.

Steps

Steps are the individual units of work in a workflow.

steps:
  - id: unique-step-id       # Required: Unique identifier
    action: plugin.action    # Required: Action to execute
    needs: [other-step-id]   # Optional: Dependencies
    if: "{{ condition }}"    # Optional: Conditional execution
    with:                    # Optional: Action parameters
      key: value
    retry:                   # Optional: Retry configuration
      attempts: 3
      delay: 1000

Step Fields

Field Description
id Unique identifier for referencing in other steps
action The action to execute (plugin.action format)
needs Array of step IDs that must complete first
if Condition that must be true to run this step
with Parameters passed to the action
retry Retry configuration for failed steps

Built-in Actions

transform

Create a value from a template string.

- id: message
  action: transform
  with:
    template: "Hello, {{ input.name }}!"

log

Log a message to the workflow output.

- id: log-result
  action: log
  with:
    message: "Processing complete: {{ steps.process.result }}"

http.request

Make an HTTP request.

- id: fetch-data
  action: http.request
  with:
    url: "https://api.example.com/data"
    method: GET
    headers:
      Authorization: "Bearer {{ env.API_TOKEN }}"

ai.agent

Execute an AI agent task. See AI Agents for details.

- id: analyze
  action: ai.agent
  with:
    task: "Analyze this data and provide insights"

json.parse

Parse a JSON string into an object.

- id: parse-response
  action: json.parse
  with:
    input: "{{ steps.fetch.body }}"

json.stringify

Convert an object to a JSON string.

- id: serialize
  action: json.stringify
  with:
    input: "{{ steps.data }}"
    pretty: true

Dependencies

Use needs to control step execution order.

steps:
  - id: fetch
    action: http.request
    with:
      url: "https://api.example.com/data"

  - id: parse
    action: json.parse
    needs: [fetch]              # Runs after 'fetch' completes
    with:
      input: "{{ steps.fetch.body }}"

  - id: process
    action: ai.agent
    needs: [parse]              # Runs after 'parse' completes
    with:
      task: "Analyze: {{ steps.parse }}"

  - id: notify
    action: slack.post
    needs: [process]            # Runs after 'process' completes
    with:
      channel: "#results"
      text: "{{ steps.process.response }}"

Parallel Execution

Steps without dependencies or with the same dependencies run in parallel.

steps:
  - id: fetch-users
    action: http.request
    with:
      url: "/api/users"

  - id: fetch-orders
    action: http.request
    with:
      url: "/api/orders"

  # Both fetch steps run in parallel
  # This step waits for both
  - id: combine
    action: transform
    needs: [fetch-users, fetch-orders]
    with:
      template: "Users: {{ steps.fetch-users.body }}, Orders: {{ steps.fetch-orders.body }}"

Variable Interpolation

Use {{ }} syntax to reference dynamic values.

Available Variables

Variable Description
{{ trigger.* }} Data from the trigger event
{{ steps.stepId }} Output from a previous step
{{ steps.stepId.field }} Specific field from step output
{{ input.* }} Input data passed to the workflow
{{ env.VAR_NAME }} Environment variable
{{ currentISODate }} Current timestamp in ISO format

Examples

# Access trigger data
message: "New PR: {{ trigger.pullRequest.title }}"

# Access step output
body: "{{ steps.analyze.response }}"

# Access nested fields
author: "{{ trigger.issue.user.login }}"

# Environment variables
token: "{{ env.GITHUB_TOKEN }}"

# Combine values
url: "https://api.example.com/{{ trigger.repo }}/issues/{{ trigger.number }}"

Conditional Execution

Use if to conditionally execute steps.

steps:
  - id: check-label
    action: transform
    with:
      template: "{{ trigger.action }}"

  # Only run if PR was opened
  - id: review
    action: ai.agent
    if: "{{ trigger.action == 'opened' }}"
    with:
      task: "Review this PR"

  # Only run if labeled with 'urgent'
  - id: alert
    action: slack.post
    if: "{{ 'urgent' in trigger.issue.labels }}"
    with:
      channel: "#urgent"
      text: "Urgent issue: {{ trigger.issue.title }}"