Skip to content

States

States are the fundamental building blocks of FlowState workflows. Each state invokes a tool and determines what happens next based on the result.

A complete state definition:

state-name:
tool: bash # Required: which tool to invoke
arguments: # Tool-specific arguments
command: echo "Hello"
output: var(result) # Optional: capture stdout
next: another-state # Optional: next state on success
on-error: # Optional: error handlers
1: handle-error
_: fallback
goto: # For switch tool only
"true": path-a
"false": path-b
_: default-path

The tool to execute. Must be one of the built-in tools or a registered custom tool.

my-state:
tool: bash
arguments:
command: ls -la

A key-value map of arguments passed to the tool. Required arguments depend on the tool:

ToolRequired Arguments
bashcommand
claudeprompt
claude-codeprompt
codexprompt
geminiprompt
ask-userquestion
get-gh-issueissue-number
paralleltasks
sub-flowworkflow
pausereason
switchvalue

The state to transition to after successful execution. If omitted, the workflow ends after this state.

step-1:
tool: bash
arguments:
command: echo "Step 1"
next: step-2
step-2:
tool: bash
arguments:
command: echo "Step 2"
# No next - workflow ends here

Capture the tool’s stdout to a variable or file.

# Capture to variable
get-version:
tool: bash
arguments:
command: cat VERSION
output: var(app_version)
# Capture to file
save-logs:
tool: bash
arguments:
command: docker logs myapp
output: file(./logs/app.log)

See Variables for output capture details.

Map exit codes to error-handling states. The special key _ serves as a wildcard matching any unhandled exit code.

risky-operation:
tool: bash
arguments:
command: ./might-fail.sh
on-error:
1: handle-permission-error
2: handle-not-found
_: handle-unknown-error
next: success-state

See Error Handling for patterns and best practices.

Used exclusively with the switch tool for conditional branching. Maps evaluated values to target states.

check-environment:
tool: switch
arguments:
value: "{{ env }}"
goto:
production: deploy-prod
staging: deploy-staging
_: deploy-dev

Most workflows follow a linear path through states:

start-at: step-1
states:
step-1:
tool: bash
arguments:
command: echo "First"
next: step-2
step-2:
tool: bash
arguments:
command: echo "Second"
next: step-3
step-3:
tool: bash
arguments:
command: echo "Third"

Use the switch tool with goto for conditional paths:

check-status:
tool: bash
arguments:
command: cat ./status.txt
output: var(status)
next: branch
branch:
tool: switch
arguments:
value: "{{ status }}"
goto:
ready: proceed
pending: wait-more
_: handle-unknown
proceed:
tool: bash
arguments:
command: echo "Proceeding..."
wait-more:
tool: pause
arguments:
reason: "Waiting for status to change"
next: check-status

Error states can rejoin the main flow or terminate:

fetch-data:
tool: bash
arguments:
command: curl https://api.example.com/data
output: var(data)
on-error:
_: retry-fetch
next: process-data
retry-fetch:
tool: bash
arguments:
command: sleep 5
next: fetch-data # Retry the original operation
process-data:
tool: bash
arguments:
command: 'echo "{{ data }}"'

A state without next is terminal - the workflow ends after it executes. This applies to success and error handlers alike:

# Normal terminal state
final-step:
tool: bash
arguments:
command: echo "Workflow complete"
# No next - workflow ends
# Error terminal state
fatal-error:
tool: bash
arguments:
command: echo "Unrecoverable error" >&2
# No next - workflow ends with whatever exit code this produces

State names should be:

  • Descriptive: fetch-user-data not step-1
  • Kebab-case: validate-input not validateInput
  • Action-oriented: send-notification not notification

Reserved patterns to avoid:

  • Names containing / (used for subflow state paths)
  • Names starting with _ (may have special meaning in future versions)