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"]
}