Documentation Index Fetch the complete documentation index at: https://mintlify.com/phodal/routa/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Routa workflows enable you to automate complex, multi-step agent processes using declarative YAML configuration. Workflows orchestrate multiple specialists in sequence or parallel, with conditional execution, retries, and output passing.
Key features:
Declarative YAML - Define workflows as code
Specialist orchestration - Chain multiple agents together
Parallel execution - Run steps concurrently
Conditional steps - Execute based on previous outputs
Variable substitution - Reference environment variables and step outputs
Retry logic - Handle transient failures automatically
Multiple triggers - Manual, webhook, or scheduled execution
Workflow Definition
Workflows are defined in YAML files with the following structure:
name : "My Workflow"
description : "Automates X, Y, and Z"
version : "1.0.0"
trigger :
type : manual # manual, webhook, schedule
variables :
BASE_URL : "https://api.example.com"
API_KEY : "${API_KEY}" # From environment
steps :
- name : step-1
specialist : DEVELOPER
input : "Do task X"
output_key : step1_output
- name : step-2
specialist : GATE
input : "Verify ${step1_output}"
if : "${step1_output} != null"
See type definitions: src/core/workflows/workflow-types.ts
Workflow Schema
Top-Level Fields
name : string # Workflow name (required)
description? : string # Optional description
version? : string # Version string (e.g., "1.0.0")
trigger? : TriggerConfig # How the workflow is triggered
variables? : Record<string, string> # Variable substitution map
steps : WorkflowStep[] # Ordered list of steps (required)
Trigger Configuration
trigger :
type : manual | webhook | schedule
source? : string # For webhook: "github", "gitlab", etc.
event? : string # For webhook: "pull_request.opened", etc.
cron? : string # For schedule: "0 0 * * *" (cron expression)
Workflow Steps
steps :
- name : string # Step name (unique within workflow)
specialist : string # Specialist role (ROUTA, CRAFTER, etc.)
adapter? : string # Adapter: "claude-code-sdk", "opencode-sdk", "acp"
config? : StepConfig # Adapter configuration
input? : string # Input template with variable substitution
actions? : string[] | object[] # Actions for the agent
output_key? : string # Store output under this key
if? : string # Condition: only run if true
parallel_group? : string # Steps in same group run concurrently
on_failure? : stop | continue | retry
max_retries? : number # Max retries (when on_failure = retry)
timeout_secs? : number # Timeout in seconds (default: 300)
Step Configuration
config :
model? : string # Model override
max_turns? : number # Max conversation turns
max_tokens? : number # Max response tokens
base_url? : string # API endpoint override
api_key? : string # API key (supports ${ENV_VAR})
temperature? : number # Generation temperature
system_prompt? : string # System prompt override
cwd? : string # Working directory
env? : Record<string, string> # Environment variables
Variable Substitution
Workflows support ${VAR} syntax for variable substitution:
variables :
API_URL : "https://api.example.com"
API_KEY : "${API_KEY}" # From environment
BRANCH : "main"
steps :
- name : fetch-data
specialist : DEVELOPER
input : "Fetch data from ${API_URL}/repos using key ${API_KEY}"
config :
env :
BRANCH : "${BRANCH}"
Variable resolution order:
Workflow variables map
Step outputs (via output_key)
Environment variables
Literal string (if no match)
Step Outputs
Steps can produce outputs that are referenced by downstream steps:
steps :
# Step 1: Run tests
- name : run-tests
specialist : DEVELOPER
input : "Run tests and report results"
output_key : test_results
# Step 2: Use output from step 1
- name : analyze-results
specialist : GATE
input : "Analyze test results: ${test_results}"
if : "${test_results} != null"
Output storage:
Stored in WorkflowRun.stepOutputs map
Keyed by output_key or step name
Available to all subsequent steps
Conditional Execution
Steps can be conditionally executed based on previous outputs:
steps :
- name : check-status
specialist : DEVELOPER
input : "Check API health"
output_key : api_status
- name : deploy
specialist : DEVELOPER
input : "Deploy to production"
if : "${api_status} == 'healthy'"
- name : alert
specialist : DEVELOPER
input : "Send alert to Slack"
if : "${api_status} != 'healthy'"
Condition syntax:
Simple string comparison
Check for null/existence: ${var} != null
Equality: ${var} == 'value'
Inequality: ${var} != 'value'
Parallel Execution
Steps in the same parallel_group run concurrently:
steps :
# These run in parallel
- name : lint-code
specialist : DEVELOPER
input : "Run linter"
parallel_group : "checks"
- name : type-check
specialist : DEVELOPER
input : "Run type checker"
parallel_group : "checks"
- name : run-tests
specialist : DEVELOPER
input : "Run unit tests"
parallel_group : "checks"
# This waits for all "checks" to complete
- name : report
specialist : GATE
input : "Report results"
Execution order:
Steps without parallel_group run sequentially
Steps in a parallel_group run concurrently
Next sequential step waits for all parallel steps to complete
Error Handling
Control what happens when a step fails:
steps :
# Stop workflow on failure (default)
- name : critical-step
specialist : DEVELOPER
input : "Do critical work"
on_failure : stop
# Continue to next step on failure
- name : optional-step
specialist : DEVELOPER
input : "Do optional work"
on_failure : continue
# Retry up to 3 times on failure
- name : flaky-step
specialist : DEVELOPER
input : "Call flaky API"
on_failure : retry
max_retries : 3
Failure modes:
stop (default) - Stop workflow execution, mark as FAILED
continue - Log error, continue to next step
retry - Retry up to max_retries times, then stop if still failing
Workflow Examples
Example 1: PR Review Workflow
name : "Pull Request Review"
description : "Automated PR review and approval"
version : "1.0.0"
trigger :
type : webhook
source : github
event : pull_request.opened
variables :
GITHUB_TOKEN : "${GITHUB_TOKEN}"
PR_NUMBER : "${GITHUB_PR_NUMBER}"
steps :
- name : fetch-pr
specialist : DEVELOPER
input : "Fetch PR #${PR_NUMBER} details from GitHub"
output_key : pr_details
- name : review-code
specialist : CODE_REVIEWER
input : "Review code changes in PR #${PR_NUMBER}"
output_key : review_comments
- name : run-tests
specialist : DEVELOPER
input : "Run test suite"
output_key : test_results
parallel_group : "validation"
- name : security-scan
specialist : SECURITY_AUDITOR
input : "Scan for security issues"
output_key : security_report
parallel_group : "validation"
- name : post-review
specialist : DEVELOPER
input : "Post review comments: ${review_comments}"
if : "${review_comments} != null"
- name : approve-pr
specialist : DEVELOPER
input : "Approve PR if tests pass and no security issues"
if : "${test_results} == 'pass' && ${security_report} == 'clean'"
Example 2: Deployment Workflow
name : "Production Deployment"
description : "Deploy to production with rollback"
version : "1.0.0"
trigger :
type : manual
variables :
ENV : "production"
DEPLOY_USER : "${USER}"
steps :
- name : pre-deploy-check
specialist : GATE
input : "Verify all tests pass and main is up to date"
on_failure : stop
- name : build
specialist : DEVELOPER
input : "Build production bundle"
output_key : build_artifact
timeout_secs : 600
- name : deploy
specialist : DEVELOPER
input : "Deploy ${build_artifact} to ${ENV}"
output_key : deploy_status
on_failure : retry
max_retries : 2
- name : smoke-test
specialist : GATE
input : "Run smoke tests on ${ENV}"
output_key : smoke_test_results
- name : rollback
specialist : DEVELOPER
input : "Rollback deployment"
if : "${smoke_test_results} == 'fail'"
- name : notify-success
specialist : DEVELOPER
input : "Send success notification to Slack"
if : "${smoke_test_results} == 'pass'"
Example 3: Scheduled Maintenance
name : "Daily Maintenance"
description : "Daily database cleanup and optimization"
version : "1.0.0"
trigger :
type : schedule
cron : "0 2 * * *" # 2 AM daily
variables :
DATABASE_URL : "${DATABASE_URL}"
steps :
- name : backup-db
specialist : DEVELOPER
input : "Create database backup"
output_key : backup_file
on_failure : stop
- name : cleanup-old-data
specialist : DEVELOPER
input : "Delete records older than 90 days"
on_failure : continue
- name : optimize-tables
specialist : DEVELOPER
input : "Run VACUUM ANALYZE on all tables"
on_failure : continue
- name : verify-backup
specialist : GATE
input : "Verify backup ${backup_file} is valid"
- name : report
specialist : DEVELOPER
input : "Send maintenance report to ops channel"
Example 4: Multi-Repo Analysis
name : "Multi-Repository Analysis"
description : "Analyze multiple repositories in parallel"
version : "1.0.0"
variables :
REPOS : "repo1,repo2,repo3"
ORG : "myorg"
steps :
# Analyze repos in parallel
- name : analyze-repo1
specialist : CODE_ANALYZER
input : "Analyze ${ORG}/repo1"
output_key : repo1_report
parallel_group : "analysis"
- name : analyze-repo2
specialist : CODE_ANALYZER
input : "Analyze ${ORG}/repo2"
output_key : repo2_report
parallel_group : "analysis"
- name : analyze-repo3
specialist : CODE_ANALYZER
input : "Analyze ${ORG}/repo3"
output_key : repo3_report
parallel_group : "analysis"
# Aggregate results
- name : aggregate
specialist : DEVELOPER
input : |
Aggregate analysis results:
- Repo1: ${repo1_report}
- Repo2: ${repo2_report}
- Repo3: ${repo3_report}
output_key : summary
- name : generate-dashboard
specialist : DEVELOPER
input : "Generate dashboard from ${summary}"
Running Workflows
Via REST API
Create Workflow
curl -X POST http://localhost:3000/api/workflows \
-H "Content-Type: application/json" \
-d @workflow.json
Trigger Workflow Run
curl -X POST http://localhost:3000/api/workflows/ < workflow-i d > /runs \
-H "Content-Type: application/json" \
-d '{
"workspaceId": "default",
"triggerSource": "manual"
}'
Response:
{
"id" : "run-123" ,
"workflowId" : "wf-456" ,
"workflowName" : "My Workflow" ,
"status" : "PENDING" ,
"totalSteps" : 5 ,
"completedSteps" : 0 ,
"createdAt" : "2026-03-03T12:00:00.000Z"
}
Get Workflow Run Status
curl http://localhost:3000/api/workflows/runs/ < run-i d >
Response:
{
"id" : "run-123" ,
"status" : "RUNNING" ,
"currentStepName" : "step-2" ,
"completedSteps" : 1 ,
"totalSteps" : 5 ,
"stepOutputs" : {
"step1_output" : "Result from step 1"
}
}
List Workflow Runs
curl http://localhost:3000/api/workflows/ < workflow-i d > /runs
Cancel Workflow Run
curl -X POST http://localhost:3000/api/workflows/runs/ < run-i d > /cancel
Via CLI
# Run workflow
routa workflow run my-workflow.yaml
# Run with variables
routa workflow run my-workflow.yaml \
--var API_KEY=sk-... \
--var ENV=production
# List runs
routa workflow list-runs
# Get run status
routa workflow status < run-i d >
# Cancel run
routa workflow cancel < run-i d >
Workflow Storage
Workflows and runs are stored in the database:
CREATE TABLE workflows (
id TEXT PRIMARY KEY ,
name TEXT NOT NULL ,
description TEXT ,
version TEXT ,
definition JSONB NOT NULL , -- Full YAML as JSON
workspace_id TEXT ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE workflow_runs (
id TEXT PRIMARY KEY ,
workflow_id TEXT NOT NULL ,
workflow_name TEXT NOT NULL ,
workflow_version TEXT ,
workspace_id TEXT NOT NULL ,
status TEXT NOT NULL CHECK ( status IN ( 'PENDING' , 'RUNNING' , 'COMPLETED' , 'FAILED' , 'CANCELLED' )),
current_step_name TEXT ,
trigger_payload TEXT ,
trigger_source TEXT NOT NULL ,
step_outputs JSONB,
error_message TEXT ,
total_steps INTEGER NOT NULL ,
completed_steps INTEGER DEFAULT 0 ,
started_at TIMESTAMP ,
completed_at TIMESTAMP ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
See implementation: src/core/workflows/workflow-store.ts
Monitoring and Debugging
View Run Logs
# Get run details
curl http://localhost:3000/api/workflows/runs/ < run-i d >
# Get step outputs
curl http://localhost:3000/api/workflows/runs/ < run-i d > /outputs
# Get error details (if failed)
curl http://localhost:3000/api/workflows/runs/ < run-i d > /error
Debug Failed Runs
# Check which step failed
curl http://localhost:3000/api/workflows/runs/ < run-i d > | jq '.currentStepName, .errorMessage'
# View step outputs up to failure
curl http://localhost:3000/api/workflows/runs/ < run-i d > /outputs | jq
# Re-run from failed step
curl -X POST http://localhost:3000/api/workflows/runs/ < run-i d > /retry
Best Practices
Each step should do one thing well: # Good
- name : run-tests
input : "Run unit tests"
- name : check-coverage
input : "Check test coverage > 80%"
# Avoid
- name : test-and-deploy
input : "Run tests and deploy if pass"
Use parallel groups for independent tasks
steps :
- name : lint
parallel_group : "checks"
- name : type-check
parallel_group : "checks"
- name : test
parallel_group : "checks"
- name : long-running-task
timeout_secs : 1800 # 30 minutes
Default is 300s (5 minutes).
Use output keys for dependencies
- name : build
output_key : artifact
- name : deploy
input : "Deploy ${artifact}"
Handle failures gracefully
- name : optional-task
on_failure : continue
- name : flaky-api
on_failure : retry
max_retries : 3
Troubleshooting
Check YAML syntax: yamllint workflow.yaml
Verify all specialists exist
Ensure variables are defined
Increase timeout_secs for the step
Check if agent is stuck waiting for user input
Review agent conversation logs
Verify variable is defined in variables or environment
Check syntax: ${VAR} not $VAR
Ensure step output key matches reference
Parallel steps not running concurrently
Verify all steps have the same parallel_group value
Check if previous sequential step completed
Review workflow execution logs
Conditional step not executing
Check condition syntax
Verify referenced output key exists
Review step outputs: GET /api/workflows/runs/<run-id>/outputs
Next Steps
Custom Specialists Create specialists for workflow steps
Custom MCP Servers Give workflows access to external tools
GitHub Integration Trigger workflows from GitHub events
Desktop App Run workflows in desktop environment