The body is the dominant cost; the catalog line is negligible.

A user has a Friday ritual: a status summary, structured just so, pulling from the same three places every week. Where does that procedure live? Re-explained every Friday, it costs a paragraph of prompting and drifts a little each time. Baked into the system prompt, every user pays tokens for one user’s ritual. Stuffed into memory, it hits a wall by design — memory is for facts, hard-capped, written by the model. A procedure is a document, written by a person.

That’s the last row of the standing context: skills — reusable instructions users author to shape the agent’s behavior, deliberately, with a name. They complete a symmetry the series has been circling: memory is what the agent writes down about the world; skills are what people write down for the agent.

An index line the author can’t overflow

A skill is {title, description, body} plus an icon and a scope. The body is markdown, stored as a blob in the object store — and it has no length cap. The only validation on a skill is a non-empty title and description. Compare that with memory’s hard field caps and the contrast is the whole design philosophy in one line: when the model writes the index, you budget by construction; when a person writes the payload, you let them write — and make sure the standing context only ever carries one line of it.

That line is the entire per-skill footprint, rendered every turn:

## Skills
Skills are reusable instructions the user has authored to shape your
behavior. This is the complete catalog for the current scope (id — title:
when it applies). …

- prj-status — Project status: Use when the user asks for their status

Seven characters of structure per skill, plus content. The catalog never touches bodies at all — listing goes through a summary shape with no body field, precisely so a catalog render doesn’t pay one object-store read per skill. The body stays behind an address until someone dereferences it, which by part 3’s vocabulary makes a skill a pointer with a title.

Two prompt-design details here are worth stealing. The section announces itself as the complete catalog — and it renders even when empty, on purpose. The code comment: the empty section “tells the model the application already checked every applicable scope and prevents speculative list_skills lookups.” A missing section invites the model to go looking; an empty one closes the world. And the description is taught to authors as a selection signalname the trigger condition, not the skill’s title — because its one job is to let a model decide whether to activate without reading the body.

Activation: the pull, and what it costs after

In the catalog — one line, every turn structure ≈ free; content is the line ## Skills - prj-status — Project status: Use when the user asks for their status activate_skill({ skillId: "prj-status" }) On activation — the full body, as a tool result takes effect the same turn [Skill activated: Project status] # Instructions Do X then Y. every later turn, replayed from the transcript For the rest of the conversation a one-line wrapper + the full body the body rides along in context on every subsequent LLM call — this re-injection, not the catalog line, is the cost worth engineering around Bodies have no length cap — the only validation on a skill is non-empty title and description.
The lifecycle: one catalog line standing; the full body arrives as a tool result the moment it's matched; and from then on it rides in the transcript on every LLM call — the re-injection the epigraph is weighing against the line.

The epigraph is a verbatim design comment, and it answers a question you might not think to ask: why aren’t activated skills removed from the catalog? Because it isn’t worth a line of code. “Activated skills are intentionally NOT filtered out — their body re-injection is the dominant cost; the catalog line is negligible.” Optimize the dominant cost; don’t polish the negligible one. The dominant cost is real: once activated, the body is replayed into context on every subsequent call for the life of the conversation — which is exactly right for instructions that must stay in effect, and exactly why the budget-conscious unit is the activation, not the catalog entry.

The mechanics tie back through the whole series:

  • activate_skill is part of part 2’s always-declared scaffolding — so matching a skill costs zero discovery round-trips. The five skill-management tools (define_skill, edit_skill, delete_skill, get_skill, list_skills) are not: managing skills is rare, so it pays the normal search → activate path. Frequency of use decides what’s standing.
  • The tool is internal and trusted: a control action, invisible to external callers, never gated on approval. An unknown id fails with a pointer back to the catalog.
  • There are two activation paths with opposite freshness semantics — a genuinely sneaky detail. Model-initiated activation returns the body as a tool result: frozen at activation time, replayed verbatim from the transcript. User-initiated activation persists only the skill id, and the provider re-resolves the body on every call: live, so edits propagate into running conversations and a deleted skill silently drops out. Same feature, two consistency models, each matching who initiated it.

Who sees which skills

Scope is three nullable axes — template, project, user — where null means “not restricted by this axis” and a skill is visible iff every axis it does set matches the caller:

