Statewright
Workflows

Fork/Join

Split work into parallel branches, join when complete

Fork/Join

Fork transitions split work into parallel branches. Each branch runs independently through its own state sub-graph. When all branches complete, the join advances the parent to the next state.

Defining a Fork

Add a fork object to any transition event:

{
  "planning": {
    "on": {
      "FORK": {
        "fork": {
          "branches": {
            "lint": { "initial": "implementing", "terminal": "branch-done" },
            "test": { "initial": "implementing", "terminal": "branch-done" },
            "docs": { "initial": "implementing", "terminal": "branch-done" }
          },
          "join": "all",
          "on_complete": "review",
          "on_fail": "failed"
        }
      }
    }
  }
}

Branch Definition

Each branch specifies:

FieldDescription
initialState the branch starts in (must exist in the workflow)
terminalFinal state that signals branch completion

Branches share the workflow's state definitions. The initial state's allowed_tools, model, instructions, and thinking_level all apply to the branch.

Join Strategies

StrategyBehavior
allWait for every branch to complete (default)
anyFirst branch to complete triggers the join

How Agents Execute Forks

Sequential (Claude Code, Codex, OMX)

The agent works branches one at a time:

  1. statewright_transition(event="FORK") — creates branch sessions
  2. statewright_load_workflow(branch="lint") — enters the lint branch
  3. Work through the branch states
  4. statewright_transition(event="BRANCH_DONE:lint") — signal completion
  5. Repeat for next branch
  6. After all branches: gateway auto-joins to on_complete

Parallel (Pi)

Pi's statewright_fork tool spawns parallel subprocesses:

  1. Model calls statewright_fork with branch tasks
  2. Plugin fires the FORK transition
  3. One Pi subprocess per branch, each with its own gateway session
  4. Branches work simultaneously on local or API models
  5. Parent fires BRANCH_DONE:name for each completed branch
  6. Gateway auto-joins to on_complete

BRANCH_DONE Event Format

Always include the branch name after a colon:

statewright_transition(event="BRANCH_DONE:lint", data={"rationale": "lint passed"})

Per-Branch Model Routing

In Pi, branches inherit the initial state's model routing:

"implementing": {
  "model": "ollama-qwen/qwen3.6:35b",
  "thinking_level": "off",
  "allowed_tools": ["Read", "Edit", "Write", "Bash"]
}

Each branch subprocess switches to this model automatically.

Complete Example

Three-branch bugfix workflow: plan with a frontier model, fix three independent bugs in parallel on local models, run integration tests:

{
  "id": "parallel-bugfix",
  "initial": "planning",
  "meta": { "default_model": "openai-codex/gpt-5.4" },
  "states": {
    "planning": {
      "model": "openai-codex/gpt-5.5",
      "thinking_level": "xhigh",
      "allowed_tools": ["Read", "Grep", "Glob", "Bash"],
      "instructions": "Read all files, identify bugs, plan fixes. Then trigger FORK.",
      "on": {
        "FORK": {
          "fork": {
            "branches": {
              "fix-auth": { "initial": "implementing", "terminal": "done" },
              "fix-parser": { "initial": "implementing", "terminal": "done" },
              "fix-tests": { "initial": "implementing", "terminal": "done" }
            },
            "join": "all",
            "on_complete": "integration",
            "on_fail": "failed"
          }
        }
      }
    },
    "implementing": {
      "model": "ollama-qwen/qwen3.6:35b",
      "allowed_tools": ["Read", "Edit", "Write", "Bash"],
      "instructions": "Fix the assigned bug. Run relevant tests.",
      "on": { "DONE": "done", "FAIL": "failed" }
    },
    "done": { "type": "final" },
    "integration": {
      "model": "ollama/gemma4:31b",
      "allowed_tools": ["Read", "Bash"],
      "instructions": "Run full test suite. All tests must pass.",
      "on": { "PASS": "completed", "FAIL": "failed" }
    },
    "completed": { "type": "final" },
    "failed": { "type": "final" }
  }
}

On this page