Skip to content

wenkil/pi-plan-runtime

Repository files navigation

pi-plan-runtime

Agentic Plan Execution Runtime for Pi Coding Agent

简体中文

pi-plan-runtime is a source-level PlanSpec execution runtime exclusively built for [@mariozechner/pi-coding-agent](https://www.npmjs.com/package/@mariozechner/pi-coding-agent).

When should you use this? If your AI project already implements its own product UI, user confirmation flows, and business logic, and you only need a pure, reusable, topology-based execution engine for multi-step Agent tasks, then pi-plan-runtime is exactly what you need. It strips away business state and focuses entirely on reliable task execution.

✨ Features

  • 🔄 Flexible Scheduling: Supports complex task topologies with both serial and parallel execution modes.
  • 🧩 Seamless Integration: Designed directly for @mariozechner/pi-coding-agent with a drop-in source-level integration pattern.
  • 🧠 Built-in State Recovery: Ships with MemoryRuntimeStore, natively supporting task suspension and user input (waiting_user).
  • 🛡️ 100% Type-Safe: Written in TypeScript with rigorous protocol and schema validation powered by Zod.
  • 📂 Standardized Handoff: Automatically manages context dependencies and file handoffs between execution steps.

Architecture

flowchart TB
  subgraph hostApp["Host application"]
    direction LR
    planSpec["PlanSpec<br/>(host-created and confirmed)"]
    hostCalls["Host calls<br/>runPlan / cancelRun / resumeStepWithInput / getState"]
    hostEvents["Consumes RuntimeEvent<br/>(optional sink)"]
    planSpec --> hostCalls
  end

  subgraph runtime["pi-plan-runtime"]
    direction LR
    sessionFactory["Pi session factory<br/>+ step prompts"]
    runtimeCore["Runtime orchestration<br/>schedule (serial / parallel,<br/>maxConcurrency)"]
    handoffWriter["Handoff writer"]
  end

  store[("RuntimeStoreAdapter<br/>MemoryRuntimeStore / custom implementation")]
  piAgent["Pi Coding Agent<br/>(per-step sessions)"]
  workspace[("Workspace<br/>.pi-plan-runtime/handoff/...")]

  hostCalls -->|"PlanSpec / user input / queries"| runtimeCore
  runtimeCore -->|"sink.emit(event)"| hostEvents

  runtimeCore -->|"write run / plan / step / handoff / event"| store
  store -->|"getRunnableSteps / getHandoff"| runtimeCore

  runtimeCore -->|"StepExecutionInput<br/>(with dependency HandoffDescriptors)"| sessionFactory
  sessionFactory -->|"create and prompt"| piAgent
  piAgent -->|"StepResult JSON<br/>completed / failed / cancelled / waiting_user"| runtimeCore

  runtimeCore --> handoffWriter
  handoffWriter -->|"result.json / raw_output.txt"| workspace

  piAgent -.->|"read dependency files<br/>via read / bash tools"| workspace

  piAgent ~~~ workspace
Loading

This diagram shows the runtime boundary rather than a fixed three-step pipeline: the host provides the PlanSpec, the runtime relies on the store to schedule dependency-ready steps, each step runs in its own Pi session, and handoff is delivered to downstream steps in two layers — descriptors via the store and actual files in the workspace. Events are both persisted to the store and pushed to the host's optional sink.

Compatibility

This version is tested against and pins @mariozechner/pi-coding-agent@0.72.1.

Pi 0.72.1 uses tool-name allowlists in createAgentSession({ tools }). Runtime examples therefore pass built-in tool names such as "read" and "bash", not constructed tool objects.

What It Adds to Pi Coding Agent

pi-plan-runtime executes a host-provided PlanSpec with one full-capability Pi agent configuration.

The runtime does not generate plans, ask users to confirm plans, define roles, route by capability, or own business state. The host project owns plan creation, plan IDs, user confirmation, plan versioning, and durable product records.

Source-Level Integration

Add the runtime source to a Pi project:

your-project/
  .pi/
  src/
    pi-plan-runtime/   # pi-plan-runtime source

Import from the source path used by the project:

import { createPiPlanRuntime, MemoryRuntimeStore } from "./pi-plan-runtime";

For a minimal host integration example, see docs/INTEGRATION.md.

Runtime Example

import {
  createPiPlanRuntime,
  MemoryRuntimeStore,
  type PlanSpec,
} from "./pi-plan-runtime";

const runtime = createPiPlanRuntime({
  piConfigRoot: "/absolute/path/to/.pi",
  workspaceRoot: "/absolute/path/to/workspace",
  model: {
    provider: "your-pi-provider-name",
    id: "your-model-id",
  },
  thinkingLevel: "off",
  tools: ["read", "bash", "edit", "write", "grep", "find", "ls"],
  stepSystemPrompt: [
    "You are the execution agent for one plan step.",
    "Use the project skills and tools to complete the current step.",
  ].join("\n"),
  store: new MemoryRuntimeStore(),
  scheduler: {
    mode: "serial",
    maxConcurrency: 1,
  },
});

const plan: PlanSpec = {
  id: "deck-plan",
  title: "Create a product pitch deck",
  summary: "Create a 5-slide product pitch deck from host-approved requirements.",
  executionMode: "serial",
  steps: [
    {
      id: "outline",
      title: "Draft outline",
      goal: "Create the deck outline.",
      dependsOn: [],
    },
    {
      id: "slides",
      title: "Create slides",
      goal: "Create slide content and assets from the approved outline.",
      dependsOn: ["outline"],
    },
  ],
};

const run = await runtime.runPlan({
  runId: "host-run-id",
  plan,
  metadata: {
    projectId: "host-project-id",
  },
});

// Optional: cancel a run (or a specific plan in that run) from the host side.
await runtime.cancelRun({
  runId: run.runId,
  planId: run.planId,
});

PlanSpec Contract

The host passes a PlanSpec directly to runPlan.

{
  "id": "plan-id",
  "title": "Plan title",
  "summary": "Plan summary",
  "executionMode": "serial",
  "steps": [
    {
      "id": "step-1",
      "title": "Step title",
      "goal": "Step goal",
      "dependsOn": []
    }
  ]
}

Valid execution modes are:

  • serial: runs one dependency-ready step at a time.
  • parallel: runs dependency-ready steps concurrently up to maxConcurrency.

Schemas are intentionally permissive. Caller-owned fields such as role, capability, executor, priority, or owner are preserved and passed through as step context. The runtime does not interpret them.

Step Result Contract

Each step Pi session must return exactly one JSON object:

  • completed: the step finished.
  • failed: the step failed.
  • cancelled: the step was cancelled by the host.
  • waiting_user: the step requires structured user input before it can continue.

For waiting_user, the result must include inputRequest. The runtime stores the waiting state and can continue with:

await runtime.resumeStepWithInput({
  planId,
  stepId,
  values: {
    topic: "Updated source material",
  },
});

When the host calls cancelRun(...), the runtime marks non-terminal steps as cancelled and attempts to abort in-flight step sessions.

Runtime Event Additions

In addition to existing events, the runtime now emits:

  • run.cancelled: the run was cancelled.
  • plan.cancelled: the plan was cancelled.
  • step.cancelled: the step was cancelled.
  • step.context: emitted before step execution, carrying StepExecutionInput (including dependency handoffs, workspace, metadata, and user input).

Handoff

After a completed step, the runtime writes handoff files under the workspace:

.pi-plan-runtime/handoff/<planId>/<stepId>/
  result.json
  raw_output.txt

Dependent steps receive handoff descriptors in their step execution context. The generated step prompt instructs the Pi agent to read dependency handoff files before doing substantial work.

Main Exports

  • createPiPlanRuntime
  • MemoryRuntimeStore
  • createDefaultPiSessionFactory
  • createPiSessionEventBridge
  • Protocol schemas and types: PlanSpec, PlanStepSpec, StepExecutionInput, StepResult, RuntimeEvent, HandoffDescriptor, PiPlanCancelResult

Current V1 Limits

  • Only serial and parallel are valid execution modes.
  • No planner, quick-answer, or user-confirmation flow is included.
  • No business role, capability, or executor routing is implemented.
  • No database store is included; use MemoryRuntimeStore or implement RuntimeStoreAdapter.

Development

npm install
npm run typecheck
npm test

License

MIT

About

A dedicated Plan Execution Runtime for Pi Coding Agent. Pure, reusable, and source-first engine for scheduling multi-step agent workflows in serial or parallel without business state coupling.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors