Two findings that changed the plan rather than confirming it:
23. Skills require a tool literally named `read`. Curator's tools are all
domain-specific, so every --skill argument was discarded in silence. The
planned split into curator-core / video-arr / books-ingest was inert before
it was written; the policy stays in APPEND_SYSTEM.md. memo-inbox is
unaffected because it registers a restricted `read` override, which is why
the earlier note generalised wrongly from it.
24. A long-lived session is worth far more than the startup it saves: 99.97% of
input read from cache on a continuing conversation against 0% on a new one.
That is what makes the generated tool list necessary rather than merely
tidy -- anything varying at the front of the prompt destroys it -- and it
makes rotation a cost to be bounded rather than applied eagerly.
profile.toml now describes the phase-3 configuration that is actually deployed,
including that the empty `skills` list is a finding and not an oversight.
pi_rpc gains --system-prompt support and no longer guesses whether a `read` tool
will exist; extension_registers_read has to be stated.
harness-layering.md records what transfers from a widely-shared account of
building a personal coding harness on pi, and what does not. The layering frame
holds and the cache-hit figure was the useful part. Its central recommendation --
installing third-party packages -- is disqualifying for an unattended agent
holding tracker credentials, and its discipline layer (AGENTS.md) is precisely
what we block, because it is discovered from every parent directory.
pi-agent-config
Authoritative configuration for every Pi 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 |
Book / film / TV / music curation agent | curator.service |
target config written, not yet deployed |
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 |
Interactive Grok 4.6 coding agent | none (manual) | registered only |
Start here
| Document | Contents |
|---|---|
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 |
The four isolation layers and the flag set every scenario should use |
docs/personality-layering.md |
How to choose between SYSTEM.md, APPEND_SYSTEM.md, AGENTS.md, SKILL.md and the request |
docs/gateway-patterns.md |
Ten patterns for hosting an agent behind a long-running service |
docs/plans/ |
Active work plans |
The finding that motivated this repository
pi emits the <available_skills> 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,
--skillwas 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):
| 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 |
<available_skills> |
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;
its 960-character figure measures the stub, not Curator.
Reproduce either with 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/<name>/
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
# 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 <backup dir>
# 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:
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
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 <scenario> --apply