@sakiko233/pi-subagent

extensionmaintained

Pi extension for one inspect-only background subagent with a frozen conversation seed, verified result retrieval, and attested single-child Pi runs, built on the shared pi-background-tasks task service.

by — · v0.1.3 · published 4w ago

$ pi install npm:@sakiko233/pi-subagent
downloads/mo
288
stars
0
last push
4w ago
open issues
0

Signals

license: MITtestspi manifest: missinginstall size: —deps: 0peer deps: 0

Download trend

No downloads in the last 12 weeks.

README

pi-subagent

One inspect-only background subagent for Pi: a frozen conversation seed, a route pinned at launch that is never substituted, a hash-verified result data plane, and an opt-in attested single-child Pi run mode.

The task registry, footer dock, logs, cancellation, and terminal notifications are owned by the shared task service; this package is an owner client of it.

Requirements

  • Pi >= 0.84.2 (peer packages @earendil-works/pi-ai, @earendil-works/pi-coding-agent, @earendil-works/pi-tui).
  • @sakiko233/pi-background-tasks v3 or newer, installed and enabled. pi-subagent cannot run without it.

Install

pi install npm:@sakiko233/pi-background-tasks
pi install npm:@sakiko233/pi-subagent

Those are the only two Pi packages to install and enable. pi-agent-runtime is an ordinary transitive npm dependency of pi-subagent; do not add it to Pi package settings. Order does not matter, and the background-service handshake happens at session start.

Tools

Exactly three tools are registered, and only after a successful startup handshake with the background-task service.

subagent_run

Launch one background Pi subagent seeded with a frozen projection of the current conversation, then return a launch receipt immediately.

Parameters (closed schema):

keytypedefaultnotes
namestringrequired2-6 words, shown in the bg footer dock
promptstringrequiredauthoritative instruction; the projected conversation is background only
route{provider, model}current modelpinned at launch, never substituted
capabilitystring"inspect"only inspect exists: read/search/list, no shell, no writes, no network, no recursion
extensionModestring"isolated"ambient executes arbitrary discovered extension code in the child and weakens isolation
maxTurnsnumber24
maxToolCallsnumber120
timeoutSecondsnumber1200wall-clock; the child is killed when exceeded
autoDeliverstring"never"never | when_small | always; appends the verified answer as a final task log frame
notifyOnCompletionbooleantruedurable terminal notification
triggerOnCompletionbooleantruethe notification starts a follow-up turn

The receipt carries the subagent task id (s…), the service-allocated registry id, the pinned route, the artifact directory, and the seed hash. Retrieve the answer with subagent_result; do not poll.

subagent_result

Non-blocking, hash-verified retrieval for subagent_run tasks only.

keytypedefaultnotes
taskIdstringrequiredsubagent task id (s…) from the receipt; unambiguous prefixes work
deliverystringautoinline returns the verified answer text; artifact returns metadata plus the artifact reference

Behavior:

  • running → a typed not-ready view (state: "running", delivery: "none"); it never blocks;
  • terminal → the committed result package is verified (seed hash, route attestations, per-block and aggregate SHA-256, strict UTF-8) before a single byte is returned;
  • answers at or under 48 KiB deliver inline; larger answers degrade to an artifact reference explicitly and are never truncated;
  • delivery: "inline" on an oversized answer fails loudly (result_too_large_for_inline);
  • observed child usage is attached to exactly one retrieval; later retrievals say so.

subagent_run_attested

Opt-in, evidence-oriented direct Pi spawn. Launches exactly one pi --mode json child, records raw Pi events/stderr, hashes prompt/report/output, observes OAuth through the ModelRegistry, and writes a strict attestation sidecar (pi-subagent.pi-task-attestation.v1) only after successful completion.

keytypedefaultnotes
namestringrequired
providerstringrequiredopenai-codex or anthropic (subscription OAuth only)
modelstringrequiredexact provider-local model id
promptstringrequiredpassed as the single user prompt
reportPathstringrequiredrelative, inside the task cwd, never .git or .pi/tasks
extraPiArgsstring[]nonemode/provider/model/api-key/auth-file args are rejected
thinkingstringnone
timeoutSecondsnumbernonetask is failed and killed when exceeded

The task cwd must be a clean Git worktree at start and finish; the attestation refuses a changed or dirty tree. Evidence lives under .pi/subagent/attested/ and terminal state is published through the background task service (observe with bg_status / bg_logs).

Failure behavior

  • No service / two services / incompatible service at session start: a loud dependency error (UI notification, console, and a session message) and none of the three tools is registered.
  • Admission refusals (unresolvable or under-capacity route, oversized seed, unsupported hook contract) create no child and no artifacts.
  • Cancellation (dock kill, /kill, or service shutdown) aborts the child process group, acknowledges the cancellation, and settles the task killed.
  • Failures settle failed with a bounded, typed error; preserved evidence (seed, budget plan, child terminal record, runtime budget) is listed in the error and never silently discarded.
  • A child that exits 0 without committing a result is child_exited_without_commit, never a silent empty success.
  • Tampered or foreign result packages fail verification (seed_hash_mismatch, route_mismatch, answer_hash_mismatch, …); their bytes are never returned.

Artifacts

Each run writes a durable store under .pi/subagent/<session>/<taskId>/: seed.json, context-omission-ledger.json, budget-plan.json, child-prompt.txt, manifest.json, outcome.json, spill payloads under spill/, and the child-committed result.json (the single answer commit point). All control writes are temp-write + fsync + rename.

License

MIT. See THIRD_PARTY_NOTICES.md for the extracted upstream ISC notice and the attribution-implementation ownership split.