Pi Agent Workspace ABI
The container workspace (/workspace/) is shared across all Pi-based agent variants — the
one-shot practice runner today, the long-lived mentor runner soon. Reserving the directory
names below is a no-cost commitment that prevents a second rename when the mentor runtime
lands (#1071) and beyond.
Layout
The workspace is partitioned by lifecycle, expressed as location (ADR 0020): read-only
vs writable is decided by where a file lives, not by convention. Three top-level regions —
inputs/ (read-only; the path-guard whitelists exactly this subtree), work/ (agent +
precompute scratch; never collected), and out/ (the only directory collected back into SQL).
/workspace/
├── inputs/ # READ-ONLY. The path-guard whitelists exactly this subtree.
│ ├── manifest.json # Telescope: the integration-agnostic index (path/connector/
│ │ # sha256 per file). Sits above the per-connector context it indexes.
│ ├── sources/ # Integration-namespaced source materialisations (ADR 0020). One namespace
│ │ └── scm/repo/ # per connector — the SCM git working tree (READ-ONLY mount) lives
│ │ # here; a future export would be sources/slack/…, sources/outline/…
│ ├── context/ # System-written, AI-readable. Populated by the ContentSource SPI.
│ │ # Files: metadata.json, comments.json, diff.patch, diff_summary.md,
│ │ # contributor_history.json, linked_work_items.json, …
│ └── practices/ # Practice catalog (index.json, {slug}.md, all-criteria.md).
├── work/ # AGENT + PRECOMPUTE SCRATCH. Never collected back into SQL.
│ ├── precompute/ # Per-practice precompute scripts injected by the server.
│ ├── precompute-out/ # Precompute runtime output (logs, structured hints).
│ └── analysis/ # Per-practice analysis output (.gitkeep markers).
├── out/ # THE ONLY collected directory — result.json, review-state.json,
│ # usage.json, runner-debug.json, watchdog-killed.json
├── task.json # TaskEnvelope<…> — runtime contract between handler and runner.
├── .pi/ # Pi SDK agent dir — $PI_CODING_AGENT_DIR resolves here.
│ ├── AGENTS.md # Orchestrator instructions
│ ├── settings.json # Pi SDK config (provider, model, compaction)
│ └── extensions/ # Custom provider extensions (auto-discovered)
└── .run-pi.mjs # Runner script entry point.
The long-lived mentor interactive sandbox (#1071) is a separate runtime with its own
layout (context/target/, context/user/, scratch/) driven by
DockerInteractiveSandboxAdapter, not by this ABI. It is documented there, not here.
Path conventions
inputs/— the entire read-only region. The sandbox path-guard whitelists exactly this subtree; an agent write attempt anywhere underinputs/is rejected.inputs/context/— written byContentSourceimplementations underagent.context.providers.*. Path prefix is enforced byWorkspaceContextBuilder.inputs/manifest.json— the telescope index, written byContextManifestBuilderaboveinputs/context/(it indexes the context files but is not itself one of them).inputs/sources/scm/repo/— the read-only SCM checkout, bind-mounted from the host Context Fabric ({fabric.root}/sources/scm/{repositoryId}).work/— agent + precompute scratch. The Pi agent may write here; the server never collects it.out/— the only directory the sandbox collects after the run.task.json—TaskEnvelope<T extends Task>. Schema version1. The runner assertsschemaVersionandtask.kind, exiting42on mismatch (envelope/image drift signal)..pi*/inputs/practices//work/precompute*/work/analysis//out/— internal control surfaces. AI-readable as configured by the orchestrator, but not part of the public agent ABI; subject to change without aschemaVersionbump.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Agent runtime failure (Pi SDK or runner error) |
| 3 | Watchdog hard-kill (budget + grace exceeded) |
| 42 | Envelope mismatch (unsupported schemaVersion or unknown kind) — image/server drift |
Versioning policy
task.json.schemaVersion is per-envelope, not per-task variant. Add a new permitted Task
subtype (a new kind discriminator) without bumping the version. Add a required field to an
existing kind, and the version bumps. The Pi runner and the Java server ship in the same
Docker-image rebuild, so version drift is bounded by deploy cadence; there is no cross-version
contract.