/drain
Fold the pending learning queue into the knowledge base — route each item to the wiki, the journal, or an agent's knowledge base, then ack it so it's deleted.
/drain is the consuming half of the v2 learning loop. Capture is automatic and deterministic: Claude marks learnings during a conversation (a visible 📝 Learned: line plus a hidden <!-- learning --> marker), and atl tick transfers each one into a durable bbolt queue exactly once. This skill is the LLM half the CLI can't do itself — and it now runs automatically in the background: when the queue is non-empty the hook signals the agent, which spawns a background drain subagent (per the learning-capture rule) rather than waiting for a manual /drain. Run manually only to force a pass. It does two judgment jobs:
- Mine the conversation for learnings the agent forgot to mark — the user's corrections, reverts, repeated mistakes — and enqueue them like any marker. Marker capture only catches what the agent noticed, and the mistakes worth not-repeating are exactly the ones it didn't.
- Quality-gate, then integrate each queued item — decide whether it's worth keeping (Save / Improve / Absorb / Drop), then route the keepers to the wiki, the journal, or an agent's knowledge base, and ack each.
When to use it
- When
atlreports "N learning(s) pending" at session start. - When
atlfires the capture-watchdog signal (atl: capture-watchdog (learning) — no learning markers for N assistant turn(s) …): a substantive stretch passed with no learning markers, so the queue may be empty — the mining step is the run's purpose; it sweeps the flagged stretch and recovers what should have been marked. The watchdog measures each capture channel separately, so a(profile-fact)signal is/profile-drain's trigger rather than this skill's; both can fire on the same turn. - Any time you want to process the learning queue manually.
The CLI half is exposed by atl learnings: status shows pending counts, peek lists the items this skill consumes, and ack deletes a processed item. The queue is keyed by the current project directory, so run the skill from the project whose learnings you want to drain.
Why ack = delete
The queue guarantees exactly-once delivery and dedup by content hash. An acked item is deleted from the queue, so it can never be re-reported — the v1 re-report bug class is structurally gone. The mining step does read the recent conversation, but anything it captures is enqueued like a marker and deduped by the same content hash, so re-running /drain is safe: a lesson you already saved re-enqueues to a no-op, and an empty queue with nothing new to mine is a no-op too.
Procedure
1. Mine the conversation for unmarked learnings
Before peeking the queue, harvest what the agent forgot to mark. Sweep the conversation flow (prose only — tool calls and results are stripped):
atl learnings transcript --channel learningThe --channel flag is what makes this a sweep: it resumes from where the last drain stopped and moves the learning cursor forward, so successive drains cover a session completely. Without it the command is a plain read of the most recent prose, and whatever accumulated between two drains is read by neither. If it reports transcript still unmined, the drain reports that in its summary; a large backlog drains across successive runs rather than in one, since the 256 KB budget exists to fit the mining subagent's context.
Scan it for durable learnings that were never captured as a marker: user corrections (the user said the agent was wrong and how to fix it), reverts (an approach was tried, rejected, replaced), and repeated mistakes (the same class of error recurred). For each, write a one-line learning stating the lesson with its why, and enqueue it exactly like a marker:
atl learnings _enqueue learning "<the lesson, with its reason>"Be strict — mine only what's worth never-repeating; a one-off or anything already obvious is noise. The queue dedups by content hash, so re-mining the same lesson is a safe no-op, but the real filter is the quality gate in step 3. If nothing qualifies, enqueue nothing.
2. Peek the queue
Run in the project directory:
atl learnings peek --channel learning --jsonEach item is {id, channel, payload, enqueued_at} — now both agent-dropped markers and anything you just mined. The payload is free text. If the list is empty, report "nothing to drain" and stop.
3. Quality-gate each item before persisting
A learning store rots when it bloats, so don't save blindly. For each item, first grep the existing knowledge (.atl/wiki/, .atl/journal/, any owning agent's children/), then give a holistic verdict:
| Verdict | When | Action |
|---|---|---|
| Save | New, durable, worth keeping | Route + write (steps 4–5) |
| Improve-then-Save | Worth keeping but vague as written | Sharpen the wording, then route + write |
| Absorb | An existing page/entry already covers it | Merge the nuance into that note — no new file — then ack |
| Drop | Trivial, one-off, redundant, or obvious | Ack, write nothing |
This is a holistic judgment, not a numeric score. Lean toward Absorb over a near-duplicate page and Drop over a marginal one — the bar for a standalone entry is "a future session would be glad this exists." Absorb and Drop both end in an ack; only Save / Improve-then-Save proceed to routing.
4. Route each kept item by the shape of its payload
The v2 marker carries no topic/kind metadata — you infer the destination from the payload, and derive a kebab-case topic from the content (one concept: auth-refresh, redis-ttl).
| Payload shape | Destination |
|---|---|
| Topic-shaped current truth ("the right way to do auth is …") | Wiki — <proj>/.atl/wiki/<topic>.md (replace/merge if it exists) + journal |
| Time-stamped narrative ("we tried X, then Y, Y worked") | Journal only — <proj>/.atl/journal/<YYYY-MM-DD>.md (append) |
| Domain knowledge for a specific installed agent | Agent KB — <scope>/.claude/agents/<agent>/children/<topic>.md + rebuild that agent's ## Knowledge Base + journal |
| A repeating workflow, a crystallized convention, a new domain with no owning agent, or an identity expansion of an agent/skill | Structural — do NOT write autonomously; collect and propose |
To find the owning agent, look at the installed agents under <proj>/.claude/agents/ and ~/.claude/agents/ (project shadows global). If no agent clearly owns it, route to the wiki instead. Always include the WHY in what you write — a fact without its reason rots.
5. Write, then ack — one item at a time
Non-structural writes are silent (no confirmation). After each item is integrated, ack it so it leaves the queue:
atl learnings ack <id>Ack only after the write succeeds. If you can't integrate an item, leave it (don't ack) and note it in the report.
6. Structural changes — propose, never auto-apply
For the "structural" row, do not author agents/skills/rules silently. Collect them and, at the end, propose each one through AskUserQuestion (new agent / new skill / new rule / identity change). This is the reactive-creation boundary: a human confirms structural growth. Ack a structural item only once its proposal is resolved.
7. Report
Summarize what landed where: per item, topic → destination; list any new files created and any structural proposals. Keep it short.
The CLI half
/drain drives deterministic verbs under atl learnings:
atl learnings transcript --channel learning # resume the mining sweep (step 1)
atl learnings status # pending counts per channel for this project
atl learnings peek # list pending items (human-readable)
atl learnings peek --json # the full machine-readable list the skill consumes
atl learnings peek --channel learning # filter to one channel
atl learnings ack <id> # delete a processed item from the queueFlags:
transcript --limit <n>— read the most recent N transcripts (default 2);--jsonemits role/text records.peek --json— emit pending items as JSON (id, channel, payload, enqueued_at).peek --channel <name>— filter to a single channel (e.g.learning).
status takes one optional flag — --json emits the pending counts as JSON. ack takes exactly one argument — the item id (an unambiguous prefix of it also resolves). The mining step itself enqueues with the hidden atl learnings _enqueue learning "<lesson>" helper (the same one capture uses), so dedup lives in the queue.
Channels
The queue is multi-channel. /drain processes the learning channel only. The profile-fact channel is handled by the shipped profile-team's /profile-drain (installed with profile-team), not here.
Agent KB rebuild
An agent's knowledge base is agent.md + a children/ directory. Each child is one topic and carries knowledge-base-summary frontmatter:
---
knowledge-base-summary: "<one-line summary used in agent.md's Knowledge Base section>"
---
# <Topic Title>
<the actual knowledge — patterns, examples, the why>After writing or updating a child, fully rebuild agent.md's ## Knowledge Base section from the children's frontmatter (sorted by filename). That section is derived, not hand-edited — it's replaced wholesale each run. Skills have no equivalent: they are procedures, not knowledge stores, so /drain rebuilds only an agent's ## Knowledge Base — there is no skill "Accumulated Learnings" section.
Wiki index rebuild
Whenever a /drain run writes or updates a .atl/wiki/ page, it rebuilds the <!-- wiki:index --> block in the project's CLAUDE.md so the knowledge map stays in sync — one - [topic](.atl/wiki/topic.md) — summary line per page, sorted by filename, derived (not hand-edited). If the project has no CLAUDE.md, the rebuild is skipped (atl init / atl install create the file). See Claude Code conventions for the block's format and placement.
Examples
Drain after a session-start prompt
A new session opens and atl reports two pending learnings. Process them:
atl learnings peek --channel learning --json[
{
"id": "9f1c2a3b4d5e",
"channel": "learning",
"payload": "Redis cache TTL should be 30 minutes, not 15 — 15 caused cold-start thrash under load.",
"enqueued_at": "2026-06-21T09:14:02Z"
}
]Write redis-ttl to the wiki (current truth) and append a dated bullet to today's journal, then ack:
atl learnings ack 9f1c2a3b4d5eCheck the queue without draining
atl learnings statuslearning queue — pending by channel:
learning 2Scope
Wiki and journal are project knowledge under <proj>/.atl/. Agent KB follows the agent's install scope — a project .claude/ shadows global ~/.claude/.