Attractor × pi · user-centered handoff

What we built, explained from the user's point of view

User problem

  • You want to drive Attractor workflows from inside pi.
  • You want this to feel like a native pi capability, not a pile of ad hoc shell commands.
  • You want both the LLM and the human operator to be able to inspect and control runs.

What the solution gives the user

/attractor-run /attractor-list /attractor-show /attractor-resume /attractor-respond LLM-callable Attractor tools

The user sees pi talking to Attractor directly, while the implementation stays grounded in Attractor's stable Python host API.

Why an extension

Why this was built as a pi extension, not a skill

What a skill would do

  • Tell the model how to behave.
  • Explain repo rules, patterns, and reading order.
  • Improve judgment and procedure.

Good for workflow authoring guidance. Not enough for first-class runtime integration.

What the extension does

  • Adds new tools pi did not previously have.
  • Adds slash commands users can invoke directly.
  • Bridges TypeScript pi runtime to Python Attractor runtime.
  • Streams run events into a user-visible pi UI flow.

In user terms: a skill would only tell pi how to improvise Attractor operations; the extension makes those operations real.

User experience

The user journey this enables

1. Start pi in this repo
The project-local extension auto-loads.
2. Validate or run a workflow
Either via slash commands or LLM tool calls.
3. Watch progress in-context
Node starts, outcomes, gates, and summaries flow back into pi.
4. Pause and respond
Human gates become explicit user actions, not implicit prompt hacks.
5. Resume and inspect
The user can list runs, inspect one, respond, and continue.

Human benefits

  • Less memorizing of CLI syntax.
  • Less manual parsing of structured output.
  • Better visibility into paused runs and gate choices.
  • A cleaner mental model: pi controls Attractor.

Model benefits

  • Named tools with focused descriptions.
  • Structured parameters instead of shell-string improvisation.
  • Fewer chances to misuse the host API shape.
Implementation

Files added for the user-facing flow

pi extension

.pi/extensions/attractor/index.ts
.pi/extensions/attractor/README.md

This is the user-facing layer inside pi.

Python bridge

scripts/pi/attractor_bridge.py

This is the trusted translator between pi and the stable Attractor Python API.

Verification

tests/test_pi_bridge.py

This protects the user flow from validate through paused-gate resume.

Architecture

How the user experience is achieved

Runtime path

pi extension (TypeScript)
    ↓
uv run python scripts/pi/attractor_bridge.py
    ↓
from attractor import Engine, parse, validate, InputCopy, ...
    ↓
Attractor repo + worktrees + journals

Why users should care

  • The integration is not faking Attractor behavior with bash.
  • It uses Attractor's documented host surface.
  • That makes the behavior easier to reason about and easier to evolve.
  • The UI feels local and immediate, while the engine remains the source of truth.
Capabilities

What the user can now do

Human-invoked commands

  • /attractor-validate <workflow.dot>
  • /attractor-run <workflow.dot>
  • /attractor-list
  • /attractor-show <run-id>
  • /attractor-resume <run-id>
  • /attractor-respond <run-id> <choice> [reason]

LLM-invoked tools

  • attractor_validate_workflow
  • attractor_run_workflow
  • attractor_resume_run
  • attractor_respond_gate
  • attractor_list_runs
  • attractor_show_run
Protocol

How users see progress instead of silence

Bridge output shape

{"type":"event","event":"run_started",...}
{"type":"event","event":"node_started",...}
{"type":"event","event":"human_gate",...}
{"type":"result","command":"run",...}

User value

  • Long-running work does not feel like a black box.
  • Paused gate state becomes visible and actionable.
  • The extension can update a widget under the editor with recent activity.
  • The final result includes a compact summary, not just raw log noise.
Verification

What was checked on behalf of users

Automated checks

  • uv run pytest -q tests/test_pi_bridge.py
  • uv run ruff check scripts/pi/attractor_bridge.py tests/test_pi_bridge.py
  • uv run pyright scripts/pi/attractor_bridge.py

What the test covers

  • workflow validation
  • running a workflow
  • pausing at a human gate
  • listing and showing a run
  • responding to the gate
  • resuming to completion

That sequence mirrors how a real user would experience the integration.

Limitations

What users should know is not wired yet

  • Workflow positional arguments are not yet bridged through the extension.
  • This was intentional so the bridge would stay on the stable top-level Attractor API.
  • If you want user-facing support for workflow arguments next, the clean move is probably to promote the relevant helpers into the stable host API first.
Use it

What the user can do now

Interactive flow

pi
/reload
/attractor-validate workflows/tool-only.dot
/attractor-run workflows/tool-only.dot
/attractor-list
/attractor-show <run-id>

Bottom line

This version is written to center the user's experience:

  • What problem is solved?
  • What commands appear?
  • What progress can the user see?
  • How does a paused run get resumed?
  • What remains outside the current UX?