A PROJECT THAT ADOPTS TEMPLATE T — WHAT'S IN THE CATALOG? SKILL TEMPLATE PROJECT USER IN CATALOG? release-checklist global — applies everywhere issue-triage T adopted from T, selection permits weekly-report this one defined on this project my-shortcuts me the caller’s own their-shortcuts other another user’s — never returned
Multi-axis visibility, from the catalog resolver: a project unions its own skills, skills adopted from its templates (subject to per-template selections), globals, and the caller's personal skills. Another user's personal skills are never returned. Names generalized.

The interesting case is the second row: a skill authored once on a template reaches every project that adopts that template — instructions distributed through the same adoption relationship the rest of the product already uses, with a per-project include/exclude selection as the throttle. Teaching scales the way configuration scales.

One more mirror of part 4: if the skill catalog can’t be loaded at wake-up, the harness fails the whole turn and lets message-bus redelivery retry, rather than proceeding without it. The doc comment: skills are user-authored instructions, so “no caller silently proceeds without them.” Tool discovery degrades gracefully; user-taught behavior does not get to silently vanish. Machine-derived context fails soft; human-authored context fails hard.

The agent as author

The loop closes in a pleasing way: define_skill is an agent tool. A user can demonstrate a procedure once in conversation and ask the agent to make it a skill — the model drafts the body, and is instructed to write the description as the trigger condition it would itself want to read next time. The agent authors its own future context, in the one place where authored context is designed to be cheap until used.

The honest costs, since unbounded trust cuts both ways: a user can paste a small book into a body and pay for it on every turn after activation — the system trusts authors rather than capping them. Activating the same skill twice injects the body twice; nothing dedupes it. And the empty-catalog paragraph is a short standing cost paid by everyone, purchased to prevent something more expensive — speculative search calls.

The series, whole

IN CONTEXT, EVERY TURN — THE INDEX ON DEMAND — THE PAYLOAD Domain ontology 13 root-domain one-liners · ≈340 tokens Concept graph 15 domains · 28 entities · 12 relationships explore_ontology Tool surface namespace line + scaffolding + active set Tool catalog 169 tools · ≈85k chars of schema search_toolsactivate_tool Skill catalog id — title: description per skill Skill bodies full instructions, injected on use activate_skill Memory digest capped index of {key, description} Memory bank capped records, key-addressed recall_memories Tool results bounded previews + $ref stubs Blob store unbounded bytes, server-side $ref resolution
The full standing context: five indexes, five payloads, five pulls. Nothing on the left grows with the product, the data, or the user's enthusiasm; everything on the right can.

Five mechanisms, one principle applied at five altitudes:

MechanismStanding costPayloadPull
Ontology13 one-liners · ≈340 tokthe concept graphexplore_ontology
Toolscapability line + ~12 schemas169 schemas · ≈21k toksearch_toolsactivate_tool
Valuespreviews + $ref stubsunbounded bytes$ref resolution
Memorya capped {key, description} indexcapped recordsrecall_memories
Skillsone line per skillunbounded bodiesactivate_skill

And underneath all five, the same two commitments. Defer, don’t truncate: nothing in this harness is thrown away to make room — it’s parked behind an address. That’s why the shrinking is not a trade-off against capability but a second win: the window the model reads is all signal, nothing it might need has been omitted, and both the token bill and the error rate go down together. Keep the prefix byte-stable: sorted declarations, WeakMap-cached schemas, the one varying line last — deferral constantly mutates the prompt, and these small disciplines are what keep the automatic prefix cache paying for it.

The honest bill, series-wide: every deferral is a round trip the model must decide to make, so the harness spends prompt text teaching it to search, drill, forward and activate; transcripts are less self-contained; and all of it is real engineering — indexes, projections, resolvers, digests, catalogs, and their tests — where a small product could paste its five tools and one page of notes into the prompt and be correct. Do that as long as you can. We couldn’t. If your catalog has three digits, your domain has its own vocabulary, your tools move megabytes, or your users have things to teach, I hope these five parts read as one pattern applied five times — an index in context, a payload behind a pull, and a model that navigates by address instead of by copy. Pointers, not payloads, all the way down.