Correct the Pi advice: per-agent skills are the design; per-agent extensions via adapterConfig.command

This commit is contained in:
Sam
2026-11-11 08:13:48 +11:00
parent 77014d035b
commit 47aacfd6d1
7 changed files with 802 additions and 0 deletions

View File

@@ -414,3 +414,79 @@ Four consequences, and they matter:
A history panel is therefore feasible without new plumbing: list an agent's sessions from
`task-sessions`, open one, and render the JSONL transcript. That is the natural next panel
after the functional tests, and it is read-only.
---
# Correction: per-agent skills are the design, not an accident
The section above gives the wrong impression. Here is the accurate version.
## Each agent has its own skill set, and that is stored in Paperclip
`GET /api/agents/{id}/skills` returns, per agent, `desiredSkills` and the entries actually
managed for it. `Builder` had its own list; `Documenter` has another. Setting it is one call:
```
POST /api/agents/{id}/skills/sync
{ "mode": "replace" | "add" | "remove",
"desiredSkills": ["company/<id>/nixos-workflow", "paperclipai/paperclip/paperclip"] }
```
`replace` means "this agent gets exactly these". At run time the adapter builds a directory
from **that agent's** desired set and passes it as `--skill`, and symlinks those skills into
`~/.pi/agent/skills/<runtimeName>` so the run can find them. So: different agents, different
skills, no problem — this is already the supported path and it needs no picker.
The caveat I over-stated is narrow: the symlinks stay in the shared global directory after a
run, and Paperclip does not pass `--no-skills`, so a skill an agent used once can remain
discoverable by another agent afterwards. That is a leak to know about (and a good argument
for `replace` plus a periodic clean), not "one set for everybody".
Where skills come from: `GET /api/skills/available`, the company list at
`GET /api/companies/{id}/skills`, and the catalog at `GET /api/skills/catalog`. A skill there
can be assigned to any agent with the call above.
## Extensions per agent: yes, through the command
The adapter's configuration document says the agent's command defaults to `pi` and can be set
per agent:
```
adapterConfig.command defaults to "pi"
adapterConfig.env KEY=VALUE pairs
```
So an agent can be given its own wrapper:
```
~/paperclip-agents/builder/pi-wrapper.sh:
#!/bin/sh
exec pi --extension npm:pi-memctx --extension git:https://gitea…/pi-config/extensions/tavily-search/index.ts "$@"
```
and `PATCH /api/agents/{id}` with `{"adapterConfig": {…, "command": "…/pi-wrapper.sh"}}`. The
adapter appends its own arguments (`--mode json`, `--session`, `--skill`, `--tools`,
`--model`) to whatever the command is, so the wrapper is additive and cannot break the run.
`env` is the same lever for environment variables.
That is how per-agent extensions become real today: one wrapper per agent role (`builder`,
`documenter`, `reviewer`), each listing the extensions that role may use. It also gives a
place to set `--no-skills` if strict isolation is wanted, and a place to keep the tool list
deliberately small.
## History: three options, in order of fidelity
1. **Open the real Pi session in a pane.** Paperclip writes every run to
`~/.pi/paperclips/<timestamp>-<agentId>.jsonl` and starts Pi with `--session <file>`. A
pane running `pi --session <that file>` gives the actual conversation, with Pi's own
interface, and can be continued. Highest fidelity, zero new code — a tool-pane entry that
takes a file path. Two writers on one session file is the risk, so this is for sessions
that are finished, or for a deliberate hand-over.
2. **A read-only transcript panel.** Parse the JSONL and draw the messages in `Agents>agents`
as a fourth tab. Integrated, safe, no second process; less faithful than the real thing.
3. **`pi --resume`** in a tool pane, and pick the session from Pi's own list. Simplest of all,
but it makes you find the session by eye.
`GET /api/agents/{id}/task-sessions` maps task → session file and working directory, so option
1 and 2 both have a reliable index and neither needs guessing.