Skip to content

[Feature] Add Pi support via interactive extension bridge and CLI runtime backend #1139

@devkade

Description

@devkade

Problem

Ouroboros currently does not have a first-class Pi integration path.

A generic “Pi support” request is ambiguous because Pi can be integrated in two different ways:

  1. From inside an interactive Pi session, where a user wants to invoke Ouroboros workflows such as ooo interview, ooo run, or ooo status.
  2. From Ouroboros itself, where Pi should act as a headless CLI runtime backend for task execution.

These are different transport and lifecycle contracts. If they are not separated, Pi support may accidentally conflate interactive extension behavior with subprocess runtime behavior, leading to unclear setup, recursive dispatch, duplicated workflow semantics outside Ouroboros core, or a runtime backend without a clear event normalization contract.

Why now

Pi already exposes enough surface to support both integration paths:

  • Pi has an extension/session model suitable for interactive command projection.
  • Pi does not currently provide native MCP support, so an explicit bridge layer is needed for MCP workflows.
  • Pi CLI supports machine-readable output through pi -p --mode json, which emits JSONL events suitable for a subprocess runtime backend.
  • Ouroboros already has comparable patterns through Codex CLI runtime support and OpenCode’s split between interactive plugin integration and headless subprocess runtime support.

Defining the architecture now would prevent a partial Pi integration from growing in the wrong direction.

User / persona

This affects users who want to:

  • use Ouroboros workflows naturally from inside Pi;
  • run ooo workflows through Pi without manually switching tools;
  • use Pi as an Ouroboros execution runtime;
  • preserve Ouroboros session/job/seed/execution semantics while using Pi as either the host or backend.

Current behavior

Today, Pi is not a first-class Ouroboros runtime or interactive integration target.

In particular:

  • Pi sessions do not have a documented ooo command projection path into Ouroboros MCP tools.
  • Pi lacks native MCP support, so an explicit bridge contract is required.
  • Ouroboros does not have a PiCliRuntime equivalent to existing CLI runtime backends.
  • Pi JSONL events are not normalized into Ouroboros AgentMessage / RuntimeHandle values.
  • There is no documented boundary between interactive Pi extension behavior and headless Pi subprocess execution.
  • The runtime capability matrix and runtime guides do not describe Pi as a supported or planned backend.

Desired behavior

Ouroboros should support Pi through two explicit integration paths.

1. Interactive Pi extension bridge

Users should be able to invoke Ouroboros workflows from inside a Pi session:

User in Pi
  → exact `ooo ...` command
  → pi-ouroboros extension
  → pi-mcp-porter generic MCP bridge
  → Ouroboros MCP tools / core workflow state
  → Pi session projection

This path should support commands such as:

ooo help
ooo interview <goal>
ooo seed <session>
ooo run <seed>
ooo status <id>
ooo cancel <id>

Pi-visible output should preserve canonical Ouroboros identifiers such as:

session_id
seed_id
job_id
execution_id

2. Pi CLI runtime backend

Ouroboros should be able to use Pi as a headless task execution runtime:

Ouroboros executor
  → PiCliRuntime.execute_task(prompt)
  → pi -p --mode json
  → Pi JSONL event stream
  → PiEventNormalizer
  → Ouroboros AgentMessage / RuntimeHandle

The initial CLI backend should use:

pi -p --mode json

not pi --mode rpc.

pi --mode rpc is richer and may be useful later for a long-lived controller, but it should not be the initial subprocess runtime contract.

Proposed solution

Add a Pi support design with two separate implementation lanes.

Interactive extension bridge

Introduce or document:

  • pi-mcp-porter as a generic Pi ↔ MCP bridge substrate;
  • pi-ouroboros as the Ouroboros-specific Pi extension/projection layer.

Responsibilities:

  • detect exact ooo commands in Pi sessions;
  • call Ouroboros MCP tools through pi-mcp-porter;
  • preserve Ouroboros lifecycle identifiers;
  • render Pi-friendly results, statuses, diagnostics, and errors;
  • avoid reimplementing Ouroboros workflow logic inside the Pi extension.

CLI runtime backend

Add a PiCliRuntime that invokes Pi in isolated JSON print mode.

Initial command shape:

pi \
  -p \
  --mode json \
  --no-extensions \
  --no-skills \
  --no-prompt-templates \
  --no-themes

Prompt delivery should prefer stdin where possible to avoid command-line length limits:

printf '%s' "$PROMPT" | pi -p --mode json

Add a PiEventNormalizer that maps Pi JSONL events into Ouroboros runtime messages.

Expected Pi event types include:

session
agent_start
turn_start
message_start
message_update
message_end
turn_end
agent_end

The session.id field should become the native Pi runtime session identifier in RuntimeHandle.

Example mapping:

RuntimeHandle(
  backend="pi",
  kind="agent_runtime",
  native_session_id=<Pi session id>,
  cwd=<working directory>
)

Final result extraction can initially prefer turn_end.message, with agent_end.messages as a fallback.

Documentation updates required

If this feature adds a new runtime backend or CLI/config surface, it should follow the contributor documentation coverage rules.

Expected documentation updates include:

  • docs/runtime-capability-matrix.md — add Pi as a runtime row with accurate capability status.
  • docs/runtime-guides/pi.md — create a Pi runtime guide.
  • docs/cli-reference.md — update --runtime option description if pi becomes a supported value.
  • docs/getting-started.md — update prerequisites/setup if Pi or pi-mcp-porter installation is required.
  • README.md — review quick-start/config snippets if the new runtime changes day-one setup.
  • Any setup or MCP bridge behavior should also be reflected in the relevant setup/MCP documentation if new commands or config keys are added.

