Skip to content

DSL Reference

Complete reference for the workflow YAML syntax.

Workflow Structure

yaml
# Required fields
id: workflow_id                    # Unique identifier (snake_case)
title: "Human-Readable Title"      # Display name

# Optional fields
description: "What this workflow does"

category:                          # Auto-detected if omitted
  level: primitive | task | process | workflow | pipeline
  domain: engineering | sales | support | marketing | personal
  reusable: true | false

params:                            # Input parameters
  param_name: string | number | boolean

policies:
  allowed_domains:                 # Domain restrictions
    - github.com
    - "*.atlassian.net"

embed:                             # Embed button configuration
  selector: ".target-element"
  # ... see Embed Buttons section

steps:                             # Execution steps (required)
  - type: step_type
    # step-specific parameters

Parameters

Define inputs that users must provide:

yaml
params:
  repo_name: string
  max_items: number
  dry_run: boolean

Use parameters with interpolation:

yaml
steps:
  - type: browser.navigate
    url: "https://github.com/{{repo_name}}"

Policies

Domain Restrictions

Limit which domains the workflow can access:

yaml
policies:
  allowed_domains:
    - github.com           # Exact match
    - "*.atlassian.net"    # Wildcard subdomain
    - "*.google.com"

If allowed_domains is set, browser steps will fail on other domains.

Category Levels

Categories help organize workflows. They're auto-detected if omitted:

LevelAuto-Detection RuleExample
pipeline2+ workflow.call stepsComplex orchestration
workflow1+ workflow.call stepsComposed automation
processHas LLM, extract, or retryAI-powered tasks
taskHas params OR 3+ stepsParameterized work
primitive1-2 steps, no special featuresSimple actions

Embed Configuration

Inject buttons into web pages:

yaml
embed:
  selector: ".target-element"      # Where to inject button
  position: prepend | append | after | before
  when: ".page-indicator"          # Only inject when this exists
  label: "Button Text"

  # Optional: Filter by parent element
  parent_filter:
    selector: ".parent-container"
    match:
      attribute: "textContent"
      contains: "Status Text"

  # Extract values from page on click
  extract:
    my_value:
      selector: ".child-element"   # Or "self" for target
      attribute: "textContent"     # Or "href", "data-id", etc.
      pattern: "regex(capture)"    # Optional regex

  # Map to workflow params
  param_map:
    my_value: "param_name"         # Extracted → param
    _domain: "domain_param"        # Magic key → param
    _path.0: "org"                 # Path segment → param

Magic Context Keys

Available in param_map:

KeyValueExample
_urlFull page URLhttps://github.com/org/repo/pulls
_domainHostnamegithub.com
_pathnameURL path/org/repo/pulls
_titlePage titlePull requests · org/repo
_pathPath segments array["org", "repo", "pulls"]
_path.NNth path segment_path.0 = "org"

Learn more about embed buttons →

Variable Interpolation

Use {{variable}} syntax anywhere:

yaml
steps:
  - type: browser.extract
    selector: ".username"
    as: user_name

  - type: browser.type
    selector: "#greeting"
    text: "Hello, {{user_name}}!"

  - type: shell.run
    cmd: "echo 'User: {{user_name}}'"

Variable Sources

SourceSyntaxExample
Extract steps{{var_name}}{{title}}
Workflow params{{param_name}}{{repo}}
Shell output{{as_name}}{{shell_output}}
Env contexts{{env.name}}{{env.github_path}}
Nested workflows{{namespace.var}}{{data.result}}

Env Contexts

Define reusable environment variables in Settings:

yaml
# In workflow
steps:
  - type: shell.run
    cmd: "cd {{env.github_base_path}}/{{repo}}"

Env contexts are automatically passed to nested workflows.

Nested Workflows

Call other workflows with workflow.call:

yaml
steps:
  - type: workflow.call
    workflow: extract_page_data
    params:
      url: "{{target_url}}"
    as: extracted  # Namespace for variables

  # Access child variables
  - type: shell.run
    cmd: "echo '{{extracted.title}}'"

Variable Scoping

  • Child workflows receive parent's variables + their own params
  • Variables from child flow back to parent
  • Use as to namespace and avoid conflicts
  • Circular calls are prevented

File Organization

Standalone Files

workflows/my_workflow.yaml

Directory Format

workflows/my_workflow/
├── workflow.yaml
└── assets/

User Workflows

Save personal workflows in actions/ directory:

actions/
├── my_custom_workflow.yaml
└── team_automation.yaml

Complete Example

yaml
id: github_pr_summary
title: "GitHub: Summarize PR"
description: "Extract PR details and generate a summary"

params:
  org: string
  repo: string
  pr_number: number

policies:
  allowed_domains:
    - github.com

embed:
  selector: ".gh-header-actions"
  position: prepend
  when: "[data-hpc]"
  label: "Summarize"
  extract:
    pr_num:
      selector: ".gh-header-number"
      attribute: "textContent"
      pattern: "#(\\d+)"
  param_map:
    _path.0: "org"
    _path.1: "repo"
    pr_num: "pr_number"

steps:
  - type: browser.navigate
    url: "https://github.com/{{org}}/{{repo}}/pull/{{pr_number}}"

  - type: browser.wait
    selector: ".js-discussion"
    timeout: 10000

  - type: browser.extract
    selector: ".markdown-body"
    as: pr_description

  - type: browser.extractAll
    selector: ".commit-message"
    as: commits

  - type: llm.generate
    prompt: |
      Summarize this pull request:

      Description:
      {{pr_description}}

      Commits:
      {{commits}}
    as: summary

  - type: control.stop
    message: "{{summary}}"

Released under the Apache-2.0 License.