# pi-agent-config Authoritative configuration for every [Pi](https://pi.dev) agent on this host: the user-level Pi runtime, plus one directory per dedicated agent scenario. The live locations (`~/.pi/agent`, `~/pi-workspaces/*`) are **runtime copies**. Changes are made here and pushed out with `scripts/deploy-*.sh`, never the other way round — except for scenarios explicitly marked `deploy = "mirror"`, which record what a running service already does. Verified against **pi 0.84.3**. Re-run the probes after every `pi update`. ## Scenarios | Scenario | Purpose | Service | Status | |---|---|---|---| | [`curator`](scenarios/curator/) | Book / film / TV / music curation agent | `curator.service` | target config written, **not yet deployed** | | [`memo-inbox`](scenarios/memo-inbox/) | Routes Telegram/WeChat messages to Calendar, Obsidian todo or journal | `pi-memo-telegram.service` | **mirror** of live config, zero behaviour change | | [`pi-grok`](scenarios/pi-grok/) | Interactive Grok 4.6 coding agent | none (manual) | registered only | ## Start here | Document | Contents | |---|---| | [`docs/pi-runtime-notes.md`](docs/pi-runtime-notes.md) | pi 0.84.3 mechanics that the official docs understate, each verified against source or a live probe | | [`docs/isolation-baseline.md`](docs/isolation-baseline.md) | The four isolation layers and the flag set every scenario should use | | [`docs/personality-layering.md`](docs/personality-layering.md) | How to choose between `SYSTEM.md`, `APPEND_SYSTEM.md`, `AGENTS.md`, `SKILL.md` and the request | | [`docs/gateway-patterns.md`](docs/gateway-patterns.md) | Ten patterns for hosting an agent behind a long-running service | | [`docs/plans/`](docs/plans/) | Active work plans | ## The finding that motivated this repository pi emits the `` block **only when a tool named `read` is active** (`dist/core/system-prompt.js:59,113`). The Curator service ran with `--no-tools --skill …` for its entire lifetime, so: - its 64-line media policy never reached the model, - `--skill` was a no-op, - and both the README and the deployment runbook described a mechanism that was not happening. Measured on the real workspace, before and after ([evidence](docs/evidence/2026-08-27-curator-phase0-prompt.md)): | | before | after | |---|---|---| | system prompt | 2548 chars | 3539 chars | | `expert coding assistant` framing | present | **gone** | | pointer to pi's own documentation | present | **gone** | | the 64-line media policy | **absent** | present | | `` | absent | absent | | workspace `AGENTS.md` | loaded | blocked | | parent-directory `AGENTS.md` | **leaked** | blocked | The prompt got *larger*, and that is the fix rather than its cost: of the original 2548 characters roughly 1.9 KB was pi's coding-assistant scaffolding and a pointer telling the agent to read pi's documentation and follow its cross-references — noise for a media agent, and a ready-made escalation path for injected text — while none of it was Curator's own policy. All 3539 characters now are. A mechanism demonstration with a stub `SYSTEM.md` is in [`docs/evidence/2026-08-27-isolation-probe.md`](docs/evidence/2026-08-27-isolation-probe.md); its 960-character figure measures the stub, not Curator. Reproduce either with [`docs/evidence/probe-harness/`](docs/evidence/probe-harness/) — zero model tokens, because a single RPC `get_state` starts the agent, fires `session_start` and exits without contacting the provider. ## Layout ``` docs/ mechanics, baselines, plans, reproducible evidence runtime/agent/ ~/.pi/agent — settings, models.json.template, extensions, prompts shared/ cross-scenario code lib/py/pi_rpc.py long-lived RPC client with rotation and budgets extensions/pi-guard-base.ts path containment, restricted read, capability guard scenarios// profile.toml single source of truth for the launch contract workspace/ what gets installed into the live workspace eval/ recorded golden transcripts scripts/ diff, deploy, backup, restore, secret guard secrets/ host-local, untracked ``` ## Usage ```bash # What differs between this repository and the host? scripts/pi-diff.sh scripts/pi-diff.sh curator # Push configuration out (dry run first; neither restarts a service) scripts/deploy-runtime.sh scripts/deploy-runtime.sh --apply scripts/deploy-scenario.sh curator --apply # Back up the live installation (archives land outside this repository) scripts/pi-backup.sh scripts/pi-restore.sh --from # Verify the mechanics still hold after a pi upgrade docs/evidence/probe-harness/collect-evidence.sh shared/extensions/tests/run-guard-checks.sh python3 shared/lib/py/tests/test_pi_rpc_smoke.py ``` ## Secrets Nothing real ever enters this repository. `models.json`, `auth.json`, `trust.json` and every `*.env` are ignored; `secrets/` accepts only `.gitkeep`, `README.md`, `*.example` and `*.template`. `scripts/verify-no-secrets.sh` enforces this as a pre-commit hook. Install it in a fresh clone: ```bash ln -sf ../../scripts/verify-no-secrets.sh .git/hooks/pre-commit scripts/verify-no-secrets.sh --all ``` Backups contain plaintext credentials and are written outside the work tree; `pi-backup.sh` refuses any destination that resolves inside it. ## First-time setup on a new host ```bash git clone gitea-45:kai/pi-agent-config.git && cd pi-agent-config ln -sf ../../scripts/verify-no-secrets.sh .git/hooks/pre-commit cp secrets/zenmux.env.example secrets/zenmux.env chmod 600 secrets/zenmux.env && $EDITOR secrets/zenmux.env npm install -g @earendil-works/pi-coding-agent@0.84.3 scripts/deploy-runtime.sh --apply scripts/deploy-scenario.sh --apply ```