The OpenFang workflow engine enables multi-step agent pipelines where each step routes work to a specific agent, and output from one step flows as input to the next. Compose complex behaviors from simple, single-purpose agents without writing code.
When to Use Workflows
Use workflows when you need to:
Sequential Processing Chain agents in a pipeline (research → write → review)
Parallel Execution Fan work out to multiple agents and collect results
Conditional Logic Branch execution based on previous step outputs
Iterative Refinement Loop until a quality gate is met
Quick Start
Create a workflow via the REST API:
curl -X POST http://localhost:4200/api/workflows \
-H "Content-Type: application/json" \
-d '{
"name": "code-review-pipeline",
"description": "Analyze code, review for issues, and produce summary",
"steps": [
{
"name": "analyze",
"agent_name": "code-reviewer",
"prompt": "Analyze this code for bugs:\n\n{{input}}",
"mode": "sequential",
"output_var": "analysis"
},
{
"name": "security-check",
"agent_name": "security-auditor",
"prompt": "Review for security issues:\n\n{{analysis}}",
"mode": "sequential",
"output_var": "security_review"
},
{
"name": "summary",
"agent_name": "writer",
"prompt": "Write summary:\n\nAnalysis: {{analysis}}\n\nSecurity: {{security_review}}"
}
]
}'
Execute the workflow:
curl -X POST http://localhost:4200/api/workflows/{id}/run \
-H "Content-Type: application/json" \
-d '{"input": "Your code here..."}'
Step Configuration
Each step in a workflow has the following structure:
{
"name" : "step-name" ,
"agent_name" : "researcher" , // OR "agent_id": "uuid"
"prompt" : "Research: {{input}}" ,
"mode" : "sequential" , // sequential | fan_out | collect | conditional | loop
"timeout_secs" : 120 , // Default: 120
"error_mode" : "fail" , // fail | skip | retry
"max_retries" : 3 , // Only for retry mode
"output_var" : "research_output" , // Optional: store output for later reference
"condition" : "ERROR" , // Only for conditional mode
"max_iterations" : 5 , // Only for loop mode
"until" : "APPROVED" // Only for loop mode
}
Agent Resolution
Specify exactly one of:
agent_name - Reference agent by name (first match)
agent_id - Reference agent by UUID
If the agent cannot be resolved at execution time, the workflow fails.
Execution Modes
Sequential (Default)
The step runs after the previous step completes. Previous output becomes {{input}}.
Step 1
Receives initial workflow input
Step 2
Receives Step 1’s output as {{input}}
Step 3
Receives Step 2’s output as {{input}}
Fan-Out (Parallel)
Multiple steps run in parallel . All receive the same {{input}} from the last sequential step.
If any fan-out step fails or times out, the entire workflow fails immediately.
Example : Three agents brainstorm in parallel:
{
"steps" : [
{
"name" : "creative-ideas" ,
"agent_name" : "writer" ,
"prompt" : "Brainstorm 5 creative ideas for: {{input}}" ,
"mode" : "fan_out"
},
{
"name" : "technical-ideas" ,
"agent_name" : "architect" ,
"prompt" : "Brainstorm 5 technical ideas for: {{input}}" ,
"mode" : "fan_out"
},
{
"name" : "business-ideas" ,
"agent_name" : "analyst" ,
"prompt" : "Brainstorm 5 business ideas for: {{input}}" ,
"mode" : "fan_out"
}
]
}
Collect
Gathers all outputs from preceding fan-out steps. This is a data-only step (no agent execution).
Outputs are joined with \n\n---\n\n and set as {{input}} for subsequent steps.
Typical pattern :
step 1: fan_out → runs in parallel
step 2: fan_out → runs in parallel
step 3: collect → joins outputs
step 4: sequential → receives joined output
Conditional
The step only executes if previous output contains the condition substring (case-insensitive).
{ "mode" : "conditional" , "condition" : "ERROR" }
Example : Fact-check only if the article mentions claims:
{
"name" : "fact-check" ,
"agent_name" : "analyst" ,
"prompt" : "Fact-check this article: \n\n {{article}}" ,
"mode" : "conditional" ,
"condition" : "claim" ,
"error_mode" : "skip"
}
Loop
The step repeats up to max_iterations times. Terminates early if output contains the until substring.
{ "mode" : "loop" , "max_iterations" : 5 , "until" : "APPROVED" }
Each iteration feeds its output back as {{input}} for the next iteration.
Example : Iterative refinement until approval:
{
"name" : "review-and-refine" ,
"agent_name" : "code-reviewer" ,
"prompt" : "Review this draft. If quality is good, respond with APPROVED. Otherwise, provide feedback and a revised version: \n\n {{input}}" ,
"mode" : "loop" ,
"max_iterations" : 4 ,
"until" : "APPROVED"
}
Variable Substitution
Prompt templates support two kinds of variables:
Always available. Contains output from the immediately preceding step (or workflow’s initial input for the first step).
{{variable_name}} - Named Variables
When a step has "output_var": "my_var", its output is stored and can be referenced in later steps:
{
"steps" : [
{
"name" : "research" ,
"output_var" : "research_output" ,
"prompt" : "Research: {{input}}"
},
{
"name" : "outline" ,
"output_var" : "outline_output" ,
"prompt" : "Outline based on: {{input}}"
},
{
"name" : "combine" ,
"prompt" : "Write article. \n Research: {{research_output}} \n Outline: {{outline_output}}"
}
]
}
Variables persist for the entire workflow run. Later steps can overwrite variables by using the same output_var name.
Error Handling
Fail (Default)
The workflow aborts immediately on error or timeout. The run state is set to Failed.
Skip
The step is silently skipped on error. A warning is logged, but the workflow continues. The {{input}} for the next step remains unchanged.
Retry
{ "error_mode" : "retry" , "max_retries" : 3 }
The step is retried up to max_retries times after the initial attempt (4 total attempts). Each attempt gets the full timeout budget.
If all attempts fail, the workflow aborts with an error.
Complete Examples
Example 1: Code Review Pipeline
Sequential pipeline where code is analyzed, reviewed for security, and summarized.
{
"name" : "code-review-pipeline" ,
"description" : "Analyze code, review for issues, and produce summary" ,
"steps" : [
{
"name" : "analyze" ,
"agent_name" : "code-reviewer" ,
"prompt" : "Analyze the following code for bugs, style issues, and security vulnerabilities: \n\n {{input}}" ,
"mode" : "sequential" ,
"timeout_secs" : 180 ,
"error_mode" : "fail" ,
"output_var" : "analysis"
},
{
"name" : "security-check" ,
"agent_name" : "security-auditor" ,
"prompt" : "Review this code analysis for security issues: \n\n {{analysis}}" ,
"mode" : "sequential" ,
"timeout_secs" : 120 ,
"error_mode" : "retry" ,
"max_retries" : 2 ,
"output_var" : "security_review"
},
{
"name" : "summary" ,
"agent_name" : "writer" ,
"prompt" : "Write a concise code review summary. \n\n Code Analysis: \n {{analysis}} \n\n Security Review: \n {{security_review}}" ,
"mode" : "sequential" ,
"timeout_secs" : 60
}
]
}
Example 2: Multi-Agent Brainstorm
Three agents brainstorm in parallel, then a fourth synthesizes their ideas.
{
"name" : "brainstorm" ,
"description" : "Parallel brainstorm with 3 agents, then synthesize" ,
"steps" : [
{
"name" : "creative-ideas" ,
"agent_name" : "writer" ,
"prompt" : "Brainstorm 5 creative ideas for: {{input}}" ,
"mode" : "fan_out" ,
"timeout_secs" : 60
},
{
"name" : "technical-ideas" ,
"agent_name" : "architect" ,
"prompt" : "Brainstorm 5 technically feasible ideas for: {{input}}" ,
"mode" : "fan_out" ,
"timeout_secs" : 60
},
{
"name" : "business-ideas" ,
"agent_name" : "analyst" ,
"prompt" : "Brainstorm 5 ideas with strong business potential for: {{input}}" ,
"mode" : "fan_out" ,
"timeout_secs" : 60
},
{
"name" : "gather" ,
"mode" : "collect"
},
{
"name" : "synthesize" ,
"agent_name" : "orchestrator" ,
"prompt" : "You received brainstorm results from three perspectives. Synthesize them into the top 5 actionable ideas, ranked by impact: \n\n {{input}}" ,
"mode" : "sequential" ,
"timeout_secs" : 120
}
]
}
Example 3: Iterative Refinement
Agent refines a draft until it meets quality standards.
{
"name" : "iterative-refinement" ,
"description" : "Refine document until approved or max iterations" ,
"steps" : [
{
"name" : "first-draft" ,
"agent_name" : "writer" ,
"prompt" : "Write a first draft about: {{input}}" ,
"mode" : "sequential" ,
"timeout_secs" : 120 ,
"output_var" : "draft"
},
{
"name" : "review-and-refine" ,
"agent_name" : "code-reviewer" ,
"prompt" : "Review this draft. If it meets quality standards, respond with APPROVED at the start. Otherwise, provide specific feedback and a revised version: \n\n {{input}}" ,
"mode" : "loop" ,
"max_iterations" : 4 ,
"until" : "APPROVED" ,
"timeout_secs" : 180 ,
"error_mode" : "retry" ,
"max_retries" : 1
}
]
}
Event Triggers
The trigger engine provides event-driven automation. Triggers watch the kernel’s event bus and automatically send messages to agents when matching events arrive.
Creating a Trigger
curl -X POST http://localhost:4200/api/triggers \
-H "Content-Type: application/json" \
-d '{
"agent_id": "<agent-uuid>",
"pattern": "lifecycle",
"prompt_template": "A lifecycle event occurred: {{event}}",
"max_fires": 0
}'
Trigger Patterns
Pattern Description "all"Matches every event (wildcard) "lifecycle"Matches any lifecycle event (spawned, started, terminated) {"agent_spawned": {"name_pattern": "coder"}}Matches when an agent with name containing pattern is spawned "agent_terminated"Matches when any agent terminates or crashes "system"Matches any system event (health checks, quota warnings) {"system_keyword": {"keyword": "quota"}}Matches system events containing keyword "memory_update"Matches any memory change event {"memory_key_pattern": {"key_pattern": "config"}}Matches memory updates where key contains pattern {"content_match": {"substring": "error"}}Matches events whose description contains substring
Prompt Templates
When a trigger fires, {{event}} is replaced with a human-readable event description:
"Agent 'coder' (id: <uuid>) was spawned"
"Agent <uuid> terminated: shutdown requested"
"Quota warning: agent <uuid>, tokens at 85.0%"
"Health check failed: agent <uuid>, unresponsive for 30s"
Use Cases
Health Monitoring {
"pattern" : { "content_match" : { "substring" : "health check failed" }},
"prompt_template" : "ALERT: {{event}}. Investigate status of all agents."
}
Spawn Notifications {
"pattern" : { "agent_spawned" : { "name_pattern" : "*" }},
"prompt_template" : "New agent created: {{event}}. Update fleet roster."
}
Quota Alerts {
"pattern" : { "system_keyword" : { "keyword" : "quota" }},
"prompt_template" : "Quota event: {{event}}. Recommend action." ,
"max_fires" : 1
}
Memory Changes {
"pattern" : { "memory_key_pattern" : { "key_pattern" : "config" }},
"prompt_template" : "Config changed: {{event}}. Validate settings."
}
API Endpoints
Workflows
# Create workflow
POST /api/workflows
# List workflows
GET /api/workflows
# Execute workflow
POST /api/workflows/:id/run
# List workflow runs
GET /api/workflows/:id/runs
Triggers
# Create trigger
POST /api/triggers
# List triggers (optionally filter by agent)
GET /api/triggers?agent_id= < uui d >
# Enable/disable trigger
PUT /api/triggers/:id
# Delete trigger
DELETE /api/triggers/:id
CLI Commands
# List all workflows
openfang workflow list
# Create workflow from JSON file
openfang workflow create workflow.json
# Execute workflow
openfang workflow run < workflow-i d > "input text"
# List all triggers
openfang trigger list
# Create trigger
openfang trigger create < agent-i d > '"lifecycle"' --prompt "Event: {{event}}"
# Delete trigger
openfang trigger delete < trigger-i d >
Limits and Quotas
Run Eviction : The workflow engine retains a maximum of 200 workflow runs. Oldest completed/failed runs are evicted when this limit is exceeded.
Step Timeout : Default 120 seconds per step (configurable)
Loop Iteration Cap : Default 5 iterations (configurable)
Hourly Token Quota : Enforced per-agent via max_llm_tokens_per_hour
Next Steps
Creating Agents Build custom agents for your workflows
Event System Learn about the event bus architecture