Intent
Store an agent's competence, not just its knowledge. When the agent works out how to do something, keep the procedure itself — a script, a function, a checklist — so the next attempt starts from a working solution rather than from a description of one.
The page makes two kinds of claim. Skill libraries — procedures the agent or a person writes down, advertised by name and description, with bodies loaded on demand — are reported practice, and common across this atlas. The outcome-verified write gate is argued, and rests on two systems: Voyager writes an executable skill only after the environment confirms it worked, and Acontext holds a partial version of the gate.
The problem
Most agent memory remembers propositions: the user prefers dark mode,
the deploy failed at step three, the schema has a tenant_id
column. Propositional memory answers "what is true?"
It answers "how do I do this?" badly. An agent that solved a fiddly multi-step task last week can retrieve a summary of having solved it and still have to rediscover every detail. Worse, a summary of a procedure is exactly the kind of memory that looks right and is subtly wrong — the steps are there, the ordering constraint that made it work is not.
Procedures also have a property propositions lack, and it is the whole opportunity: you can run them. "Is this fact true?" requires judgment. "Does this procedure work?" can be answered by executing it and checking the result.
The pattern
Store the executable artifact. Index it by a generated description of what it does. Gate the write on verified execution.
task -> agent produces a procedure (code, script, sequence)
-> execute
-> verify against observable outcome, not model self-report
-> on success: generate a natural-language description
embed the DESCRIPTION, store the PROCEDURE
-> on failure: feed the failure back as reasoning input; write nothing
retrieval: embed the task -> search descriptions -> return procedures
-> earlier procedures become primitives for new ones
Diagram source
%% caption: nothing enters the skill library until an outcome verifies it; a failed attempt is critiqued and retried, and the store stays empty
flowchart TD
T["Task"] --> Gen["Agent writes procedure"]
Lib["Skill library"] --> Gen
Gen --> Exec["Execute"]
Exec --> Ver{"Verified by outcome?"}
Ver -- "no" --> Crit["Critique -> retry (nothing stored)"]
Crit --> Gen
Ver -- "yes" --> Desc["Generate description"]
Desc --> LibThree invariants make it work:
- The retrieval key is not the payload. Embed a description of intent; return the artifact. Source code embeds poorly.
- Verification precedes storage. The gate is an observed outcome, not the model's confidence.
- Failures inform, they do not persist — at least not in the same store, and not as callable procedures.
Why it works
It converts memory from recall into capability. A propositional store gets larger as the agent works; a skill library gets more capable, because retrieved procedures become building blocks for new ones.
And it sidesteps the hardest problem in the rest of this atlas. Every pattern here about trust — rejected-value tombstones, trust-state machines, evidence before belief — exists because propositional truth is expensive to establish. Procedural truth is cheap to establish where actions have observable effects: run it and look.
Tradeoffs
- Verification is only as good as the check. Succeeding once in one state is not evidence of generality, and a skill stored after a single lucky execution is a false memory with a confident-looking provenance.
- Executing stored artifacts is a trust boundary. A skill library is durable, agent-authored, retrieved-by-similarity code. Outside a sandbox, in any setting where inputs are not trusted, this is an obvious attack surface.
- Libraries need pruning, and pruning needs a utility signal. Without one — reuse count, success rate on reuse, composition depth — the library accumulates near-duplicate one-offs.
- Retrieving the wrong procedure is worse than retrieving the wrong fact. An irrelevant fact is noise the model can ignore; an irrelevant callable invites the model to call it. Score thresholds matter more here than elsewhere.
- Supersession needs lineage. Replacing a skill with a better version is a correction, and correction without a lineage record leaves you unable to answer why behaviour changed.
- Not every domain has a checkable outcome. The pattern degrades toward ordinary memory wherever success is a matter of judgment.
Do not use this to store prose "procedures" that nothing executes. Without the verification gate, this is just tagged notes, and it inherits none of the property that makes it worth doing.
Cost to adopt
Build: a store for runnable procedures, a description index to retrieve them by, and an execution gate that only writes on verified success.
Forces elsewhere: you need a sandbox and a real success signal. Without one, this degrades into storing plausible-looking code that nothing has ever run — which is worse than not storing it, because it looks authoritative.
Ongoing: skills go stale as the environment changes, and nothing invalidates them automatically. Progressive disclosure keeps their context cost bounded but adds a loading mechanism.
Skip it if you have no execution environment to verify against.
Seen in the atlas
Voyager is the clearest
implementation. Its SkillManager stores JavaScript
functions written by the agent, indexed by an LLM-generated description;
the write happens only inside if info["success"]:, where
success comes from a critic that inspects environment state. Retrieved
skills are injected as callable functions, so the library composes. It
also shows the failure modes: unbounded concatenation of every skill
into the JavaScript preamble sent to the environment on every step (the
model prompt is capped at five retrieved skills), retrieval with no
score threshold, versions written to disk with no lineage, no failure
memory, and one hardcoded exclusion standing in for a memory-worthiness
policy.
Hermes Agent applies the
same idea without the gate. Skills are Markdown files the agent creates
and edits through skill_manage, with provenance and usage
tracked separately; only names and descriptions occupy prompt space and
bodies load on demand — a better context strategy than Voyager's — but
nothing verifies a skill before it becomes durable.
Atomic Agent takes the
opposite position from Voyager and states it as a rule: its
procedures are derived alongside a parent lesson from the
same consolidator cluster, and cross-phase invariant 20 holds that the
runtime never auto-executes them — they are "advisory
text the agent reads and either follows or consciously deviates from."
Voyager buys empirical verification by making skills executable and
accepts the trust boundary that follows; Atomic Agent gives up
verification to avoid it. Both are defensible, and the choice is the
pattern's central tradeoff.
Acontext carries the gate over
prose skills. Its tasks table constrains
status IN ('success', 'failed', 'running', 'pending') as a
database CHECK, the task-update path queues a learning task only on a
terminal status, and test_running_does_not_append,
test_pending_does_not_append and
test_no_status_does_not_append assert the gate holds. Two
things make it partial: a failed task triggers distillation
as well as a success does, so the gate is on the task
having ended rather than on its having worked, and the skill written is
a Markdown SKILL.md, so nothing re-executes it to check
that it still does.
ScienceClaw, an OpenClaw
derivative outside the corpus and read without a pinned report,
demonstrates the scale end: its README states that "the agent writes new
SKILL.md files at runtime without any redeployment."
Runtime skill authoring is what the pattern looks like when the library
is the product, and it is where pruning stops being optional — the
utility signals below are the answers this atlas has to that
question.
MemOS mounts skill memory as one cube type among several, and agentmemory keeps procedural records alongside semantic ones; in both, procedure is one kind in a broader taxonomy rather than a design centre, and neither gates on execution.
OpenViking unifies memory, resources, and skills in one filesystem hierarchy — skills are retrievable through the same tiered mechanism as everything else.
Verel approaches the same territory from the opposite direction: it clusters failures into induced candidate rules and requires promotion gates before they become trusted. Read together with Voyager, the two halves of the missing system are visible — Voyager verifies successes and discards failures; Verel mines failures and gates promotion.
SESA answers the pruning question
with a trained reward, and shows what it costs. Its skill bank writes a
card only from a failure — the exact inversion of
Voyager's gate — and then measures every card it hands out:
retrieved_count, helpful_count and
hurt_count, all three written by the same rollout reward
that trains the model. A card whose net score has gone negative after at
least three retrievals is deleted, not demoted. The
reason it works is a precondition worth stating plainly: SESA is a
training loop, so the outcome is a scored answer rather than a guess
about whether the user was pleased. A library without that signal cannot
borrow the mechanism, only the wish for it.
Two failures sit beside it and both generalise. The eviction leaves
no record — _evict_negatives drops the
row, and _add_new_with_dedup compares new cards only
against the live bank, so a similar failure regenerates the card the
system just measured as harmful, back at score zero and needing three
more losses to leave again. And credit is assigned uniformly: all three
retrieved cards receive the outcome of one rollout, so a harmful card is
rewarded whenever it rides along with two good ones. The similarity
score that would support weighted attribution is computed on every
retrieval and attached to each card, and no caller reads it.
Agentic Context
Engine keeps the same counters outside a training loop and refuses
to let them delete anything. Every skill carries
used_count, helpful_count,
harmful_count and neutral_count, moved by
tag_skill calls from a model that judges each injected
skill against the run's outcome, and the prompt governing that model
tells it to use them "as one input among several … never as a hard
removal trigger", because a heavily-used skill accumulates harm
counts while still being net-positive. SESA acts on the signal
mechanically; this one treats it as evidence for a judgement.
autoharness answers the
pruning question with an opportunity-relative load rate — loads divided
by requests since the skill landed, a probation window, and a view that
pardons at graduation but never feeds the rate — and evicts to an
.archive/ folder rather than deleting. It then repeats SESA's regeneration failure by
construction: the reflector's index globs one directory level deep, a
committed test asserts the archived skill is absent from it, and the
promoter's create consults neither the archive nor the run
account of rejected intents, so a name the lifecycle retired can be
proposed again at zero use. Its write gate is lint rather than outcome:
six deterministic classes over the text, with nothing executed and
nothing observed about whether following the skill worked.
Neo4j Agent Memory supplies the half this pattern's gate leaves out. Its reasoning tier records traces through a context manager, so on a raised exception the error becomes the trace's outcome — meaning failures are stored by default, where a verified-execution gate by construction stores only successes. An agent that has failed the same approach four times has learned nothing if nothing wrote the failures down. Outcomes carry an indexable error kind, and a retrieved step arrives with its parent trace's outcome attached, so a step from a failed attempt cannot be read as precedent.
Ollama's built-in agent
was the smallest complete instance, and it treated loading a skill as a
privileged act — until the agent was removed from Ollama in
September 2026. Its whole procedural memory was four files: discovery
across four roots, a 1 MiB ceiling and front-matter validation, an
<available_skills> block of names and descriptions in
the prompt, and a skill tool that loads a body by exact
name. Two decisions transfer.
agent/tools/skill.go returns an unconditional
true from RequiresApproval, with the reason in
the comment — "Model-initiated loads require approval because a
skill's instructions can influence the rest of the run" — while
explicit user activation goes through a synthetic tool call that
bypasses the gate. Voyager and Hermes gate the write; this
gates the read, which is the operation that actually changes
the agent's behaviour. Its limit is that the approval prompt shows a
name, so the person approving has probably not read what they are
approving.
The second is the trust disclaimer, said twice to two audiences. The Go type comment reads "It never grants tool permissions; it is supplied to the model as ordinary tool-result content", and the system prompt tells the model the same thing: "Skills only provide instructions; use ordinary tools for filesystem or network access, with their normal approval rules." That costs one line and answers the question a retrieved instruction document always raises.
Against all of that, Ollama has no verification gate of any kind — no critic, no success signal, no usage tracking — because it also has no write path. A skill exists because a person wrote the file.
Forgetful stores skills as
rows beside memories — kebab-case name, description, Markdown body up to
100 KB, licence, compatibility, allowed tools, tags and an importance —
with import_skill and export_skill in the
Agent Skills SKILL.md format and a second vector table,
vec_skills, built from the description alone so a skill is
found by what it is for rather than by its body. The feature is off by
default (SKILLS_ENABLED=false), nothing executes a skill,
and nothing records whether following one worked. The ten
SKILL.md files in the repository's own skills/
directory are the other half of the pattern: they are the server's
memory policy — query before create, confirm before update or obsolete,
announce every save — shipped as procedures the agent loads, and the
server has no way to know whether it did.
Hivemind
(Activeloop) answers the pruning question without a training reward,
and then throws the answer away. Its write gate is the weak kind — a
model curator reading ten recent sessions, told to keep a pattern only
if it recurs across three exchanges and is not already covered, with
nothing executed. The interesting half is after the write. A
PreToolUse on an org skill arms a three-message judgment
window; the user's next prompt spawns a worker that rebuilds the
transcript around the invocation, appends the reaction, and asks a judge
one question phrased against sycophancy — "Ignore whether the user
seemed happy or polite — a praised-but-wrong answer is a FAILURE" —
with an unparseable or errored verdict returning success, so the judge
can miss a failure and never invent one. That is a reuse-quality signal
derived from ordinary human reaction rather than a scored rollout, and
it is the piece a library outside a training loop can borrow. The edit
it produces is bounded the way this page's supersession tradeoff asks
for: at most three anchored operations, a protected region the fast pass
may not touch, and a new version appended rather than an overwrite.
Two failures sit beside it. The new version is published to the whole
organisation under a comment reading "No approval gate by design:
detect → improve → publish, directly", and auto-pull writes every
author's skills onto every signed-in machine at the next session start —
so one person's bad turn rewrites a colleague's procedure before anyone
has read the diff. And the loop never closes: its meta log declares
proposed | applied | reverted, writes only
proposed, and reads the field nowhere, so the dedup
prevents re-proposing an identical edit and nothing distinguishes an
improvement from a regression. Declaring the states and not writing them
is how a library keeps editing in a direction no one has checked.
SkillCorpus is the pattern
at the other end of the supply chain: not an agent writing skills, but a
pipeline admitting other people's — ~821,000 crawled files
filtered by structural thresholds, an LLM judge over utility, robustness
and safety, and a cross-source near-duplicate merge. Its transferable
move is where the decisions live. Both judges write their verdict keyed
on the SHA-256 of the body they judged —
quality_judgments(content_hash PRIMARY KEY) and
dedup_judgments(pair_key) over a sorted hash pair — and the
build re-derives every exclusion from those caches before it exports. A
skill excluded for a cmd_injection flag is excluded again
the next time the same body is crawled, by the same verdict, and the
judge is never re-asked. That is the thing SESA's eviction above is
missing stated as a schema decision rather than a wish: an exclusion
keyed on the value survives regeneration, and one keyed on the row does
not. This library shows both, because the row-level markers here are
clobbered by a re-ingest and only the hash-keyed caches hold.
It also ships the test this page asks for.
test_an_unrelated_query_gets_nothing_from_the_local_source
builds twelve file-handling skills, asserts the weather query returns an
empty block, and asserts in the next line that the same directory still
answers "fill an acroform" — the third bullet below, with
the control that stops it passing vacuously. What it has none of is a
verification gate or a usage signal: no skill is executed, nothing
observes whether following one worked, and the record type it was
adapted from had counters and lineage fields that were deliberately
dropped.
Agent Memory
Distillation stores procedure at three granularities and retrieves
each at a different moment: a workflow insight and subtask examples
before the first turn, and a per-function example only when that
function's call returns an error
(bfcl/common/memory/injection.py:338-400). It is also the
counterexample on the success gate this pattern depends on. On BFCL the
gate is a --score-file argument whose default is empty, so
every teacher trajectory that did not force-quit becomes memory
(bfcl/common/scripts/teacher_build_memory_multi_turn.sh:21),
while its ToolSandbox builder keeps only scenarios at full milestone
similarity.
Browsentic puts the gate on
admission rather than on success, and puts it in front of a person. A
mapping run walks one host with read actions only and hands in a typed
report; the daemon renders it into a staging folder the skill loader
skips, and the note joins the prompt only after a person reads the exact
Markdown and presses Activate
(src/daemon/agent/site-map-store.ts:84-98,
:227-261; src/daemon/agent/skills.ts:87).
Retrieval is a domain predicate on the active tab's host, so a site's
notes cost nothing anywhere else. Two failures sit beside it. The prompt
introduces generated and hand-written notes under one preamble calling
them "the user's own words, not page content"
(src/daemon/agent/prompt.ts:40), so the review becomes a
promotion of page text to user voice. And its second procedural kind, a
recorded demonstration turned into named steps by a one-shot agent call,
becomes usable with no review at all
(src/lib/bridge/recording-store.ts:105-141) — the same
shape Cua has, where the person who
demonstrates never sees the generated text.
ripwire-rs shows the
staleness cost from the supply side. Its seventeen skills are adapted
from ripwire's and embedded into
the binary at build time, and they tell an agent to record a trade-off
with --quality-ack, scope it with --scope, and
expect notes beside --for output. The port's binary
implements none of the three. A procedure carried across a rewrite
describes the old implementation until something checks it against the
new one; here nothing does, and an agent that follows the skill believes
it recorded an acceptance the ledger never received.
MuscleMemory carries the
outcome gate to coding agents and adds the generality check this page
asks for. A session becomes a skill only when a test run passes after
the last edit, and the skill reaches a prompt only after a person
approves it and two later sessions, never the source, execute its
required capabilities and action shapes and re-run its own test after
their last change
(packages/musclememory/service.py:723-845,
retrieval.py:211-233). One failed check flags the revision
for good. It also keeps the failures Voyager discards: failed runs with
the same action sequence are diffed against the success by argument
shape and become avoid notes (service.py:441-489). Two
things weaken the gate. "Passed" is the exit status the client captured
for a command recognised as a test runner by name
(artifacts.py:18-77). And the hooks flag a skill only when
the session was handed it and its own test ran last and failed
(service.py:1232-1289), so a skill whose test is the whole
suite is blamed for any later failure of the suite.
Screenpipe settles who may
edit a skill with a hash rather than a flag.
AgentSkillStore::create records
created_by: screenpipe-agent and the file's SHA-256 in a
manifest at the store root, where an imported skill folder cannot place
one; a skill reads as agent-owned only while its file hashes to that
value, and patch demands the current hash
(crates/screenpipe-engine/src/agent_skills.rs:164-313). A
person who edits a skill by hand therefore takes it from the agent with
no setting to change, and
manual_changes_revoke_agent_write_provenance asserts it.
The admission side is weaker: creating a skill needs
confirmed: true, a field the agent fills in its own tool
call (:518).
Harness² stores skills as part
of whole adopted harnesses and serves them to the editor rather than the
executor. After each task a per-domain library receives the adopted tree
— skills, scripts, subagents, plugins and always-on files — with the
reflector's lesson, and every later task's editing sessions get the
whole directory copied into context
(harness2/core/library.py:106-152,
harness2/core/context.py:160-169). A component reaches
execution only when an editor copies it into the new harness, and
validation rejects a skill whose script did not come with it
(harness2/core/tree.py:324-333). There is no outcome gate:
adoption is a blind model choice over deliverables, made without any
selector session at k = 1, and a lesson is admitted when
its three fields are non-empty
(harness2/core/selection.py:360-399,
:494-501).
Cindy holds a one-off approach
back until it recurs. The nightly routine puts a skill draft first seen
in an owner conversation into a candidate list that no prompt loads,
promotes it only when a later night cites a new occurrence as evidence
or a person presses promote, and drops it for good when a person
declines
(apps/desktop/src/main/maker-ipc/botNightlyLearning.ts:532-575,
:634-647). The gate is recurrence, not execution: a
promoted skill has been seen twice and never run against an outcome, and
the teammate's own save_teammate_skill tool writes skills
directly when the owner asks.
Tests to require
- Store a skill, then execute the retrieved copy in a fresh context and assert it still succeeds — generality, not just recorded success.
- Assert that a failed attempt produces no durable procedural memory.
- Retrieve against an unrelated task and assert no skill is returned above threshold.
- Supersede a skill and assert the prior version remains retrievable with a lineage link.
- Compose: build a skill that calls a stored skill, then modify the callee and assert the caller's behaviour change is detected.
- Assert the injected skill context stays inside a token budget as the library grows.
- Execute a deliberately malicious stored procedure in the sandbox and assert containment.
- Track reuse and assert that never-reused skills are surfaced for pruning.