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.
101 lines
5.3 KiB
Markdown
101 lines
5.3 KiB
Markdown
# Harness layering, and which parts transfer to a dedicated agent
|
|
|
|
Notes taken from a widely-shared account of building a personal *coding* harness on
|
|
pi ([@chasen_liao, 2026-08-27](https://x.com/chasen_liao/status/2092963119337476137)),
|
|
checked against what this repository actually runs. Recorded because the layering
|
|
is a good frame and because several of its specifics are actively wrong for a
|
|
service-embedded agent — and the reasons are worth stating once rather than
|
|
rediscovering.
|
|
|
|
## The frame: three layers
|
|
|
|
| layer | coding harness | this repository |
|
|
|---|---|---|
|
|
| discipline — durable, always loaded | global + project `AGENTS.md` | `.pi/SYSTEM.md` + `.pi/APPEND_SYSTEM.md` |
|
|
| capability — loaded when needed | Skills, hidden by default | tool list generated into the system prompt |
|
|
| control plane | third-party packages | one scenario extension + a loopback bridge |
|
|
|
|
The frame holds. What differs is every mechanism, and the differences are not
|
|
stylistic.
|
|
|
|
## What transfers
|
|
|
|
**Discipline belongs in a durable file, not in each request.** We reached the same
|
|
place from the opposite direction: per-request restatements of "which adapters
|
|
exist" were removed in phase 2 because they varied the prompt prefix and cost
|
|
cache hits (`pi-runtime-notes.md` §24).
|
|
|
|
**Don't pile on capabilities.** "Several dozen enabled made routing worse" matches
|
|
the reason Curator exposes five tools and not fifteen. Every tool is a branch the
|
|
model can take wrongly.
|
|
|
|
**Watch where context goes.** The article uses `pi-context-usage` for this. We take
|
|
the same numbers from `message_update.usage` in the RPC stream, which costs nothing
|
|
extra, and write them to `control_events` per turn. The article's reported 98%
|
|
cache hit is the single most useful figure in it, and it is what justified phase
|
|
3b's long-lived sessions; we measure 99.97% on a continuing conversation.
|
|
|
|
**One writer at a time.** Their rule for parallel subagents ("only one writer per
|
|
directory; reviewers may run in parallel because they are read-only") is the same
|
|
shape as Curator's: many read tools, exactly one write path through
|
|
`CuratorService`.
|
|
|
|
**No claiming done without evidence.** Their coding loop insists on it; Curator
|
|
enforces it mechanically, generating receipts from `tool_execution_end` rather than
|
|
letting the model narrate what it did.
|
|
|
|
**pi has no sandbox and runs at full privilege.** Stated as a closing caution
|
|
there; recorded as `pi-runtime-notes.md` §20 here, and the reason isolation is four
|
|
layers rather than a flag.
|
|
|
|
## What does not transfer, and why
|
|
|
|
**Third-party packages.** `pi install npm:...` is the article's main recommendation.
|
|
For a dedicated agent it is disqualifying: a package runs arbitrary code in the
|
|
same process as the agent, and Curator's whole posture is that the agent reaches
|
|
exactly five audited endpoints over loopback. The article says as much in passing
|
|
("look at the source and permissions before installing") — advice that scales to a
|
|
human's interactive tool and not to an unattended service holding tracker
|
|
credentials. `no_extensions = true` plus one reviewed extension stays.
|
|
|
|
**`AGENTS.md` as the discipline layer.** For an interactive agent in a repository
|
|
this is right. For us it is precisely the thing to block: `AGENTS.md` is discovered
|
|
from *every parent directory* of the workspace, so a file written for an unrelated
|
|
project leaks in. `--no-context-files` is the only switch that stops it, and it is
|
|
on. Discipline lives in the system-prompt files, which that flag does not touch.
|
|
|
|
**Skills as the capability layer.** Cannot work here at all: pi emits the skills
|
|
section only when a tool named `read` is active, and Curator's tools are all
|
|
domain-specific, so every `--skill` argument is discarded in silence
|
|
(`pi-runtime-notes.md` §23). The capability layer is generated into the system
|
|
prompt instead.
|
|
|
|
Beyond the mechanism, on-demand loading is *undesirable* for us: it varies the
|
|
prompt prefix, and a varying prefix is exactly what destroys the cache hit the
|
|
article is celebrating. Interactive sessions can afford it; a per-message service
|
|
cannot.
|
|
|
|
**Subagents and parallel lanes.** Curator answers one message about one library.
|
|
There is no plan to decompose. The article's own caution — "don't force the full
|
|
workflow onto a small task" — applies, and here every task is small.
|
|
|
|
**`$`-expansion, `/btw`, `/goal`, `/context`, TUI packages.** All interactive
|
|
affordances for a human at a terminal. Curator has no human at a terminal; it has
|
|
Telegram and an HTTP server.
|
|
|
|
**`pi-ask` for stopping at ambiguity.** The instinct is right and Curator has an
|
|
equivalent, but it cannot be a tool: a Telegram round-trip is not a blocking
|
|
prompt. Ambiguity is handled by the `clarify` intent, and the harder rule is that
|
|
ambiguity must resolve towards *reading*, not asking — phase 0 removed a
|
|
`clarify → library_query` rewrite that was guessing, while phase 3 keeps "when a
|
|
message is only a title, query rather than ask what the user wants".
|
|
|
|
## The transferable conclusion
|
|
|
|
The article's actual thesis is not its package list, it is that a small core plus
|
|
your own assembly beats a fixed harness. That is the same conclusion this
|
|
repository reached, with the opposite emphasis: for an unattended agent holding
|
|
real credentials, most of the assembly is deciding what *not* to load, and every
|
|
capability has to be justified against what it would cost if the model were
|
|
adversarial rather than merely wrong.
|