pi-procedural-graphs
Procedural Graph extension for pi: self-evolving, graph-structured procedural memory that injects step-level guidance at every decision step. Based on arXiv:2609.09153.
Package details
Install pi-procedural-graphs from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-procedural-graphs- Package
pi-procedural-graphs- Version
0.1.0- Published
- Sep 10, 2026
- Downloads
- 128/mo · 128/wk
- Author
- leftwinglautus
- License
- MIT
- Types
- extension
- Size
- 79.1 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-procedural-graphs
A pi extension implementing the Procedural Graph framework from arXiv:2609.09153 — Procedural Graphs: Self-Evolving Execution Structures for LLM Agents.
A Procedural Graph organizes procedural knowledge — what to do, in what order, under which
conditions — as directed, attributed triplets (procedure --relation--> procedure), each edge
carrying condition, guidance, and pitfalls. At every decision step pi's context hook
localizes the agent's active node, extracts its h-hop neighborhood, and injects it as
step-level situational guidance that biases the next action without dictating it. After batches
of verdict-bearing tasks, an LLM refiner proposes topology/attribute edits; candidates must pass
structural validation and a configurable validation gate, and rejected candidates are kept as
negative evidence (rejection memory) so the refiner does not repeat them.
It is fully self-contained: state lives in .pi/procedural-graph.json on disk. It does not
depend on magic-context or any other extension, and composes fine with them (each context
handler adds its own block).
Install
# from npm (once published)
pi install npm:pi-procedural-graphs
# or from this repo directly
pi install /path/to/pi-procedural-graphs
To try without installing (current run only):
pi -e /path/to/pi-procedural-graphs
The package manifest (pi.extensions → ./src/index.ts) is read automatically. Extensions run
with full permissions — review src/ before installing a third-party copy.
First run
The extension auto-creates a small neutral skeleton graph on the first session. You can replace it at any time:
/pg init— recreate the neutral skeleton/pg init --scratch— minimal graph (justStart)/pg init --expert path/to/graph.json— import your own graph (must satisfy the schema below)/pg reset— back to skeleton (keeps history),/pg reset --historyalso clears history
How it maps to the paper
| Paper (Section 3) | This extension |
|---|---|
Graph G = (V, R, E, Φ), edges (u, r, v) with condition/guidance/pitfalls |
ProceduralGraph in src/graph.ts |
locate: u_t = Match(a_{t-1}, V) |
last tool call name matched to node tool:<name> (or exact id / label) |
extract: h-hop neighborhood 𝒩_h(u_t), full graph on miss |
neighborhood(g, node, hops), injectOnMiss config |
generate: g_t = Ψ(𝒢_t, q, 𝒯_{t-w:t}) |
inject mode = raw subgraph; llm mode = separate guidance-model call (modelRegistry.complete, same LLM as solver — as in the paper) |
solver a_t ~ P_solver(q, 𝒯_t, g_t) |
pi's main loop; guidance appended via the context event before each LLM call |
| Self-evolution: diagnostic rollout → mutation → validation gate → rejection memory | src/evolution.ts; verdict-bearing task batches, LLM refiner, structural validity, optional validationCommand, rejection memory |
Defaults match the paper: hops: 2, window: 3. Raw injection is not a hack — the paper's
usage ablation (Table 3) explicitly compares raw full-graph injection vs generative
guidance.
Configuration
Optional per-project file .pi/procedural-graph.config.json (everything is optional; shown with
defaults):
{
"enabled": true,
"graphFile": ".pi/procedural-graph.json",
"guidance": {
"mode": "inject",
"hops": 2,
"window": 3,
"maxTokens": 400,
"injectOnMiss": true,
"maxGraphNodesForFullInjection": 20
},
"evolution": {
"batchSize": 5,
"minBatchForForce": 2,
"autoApprove": false,
"validationCommand": null,
"refinerMaxTokens": 2000,
"maxTrajectoryTokens": 8000,
"maxRejectionMemories": 10
},
"verdict": {
"command": null,
"autoFailOnError": false
}
}
guidance.mode:inject(free) orllm(separate distillation call per step — faithful to the paper's generative guidance, costs tokens + latency).evolution.validationCommand: your held-out validation proxy. A shell command run with cwd = project and envPG_CANDIDATE_FILEpointing at the candidate graph JSON (andPG_GRAPH_FILEat the current graph). Exit 0 = pass → candidate is committed; non-zero = fail → candidate goes to rejection memory. WithautoApprove: falseit is also run by/pg reviewto inform your accept/reject decision.verdict.command: a shell command that derives a task verdict at task end. Exit 0 = success, non-zero = fail. Leavenullto mark verdicts manually with/pg verdict.
Commands
| Command | What it does |
|---|---|
/pg |
Status: graph size, mode, active node, injection/evolution stats, pending tasks |
/pg graph |
Print the graph; /pg graph --localize shows the current neighborhood |
/pg task start [name] |
Explicit task start (usually unnecessary — user prompts auto-start tasks) |
/pg task done --verdict success|fail|score:N |
End current task with a verdict |
/pg verdict success|fail|score:N [note] |
Mark the active task's outcome (used by the refiner) |
/pg evolve |
Run the refiner on pending verdict-bearing tasks; /pg evolve --force runs with fewer than a full batch |
/pg review |
Show the staged candidate diff (+ run validationCommand if set) |
/pg accept [note] |
Commit the staged candidate |
/pg reject [reason] |
Reject the staged candidate into rejection memory |
/pg edit add-node … |
Manual graph editing (minimal mode without the refiner) |
/pg disable / /pg enable |
Toggle guidance injection (persisted to config) |
/pg export [path] |
Export the graph JSON |
/pg reset [--history] |
Replace the graph with the skeleton (confirm required) |
/pg edit syntax:
/pg edit add-node step:check_tests --kind step --label "Check tests"
/pg edit add-edge tool:edit leads_to step:check_tests --guidance "Run the affected test file"
/pg edit add-edge tool:bash if_failed state:needs_verification --pitfalls "Don't blindly rerun"
/pg edit revise-edge tool:bash if_failed state:needs_verification --guidance "Read the error first"
/pg edit delete-node step:obsolete
/pg edit delete-edge tool:read leads_to tool:edit
The extension also registers a pg_status tool the model can call to inspect the active
procedural context.
How the loop works day-to-day
- You work as usual. Each user prompt starts a task; tool calls/observations are tracked silently.
- Before every LLM call, the localized subgraph is injected as
<procedural-guidance>context (marked as automatic, not a user message). - When a task finishes, give it a verdict:
/pg verdict successor/pg verdict fail(or configureverdict.commandto automate it). - After
evolution.batchSizeverdict-bearing tasks accumulate, the refiner runs: it contrasts successes vs failures and proposes edits. Candidates are staged:/pg reviewto inspect, then/pg acceptor/pg reject;- or configure
evolution.autoApprove/validationCommandto automate the gate.
Graph JSON schema
.pi/procedural-graph.json wraps the graph with history/rejection/staging state. The graph
portion:
{
"version": 1,
"name": "default",
"nodes": [
{ "id": "Start", "kind": "step", "label": "Start" },
{ "id": "tool:bash", "kind": "tool" }
],
"edges": [
{
"id": "tool:edit --leads_to--> tool:bash",
"source": "tool:edit",
"relation": "leads_to",
"target": "tool:bash",
"attrs": {
"condition": "After modifying code.",
"guidance": "Run the relevant tests or a build to verify your change.",
"pitfalls": "Do not claim success without verification."
}
}
]
}
Node kinds: tool (id tool:<name> matching a pi tool name), step, state. Relations are
free-form; the skeleton uses leads_to, if_failed, and requires.
Validation (safe — won't disturb running sessions)
This extension is designed to be validated in an isolated project so running pi sessions are
untouched. Nothing here touches ~/.pi/agent/settings.json or any running session.
Step 0 — pure logic (no pi at all):
cd /path/to/pi-procedural-graphs
npm install # dev deps only, writes just this repo's node_modules
npm run smoke # exercises graph/evolution core in memory + /tmp
Step 1 — one disposable pi session:
mkdir -p /tmp/pg-test && cd /tmp/pg-test
git init -q
pi -e /path/to/pi-procedural-graphs/src/index.ts # try once; nothing installed globally
(-e loads the extension file for the current run only. Alternatively pi install -l /path/to/pi-procedural-graphs inside the disposable project writes only that project's
.pi/settings.json.)
Inside that disposable session:
/pg status— expect the skeleton graph (9 nodes / 13 edges) andinject:0.- Ask pi to do a small task (read a file, edit something, run a check).
pg_statusshould show a matched active node andinjectionsincreasing on/pg status. /pg verdict success, then/pg evolve --force— expect a staged proposal./pg review→/pg acceptor/pg reject.- Inspect
.pi/procedural-graph.jsonafterwards.
Because -e loads the extension for that run only (and install -l writes only the disposable
project's settings), your global settings and other sessions are never modified. The extension
writes only .pi/procedural-graph*.json files inside the project directory.
Known differences from the paper
- Validation gate: the paper gates on held-out benchmark scores. Here the gate is your
validationCommand(a shell proxy) or explicit user review. Without a scoring harness the extension cannot measure held-out performance on its own. - Localization: exact-match on tool names, plus a
Startmarker — the paper'sMatchis also exact-match, so this is close, but pi's open-ended tasks have no fixed action grammar. - Batch/session semantics: "training tasks" are pi sessions/tasks with user-provided verdicts; the paper uses curated benchmark splits.
- No weight updates: like the paper, all learning is graph edits; no model retraining.
Publishing
npm publish # requires an npm account; package is "pi-procedural-graphs"
pi install npm:pi-procedural-graphs
License
MIT