Skip to main content
DocsBuild WorkflowStep Type

8 Step Types

Usage and field reference of single Agent, group_chat, agent_based, code, classifier, state_machine, sub_workflow, manual_approval.

Braidrun currently offers 8 step types. Only one main mode must be selected for each step; other fields are enhancements (retry, condition, manual_approval, etc.).

1. Single — Single Agent

The most common step: asking an Agent to perform a task.

yaml
  - step: plan
    agent: planner
    input: "Plan a daily report pipeline"
    depends_on: [intro]
    retry:
      maxAttempts: 3
      backoff: exponential

Allowed combined enhancements: parallelrepeat_untiliterate_over.

2. group_chat — Multi-Agent Discussion

Multiple Agents take turns speaking on the same topic. You can specify the speaking order, or let the orchestrator decide.

yaml
  - step: peer_review
    group_chat:
      agents: [coder, reviewer]
      topic: "Review the change"
      max_rounds: 6
      repeat_until: "score >= 8"

repeat_until The conditional expression will be evaluated after each round; if it is met, group_chat will end.

3. agent_based — Dynamic Delegation

The orchestrator agent selects workers and dispatches subtasks at runtime. Compared with static group_chat, it is more suitable for the scenario of "I don't know who is suitable, let the planner decide".

yaml
  - step: delegate
    agent_based:
      orchestrator: planner
      workers: [coder, analyst, writer]
      input: "{{steps.plan.output}}"

4. Code — Deterministic Script

Supports 7 languages: Python / JavaScript / TypeScript / Bash / Ruby / Lua / CLI. In production, they run in a sandboxed container by default.

yaml
code_preamble:
  python:
    inline: |
      import json, os

workflow:
  - step: transform
    code:
      language: python
      timeout: 30
      script: |
        data = json.loads(os.environ.get("STEP_INPUTS", "{}"))
        print(json.dumps({"rows": len(data)}))
Shared Code Prefix

When multiple code steps need to share imports or utility functions, use the top-level code_preamble, grouped by programming language; at run time it's automatically prepended to the script of code steps in the same language.

5. Classifier — Routing Variable

Let the Agent take "Which category the current context belongs to" as output and write it into a routing variable for use by condition in subsequent steps.

yaml
  - step: classify_request
    classifier:
      agent: router
      input: "Classify the user intent"
      categories:
        - name: coding
          description: Needs code changes
        - name: analysis
          description: Needs investigation only
      output_variable: route

  - step: coding_path
    agent: coder
    condition: route == coding
    depends_on: [classify_request]

Recommended classifier + condition instead of complex on_success.next String array.

6. state_machine — Nested State Machine

Running as a DAG composite node, it can have several states and transitions inside it.

yaml
  - step: triage
    state_machine:
      initial: ingest
      states:
        - name: ingest
          agent: planner
          transitions:
            - condition: route == analysis
              next: analyze
            - condition: route == coding
              next: code
        - name: analyze
          agent: analyst
          transitions:
            - next: DONE
        - name: code
          agent: coder
          transitions:
            - next: DONE

Do not configure parallel in the outer steps; there is only one flow entering state_machine.

7. sub_workflow — Sub-Workflow Module

Call another published Module. Input/output adheres to the contract declared by the module; loop detection is performed at runtime.

yaml
  - step: fetch_report
    sub_workflow:
      workflow_id: 0d2c…ab12        # UUID of the published module
      version_strategy: pinned
      pinned_version: "2.0.1"
      inputs:
        app_id: "{{var:app_id}}"
        window: last_7d
      outputs:
        report_path: report_path    # parent variable <- module output

List all built-in modules: Built-In Module Library.

8. workflow_output_read — Cross-Workflow Reads

A system-level step: it reads values from the outputs published by an execution of another workflow (see publish_outputs below) and writes them into this workflow's variables. By default it reads the source workflow's most recent successful execution.

yaml
  - step: read_spend_report
    workflow_output_read:
      workflow_id: 7f3a…9c21           # source workflow UUID
      selector:
        mode: latest_successful
      outputs:
        report_url: spend_report_url   # published name -> local variable
      missing_policy: use_default
      defaults:
        report_url: ""
  • selector.mode — Defaults to latest_successful (the most recent successful execution); you can also use execution_id to pick a specific execution, or input_variable to take the execution id from a variable
  • outputs — Required: a mapping from published output names to this workflow's variable names
  • missing_policy — When an output is missing: fail (default, the step errors), skip_step (skip this step), or use_default (take the value from defaults)
  • require_workflow_status — By default the source execution must have status COMPLETED

Step-Level Enhancements

The following fields aren't standalone step types but enhancement configs added onto a step.

manual_approval — Manual Approval

Add a manual gate before any step: execution pauses and notifies the reviewer, continues on approval, and stops on rejection or timeout.

yaml
  - step: deploy
    agent: deployer
    input: "Deploy to production"
    manual_approval:
      enabled: true
      approvers:
        - team-lead@company.com
      timeout: 3600
      approval_message: "Ready to ship?"

View the complete parameter list and approval process: Manual Approval.

publish_outputs — Publish Step Outputs Externally

After a step succeeds, publish named outputs for other workflows to read via workflow_output_read. By default, no internal artifacts are published.

yaml
  - step: build_report
    agent: analyst
    input: "Summarize yesterday's spend"
    publish_outputs:
      - name: report_url
        type: url
        source: "{{steps.build_report.output}}"
        description: Latest spend report link
        visibility:
          scope: team
  • source — Required: a template expression evaluated at publish time, e.g. referencing this step's output
  • type — Defaults to text; also supports markdown, json, number, boolean, url, file, and more
  • visibility.scope — private (default, only the workflow owner), team, or workflow_allowlist (paired with the allowed_workflows allowlist)

structured_output — Structured Final Output

Single-Agent steps only: the Agent calls tools as usual, but its final reply is parsed into a structured result against a registered schema; when write_to is set, the result is also serialized to a file.

yaml
  - step: final_commentary
    agent: analyst
    input: "Write the commentary"
    structured_output:
      schema: ai_commentary_parts
      write_to: "{{var:output_dir}}/commentary.json"
      fail_on_empty: true
  • schema — Required: the name of a registered structured schema
  • write_to — Optional: the file path to write to, with template-variable support; the write format currently supports only json
  • fail_on_empty — Whether to fail the step when the structured result is empty; defaults to true

A Quick Look at Combo Limits

  • parallel — Only single Agent steps can be configured
  • repeat_until — Only single Agent or group_chat
  • iterate_over — Only single Agent or code
  • structured_output — Single-Agent steps only
  • state_machine — Run as a DAG composite node, do not configure parallel in the outer layer