Constraints

  • Pi should not be treated as if it has native MCP support.
  • pi-mcp-porter should remain a generic MCP bridge, not an Ouroboros-specific integration.
  • pi-ouroboros should remain a Pi projection/command layer, not a reimplementation of Ouroboros.
  • Interactive Pi extension loading should be disabled in headless PiCliRuntime execution by default to avoid double dispatch or recursion.
  • The initial CLI runtime backend should use pi -p --mode json.
  • pi --mode rpc should be reserved for later controller-style integration unless there is a strong reason to start there.
  • Tool permissions should be conservative by default.
  • Docs must not list Pi as a working runtime until create_agent_runtime() actually supports it and no NotImplementedError/placeholder behavior remains.
  • If a new CLI flag, config key, or setup behavior is added, the matching docs must be updated in the same change or explicitly tracked.

Suggested initial tool policy mapping:

Ouroboros policy Pi CLI behavior
no tools --no-tools
read-only --tools read,grep,find,ls
workspace-write --tools read,grep,find,ls,edit,write
shell-enabled add bash only when explicitly allowed

Non-goals

  • Do not fork or reimplement Ouroboros core workflows.
  • Do not make Pi-local state the source of truth for Ouroboros sessions/jobs.
  • Do not assume Pi has native MCP support.
  • Do not make pi-mcp-porter Ouroboros-specific.
  • Do not load pi-ouroboros inside headless PiCliRuntime subprocesses by default.
  • Do not use pi --mode rpc as the initial runtime backend contract.
  • Do not require full OpenCode-style task-pane/subagent UI parity in the first interactive bridge.
  • Do not enable shell/write tools by default in the Pi runtime backend.
  • Do not document Pi as generally available until the runtime and/or extension path is actually implemented and verified.

Alternatives considered

Only implement interactive Pi extension support

This would let Pi users call Ouroboros from inside Pi, but it would not let Ouroboros use Pi as a headless execution runtime. That would leave Pi behind Codex/OpenCode-style runtime support.

Only implement Pi CLI runtime backend

This would support headless execution but would not solve the Pi session UX problem. Users inside Pi would still lack a natural ooo workflow bridge.

Use pi --mode rpc as the first runtime backend contract

RPC mode is more powerful, but it introduces significantly more lifecycle complexity:

  • persistent subprocess management;
  • JSONL stdin writer;
  • command ID correlation;
  • prompt accepted vs prompt completed distinction;
  • abort/follow-up/steering mapping;
  • shutdown handling;
  • extension UI request/response handling.

For the first runtime backend, pi -p --mode json better matches the existing subprocess runtime pattern used by other runtimes.

Reimplement Ouroboros workflow behavior inside Pi

This would make Pi integration more independent, but it would duplicate core workflow semantics and risk divergence. Ouroboros should remain the source of truth.

Acceptance criteria

  • The design clearly separates interactive Pi extension bridge from Pi CLI runtime backend.
  • pi-mcp-porter is treated as a generic MCP bridge substrate.
  • pi-ouroboros is treated as the Ouroboros-specific Pi command/projection layer.
  • Interactive Pi support documents exact ooo command routing.
  • Pi-visible interactive output preserves canonical Ouroboros IDs such as session_id, seed_id, job_id, and execution_id.
  • PiCliRuntime uses pi -p --mode json as the initial subprocess runtime contract.
  • pi --mode rpc is documented as future controller work, not the initial backend.
  • Headless Pi runtime execution disables interactive extension surfaces by default.
  • Pi JSONL events are normalized into Ouroboros AgentMessage and RuntimeHandle values.
  • session.id from Pi JSON output is captured as the native Pi runtime session identifier.
  • Final assistant output is extracted from turn_end.message or agent_end.messages.
  • Runtime errors, malformed JSON, missing binaries, and setup failures produce actionable diagnostics.
  • Tests or fixtures cover Pi JSON event normalization and final result extraction.
  • No Ouroboros core workflow semantics are reimplemented inside Pi extension or runtime adapter code.
  • If pi is added as a runtime backend, docs/runtime-capability-matrix.md includes an accurate Pi row.
  • If pi is added as a runtime backend, docs/runtime-guides/pi.md exists.
  • If pi becomes a valid --runtime value, docs/cli-reference.md documents it.
  • docs/getting-started.md documents any required Pi / pi-mcp-porter prerequisites.
  • Docs do not present Pi as fully available while implementation remains a placeholder or raises NotImplementedError.

References

Comparable existing patterns:

  • Existing Codex support demonstrates a CLI runtime backend pattern.
  • Existing OpenCode support demonstrates the need to separate interactive host integration from subprocess/headless runtime execution.
  • Pi’s --mode json provides a JSONL event stream suitable for an initial PiCliRuntime.
  • Pi’s --mode rpc provides a richer bidirectional protocol that may be useful for later controller-style integration.
  • CONTRIBUTING.md requires new runtime backends to update runtime capability docs, runtime guides, CLI reference, and getting-started prerequisites.

Checklist

  • I searched existing issues and discussions first.
  • I explained the problem, not just the solution.
  • I included clear scope boundaries and non-goals.
  • I listed concrete acceptance criteria.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or meaningful improvementneeds-designMulti-PR epic or architectural change, needs human planning

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions