Local actor kernel for Pi.
pi-actors turns trusted local programs, scripts, services, pipelines, recipes, and sub-agents into addressable actors that Pi can spawn, steer, inspect, and reuse. It is the bridge between one-shot shell commands and durable local capability memory.
A command is a moment. An actor is a local thing with time: address, lifecycle, logs, mailbox, messages, artifacts, state, and an interaction contract.
trusted local capability
→ command template
→ recipe
→ spawn
→ run:<id>
→ message / inspect / artifacts
→ reusable tool memory
Agents are good at reasoning, but they should not reconstruct the same fragile background command every time a task becomes long-lived. pi-actors gives Pi a local-first actor layer: work can outlive the current turn, expose bounded state, receive typed instructions, produce artifacts, and graduate into persistent recipe-backed tools under ~/.pi/agent/recipes.
Use it when the correct shape is not "run a command and forget" but "start a local capability, keep its handle, and come back with intent."
- Spawn long-lived work without shell gymnastics. Start services, workers, subagents, fanouts, and pipelines as named actor runs.
- Steer instead of restarting. Send typed
messageenvelopes to runs, tools, branches, rooms, sessions, or coordinators. - Inspect intentionally. Read status, logs, messages, mailboxes, artifacts, registry health, and room rosters at decision points.
- Promote what works. Persist trusted command templates and recipes as durable local tools in
~/.pi/agent/recipes. - Keep orchestration local. State is file-backed, inspectable, operator-owned, and designed for Pi sessions rather than a cloud broker.
pi-actors compresses local orchestration into three public verbs:
| Verb | Use it when | Result |
|---|---|---|
spawn |
Work may outlive this turn, fan out, produce artifacts, or need later steering | A run:<id> actor with lifecycle and state |
message |
An existing actor should be continued, stopped, approved, killed, or given scoped input | One typed envelope delivered to one address |
inspect |
You need evidence before deciding the next step | Bounded views of status, logs, messages, registry, artifacts, or rooms |
Everything else is an adapter until proven otherwise.
pi install npm:@llblab/pi-actorsOr from git:
pi install git:github.com/llblab/pi-actorsThe npm package is dist-first for JavaScript-only runtimes: Pi metadata points at the named compiled entrypoint dist/pi-actors/index.js plus mirrored runtime assets, so extension discovery identifies pi-actors rather than an anonymous dist directory. Source TypeScript and source skills remain packaged for TypeScript-native or checkout-based runtimes.
Use actors instead of ad hoc shell backgrounding when work is long-running, stateful, resumable, artifact-producing, service-like, parallel, agentic, or worth saving.
Start an actor:
spawn template="sleep 30" as=run:demo
Inspect it when you need evidence:
inspect target=run:demo view=status
inspect target=run:demo view=tail lines=40
Steer it with a typed message:
message to=run:demo type=control.kill body=stop
For non-trivial actor workflows, load the bundled actors skill before improvising. For multi-model review or delegated audit, load the bundled swarm skill.
Core addresses stay small:
run:<id> one detached actor run
tool:<name> executable registered tool actor
Advanced addresses exist for coordination and diagnostics:
branch:<run>/<branch> branch-local worker endpoint
room:<run> run-local group timeline plus roster
coordinator current session coordination path
session: current session actor surface
session:all cross-session diagnostics inventory
Messages use one envelope shape:
{
"to": "run:review",
"from": "coordinator",
"type": "control.continue",
"summary": "Continue after checkpoint",
"body": "continue",
"reply_to": "msg_123",
"correlation_id": "task_456",
"metadata": {}
}Routing comes from to, actor ownership, and runtime policy. type describes intent. Recipes should expose semantic message types instead of transport knobs.
| Surface | What it gives you | Typical move |
|---|---|---|
| Command templates | Portable command graphs with placeholders, defaults, guards, retries, parallel nodes, recovery, and timeouts | Wrap a trusted local executable without writing a bespoke tool |
| Recipes | JSON/Markdown capability specs with metadata, args, defaults, imports, mailbox contracts, artifacts, and async mode | Save a known-good local workflow as reusable muscle memory |
| Async runs | File-backed detached lifecycle, logs, progress, output, cancellation, artifacts, and durable terminal follow-up notifications | Let model work, media jobs, services, or pipelines continue after the turn |
| Message protocol | Typed envelopes across run, tool, branch, room, coordinator, and session targets | Continue, approve, kill, or route work without restarting actors |
| Rooms and rosters | Run-local group timeline with actor join/leave, contacts, previews, and branch-aware delivery | Coordinate multiple subagents under one visible run |
| Registry and recipe doctor | Discovered tools, overrides, drafts, invalid recipes, and advisory risk labels | Audit local capability memory before using or promoting it |
| Draft promotion | Captured ad hoc spawn patterns can become explicit recipes after operator approval | Turn successful improvisation into durable local tools |
| Review/swarm recipes | Maintained packaged pipelines with preflight, marked semantic evidence, quorum knobs, model/thinking inheritance, one-turn prompt-file transport, and diagnostics | Delegate reviews without rebuilding fanout commands |
| Actor inspector | One manual Messages or Turns → filtered timeline → detail overlay for owned actor messages and persisted subagent sessions, with bounded/redacted prompt, model, thinking, tool, result, usage, and provenance evidence |
Follow actor traffic and every persisted subagent turn without exposing another session or inventing hidden reasoning |
| Packaged recipe QA | Installed-package-safe checks for helper paths, mailbox contracts, platform scope, artifacts, and recipe structure | Keep shipped actor components executable and diagnosable |
Create a reusable async actor recipe in the user recipe root:
mkdir -p ~/.pi/agent/recipes
cat > ~/.pi/agent/recipes/docs_review.json <<'JSON'
{
"description": "Start an async docs review actor",
"async": true,
"args": ["scope:path", "model:string", "thinking:string"],
"defaults": { "model": "{current_model}", "thinking": "{current_thinking}" },
"mailbox": {
"accepts": ["control.kill", "control.continue"],
"emits": ["review.completed", "run.failed"]
},
"template": "pi -p --model {model} --thinking {thinking} --no-tools \"Review {scope} for unclear actor-runtime onboarding. Return concise findings.\""
}
JSONBecause it lives under ~/.pi/agent/recipes/, the filename becomes the tool id. {current_model} and {current_thinking} inherit the active Pi session policy; pass explicit values only when a run should intentionally diverge.
Run it:
docs_review scope="README.md" run_id=docs_review
Inspect it:
inspect target=tool:pi-actors view=triage
inspect target=run:docs_review view=status
inspect target=run:docs_review view=tail lines=80
inspect target=run:docs_review view=messages
inspect target=run:docs_review view=mailbox
Steer it:
message to=run:docs_review type=control.continue body=continue
message to=run:docs_review type=control.kill body=stop
The persistent tool surface is location-derived:
~/.pi/agent/recipes/*.json
~/.pi/agent/recipes/*.md
Rules:
- User recipes in
~/.pi/agent/recipes/are tools by location. - Recipe filenames define tool ids.
- User recipes override same-name lower-priority recipes.
- Same-id JSON recipes shadow Markdown recipes in the same priority layer.
- Packaged recipes are standard-library components, not automatically installed operator policy.
- Draft recipes in
~/.pi/agent/recipes/drafts/are replayable memory, not active tools. register_toolcreates, updates, lists, deletes, or explicitly promotes draft recipe files through the normal agent interface.
Register a foreground tool:
register_tool name=transcribe_audio \
description="Transcribe a local audio file" \
template="~/bin/transcribe {file:path} {lang=ru} {model:string}"
Register a recipe-backed tool:
register_tool name=docs_review \
description="Start an async docs review actor" \
template="docs_review" \
args="scope:path,model:string"
Promote a captured draft only after explicit operator approval:
register_tool name=docs_review draft=~/.pi/agent/recipes/drafts/spawned-run.json
Inspect the registry:
inspect target=recipes view=status
inspect target=recipes view=summary verbose=true
inspect target=tool:pi-actors view=triage
A command template is the launch substrate. It can be a string, a sequence, or a composed graph.
Templates support:
- Named placeholders such as
{file},{model},{prompt}; - Compact types such as
string,path,int,number,bool,enum(a,b); - Defaults such as
{lang=ru}and{dry_run:bool=true}; - Fallback and small ternary forms;
- Sequences with stdin flow;
- Parallel nodes;
- Retries, recovery, failure policy, delays, guards, and timeouts;
- Async run values such as
{run_id},{state_dir},{actor_address},{default_room}, and{communication_file}.
The template owns execution shape. The recipe owns saved metadata, defaults, imports, mailbox, artifacts, and async launch policy. The run actor owns detached lifecycle, state, messages, cancellation, and inspection.
Packaged recipes live under recipes/ and helper scripts live under scripts/.
The library includes:
- Subagent launchers;
- Review, critic, planner, verifier, merger, judge, normalizer, and artifact atoms;
- Quorum and lens-style pipelines;
- Repo-health, release-summary, research-synthesis, development-tasking, docs-maintenance, and room-swarm pipelines;
- Coordinator-locker and actor-message utilities;
- Local music-player actor recipe.
Packaged recipes are building blocks. Use spawn file=<recipe> for maintained packaged pipelines before rebuilding equivalent shell commands. Copy or wrap them into ~/.pi/agent/recipes/ only when they should become durable operator-facing tools.
| If the work is... | Prefer... |
|---|---|
| Short, bounded, and foreground | Ordinary tools or registered foreground tools |
| Long-running, service-like, parallel, agentic, artifact-producing, or controllable | spawn / async recipe |
| Already running and needs new input | message |
| Unclear, failing, or ready for a decision | inspect |
| A multi-actor collaboration under one run | room:<run> plus branch addresses |
| A useful output that should survive context compression | Artifacts |
| A repeated local workflow | Recipe/tool memory |
When a directly spawned inline/ad hoc actor or a recipe outside the user recipe root completes successfully, pi-actors may include a promotion suggestion in its terminal follow-up notification. The agent should ask first and never auto-save.
Core actor state, inspection, foreground tools, and basic async runs are portable Node.js behavior. Run-local messaging and stop/kill use platform adapters under the same message API.
| Surface | Linux/macOS/WSL | Native Windows |
|---|---|---|
| Foreground tools, recipe discovery, inspect | Supported | Supported |
| Async runs and file-backed state | Supported | Supported |
| Mailbox-only actors and worker recipe | Supported | Supported |
| FIFO control endpoints | Supported | Not supported; use mailbox or named pipe |
| Named-pipe control endpoints | Not needed | Supported when recipe exposes one |
| Process cancel/kill | Process group signal with pid fallback | Windows process-tree adapter |
Packaged recipes should prefer mailbox/wake behavior for portable control. Recipes that require FIFO, Unix shell tools, or platform-specific media backends should make that limitation visible in docs or diagnostics before launch.
pi-actors is local-first, not sandbox-first.
Commands execute directly without shell evaluation where possible, but trusted executables still run with the same system permissions as Pi. Only register commands, scripts, recipes, and paths you trust.
High-risk templates such as shells, interpreter eval modes, network access, external side effects, and broad filesystem mutation may surface warnings, but the runtime is not a security boundary.
Prefer:
- Narrow commands;
- Explicit paths;
- Typed args;
- Bounded timeouts for bounded work;
- Explicit tool allowlists for subagents;
- Deterministic utility recipes for filesystem writes;
- Human approval for destructive or external side effects.
pi-actors is not:
- A generic workflow DSL;
- A remote agent interoperability protocol;
- A heavyweight broker;
- A sandbox;
- A facade that hides logs, artifacts, ownership, or local side effects;
- A polling-first async runner.
Its job is narrower: make trusted local capabilities addressable, messageable, inspectable, and reusable by agents.
Start here:
Core docs:
- Command templates
- Template recipes
- Async runs
- Actor messages
- Actor inspector
- Tool registry
- Recipe library
MIT
