Attractor (Pipeline Engine)
Attractor is an agent-driven workflow engine that runs multi-step workflows defined as DOT graphs. Each node is a task; edges define the execution order. Nodes can be assigned personas, AI clients, prompts, and quality gates.
DOT pipeline files are complex and not intended to be hand-authored. When a user needs a pipeline, they ask an agent to generate the DOT file based on a high-level description of the desired workflow. The agent uses the pipeline specification to produce the correct graph.
Validate a Pipeline
$ recalletta attractor validate pipeline.dot
Checks the graph for structural errors (missing start/exit, unreachable nodes, invalid attributes) and warnings (goal gates without retry targets):
$ recalletta attractor validate simple_linear.dot
✓ Pipeline is valid: 4 nodes, 3 edges
$ recalletta attractor validate crew_pipeline.dot
⚠ [WARNING] goal_gate_has_retry: Node with goal_gate=true has no retry_target (node: test) [fix: Add retry_target attribute]
✓ 1 warning(s), no errors
Show Pipeline Structure
$ recalletta attractor show pipeline.dot
Prints all nodes, their types, attributes, and edges:
$ recalletta attractor show parallel.dot
Pipeline: Parallel
Goal: Build a music player
Size: 9 nodes, 10 edges
Nodes:
start "Start" [start]
plan "Plan" [codergen]
prompt: Plan the architecture
parallel_impl "Parallel Implementation" [parallel]
audio_engine "Audio Engine" [codergen]
prompt: Implement audio playback
ui_shell "UI Shell" [codergen]
prompt: Implement the user interface
playlist "Playlist" [codergen]
prompt: Implement playlist management
fan_in "Merge Results" [parallel.fan_in]
integrate "Integrate" [codergen]
prompt: Wire all modules together
exit "Exit" [exit]
Edges:
start → plan
plan → parallel_impl
parallel_impl → audio_engine
parallel_impl → ui_shell
parallel_impl → playlist
audio_engine → fan_in
ui_shell → fan_in
playlist → fan_in
fan_in → integrate
integrate → exit
Run a Pipeline
$ recalletta attractor run [OPTIONS] <FILE>
| Option | Default | Purpose |
|---|---|---|
--backend <BACKEND> |
sim |
Execution backend: sim (simulation), crew, none |
--goal <GOAL> |
from graph | Override the pipeline goal |
--resume <DIR> |
Resume from a previous run directory | |
--logs-dir <DIR> |
auto | Output logs directory |
Backends:
| Backend | What it does |
|---|---|
sim |
Simulates execution without spawning real agents. Useful for testing pipeline structure. |
crew |
Executes via the crew system — summons real agents into tmux sessions for each node. |
none |
Parses and validates the graph only. No execution. |
Example:
$ recalletta attractor run --backend crew pipeline.dot
$ recalletta attractor run --backend sim --goal "Build a REST API" pipeline.dot
To resume a pipeline that was interrupted:
$ recalletta attractor run --resume ./attractor-logs/2026-02-09_14-30-00 pipeline.dot
DOT Syntax Reference
Pipelines are standard DOT digraphs with custom node and edge attributes.
Graph Attributes
digraph MyPipeline {
graph [goal="Build a REST API with JWT authentication"]
rankdir=LR
}
| Attribute | Purpose |
|---|---|
goal |
The pipeline's overall objective. Referenced as $goal in node prompts. |
retry_target |
Default node to retry on goal gate failure |
Node Types
Node type is determined by the shape attribute:
| Shape | Type | Purpose |
|---|---|---|
Mdiamond |
Start | Entry point. Every pipeline needs exactly one. |
Msquare |
Exit | Terminal node. Pipeline ends here. |
box (default) |
Codergen | A task node. Runs an AI agent with the given prompt. |
component |
Parallel | Fan-out point. All outgoing edges execute concurrently. |
tripleoctagon |
Fan-in | Merge point. Waits for all incoming parallel branches, then merges results. |
hexagon |
Human review | Pauses for human input. Presents labeled edges as choices. |
diamond |
Decision | Conditional routing based on outcome. |
Node Attributes
implement [
label="Implement Auth",
persona="forge",
client="claude",
prompt="Implement JWT authentication for $goal",
goal_gate=true,
retry_target="implement",
timeout="900s"
]
| Attribute | Purpose |
|---|---|
label |
Display name for the node |
prompt |
The task prompt sent to the agent. Supports $goal substitution. |
persona |
Crew persona to use (e.g., forge, circuit, harbor) |
client |
AI client override: claude, codex, or gemini |
goal_gate |
When true, the node's outcome is evaluated. Failure triggers retry. |
retry_target |
Which node to retry on goal gate failure. Defaults to graph-level retry_target. |
timeout |
Node execution timeout (e.g., 900s, 30m) |
type |
Explicit type override (e.g., wait.human) |
Edge Attributes
review_gate -> ship_it [label="[A] Approve"]
review_gate -> fixes [label="[F] Fix"]
test -> review [condition="outcome=success"]
test -> implement [condition="outcome=fail"]
| Attribute | Purpose |
|---|---|
label |
Display label. For human review nodes, labels become selectable choices. |
condition |
Conditional routing expression (e.g., outcome=success, outcome!=success) |
Pipeline Patterns
Linear
The simplest pattern. Tasks execute in sequence.
digraph Simple {
graph [goal="Run tests and report results"]
start [shape=Mdiamond]
exit [shape=Msquare]
run_tests [prompt="Run the test suite and report results"]
report [prompt="Summarize the test results"]
start -> run_tests -> report -> exit
}
Parallel Fan-Out / Fan-In
A component node fans out to concurrent branches. A tripleoctagon node waits for all branches to complete, then merges their results.
Fan-in merge is deterministic: branches are merged in alphabetical order by branch ID, with results namespaced as branch.<branch_id>.<key>.
parallel_impl [shape=component]
audio_engine [prompt="Implement audio playback"]
ui_shell [prompt="Implement the user interface"]
fan_in [shape=tripleoctagon]
parallel_impl -> audio_engine
parallel_impl -> ui_shell
audio_engine -> fan_in
ui_shell -> fan_in
Goal Gates with Retry
A node with goal_gate=true evaluates whether its task succeeded. On failure, execution loops back to retry_target.
implement [prompt="Write the code"]
test [prompt="Run all tests", goal_gate=true, retry_target="implement"]
start -> implement -> test -> review -> exit
If tests fail, execution returns to implement and the cycle repeats.
Human Review Gates
A hexagon node (or type="wait.human") pauses the pipeline and presents edge labels as choices to a human operator.
review_gate [shape=hexagon, label="Review Changes"]
review_gate -> ship_it [label="[A] Approve"]
review_gate -> fixes [label="[F] Fix"]
fixes -> review_gate
Crew Pipeline (Full Example)
A complete pipeline with persona assignments, parallel execution, goal gates, human review, and conditional edges:
digraph CrewPipeline {
graph [goal="Build a REST API with JWT authentication"]
start [shape=Mdiamond]
requirements [persona="beacon", prompt="Break down $goal into requirements"]
architecture [persona="keystone", prompt="Design the system architecture"]
human_review [shape=hexagon, label="Review architecture?"]
parallel_impl [shape=component]
auth_module [persona="forge", prompt="Implement JWT authentication", client="claude"]
api_routes [persona="circuit", prompt="Implement API routes", client="codex"]
fan_in [shape=tripleoctagon]
integrate [persona="circuit", prompt="Wire all modules together", client="codex"]
test [persona="drift", prompt="Write and run tests", client="codex", goal_gate=true]
review [persona="harbor", prompt="Review the full codebase", client="claude"]
done [shape=Msquare]
start -> requirements -> architecture -> human_review
human_review -> parallel_impl [label="[A] Approved"]
human_review -> architecture [label="[R] Revise"]
parallel_impl -> auth_module
parallel_impl -> api_routes
auth_module -> fan_in
api_routes -> fan_in
fan_in -> integrate -> test
test -> review [condition="outcome=success"]
test -> integrate [condition="outcome=fail"]
review -> done [label="approved"]
review -> integrate [label="rejected"]
}