OpenClaw Learning Loop Architecture: How Repeated Failures Become Skills That Actually Load
Capturing a lesson is the easy half. Most self-improving agent setups stop there, and the lesson sits in a file nobody reads.
On September 3 my nightly skill job did everything right. It found two recurring failure categories that had no skill covering them, wrote a proposal for each (deployment-gate-discipline and message-delivery-discipline, stamped with the date and a short hash), and handed them off for approval. Then they sat there. The approval step expected a reply over Telegram, and no Telegram approval route had been configured, so the proposals waited for someone to type /approve in a web UI or a terminal that nobody had a reason to open.
The loop worked. The handoff went nowhere.
What the Usual Guides Cover
Read the popular write-ups on making an OpenClaw agent self-improving and you get the same good skeleton. The agent logs corrections and errors to a lessons file (some versions split it into LEARNINGS.md and ERRORS.md). A scheduled review consolidates entries. Lessons that hold up get promoted into AGENTS.md or MEMORY.md, usually after a human signs off. One of them adds stable pattern keys so that two differently worded entries about the same failure count as a recurrence.
All of that is worth doing. None of it answers the question that bit me, which is what happens between "a human approved this" and "the agent that needs it behaves differently tomorrow." That gap is where this page spends its time.
Three Jobs With One Writer Each
My fleet runs the loop as separate scheduled jobs, in a fixed order every morning, and each one writes a single line to a shared work log when it finishes. The failure-replay job goes first. It looks back over recent failures, groups the ones that share a pattern, and decides which patterns deserve a signal. The skill harvester runs next, reads those signals, and either proposes a new skill or marks the signal resolved by an existing one. The daily digest runs last and tells the operator what, if anything, needs them.
2026-10-20 · skill-harvester · 0 skill proposals, 0 signal resolutions 2026-10-22 · failure-replay · 4 failure patterns found, 2 signal actions 2026-10-22 · skill-harvester · 2 skill proposals, 1 signal resolutions
Zero proposals on October 20 was a good day. A harvester that feels obliged to produce something every morning will produce duplicates, and a fleet with four skills that say the same thing in slightly different words is harder to steer than a fleet with one. The separation matters for a less obvious reason too. Each job owns its own output and nothing else, which is the one writer per fact rule applied to learning. The replay job never edits skills. The harvester never decides what counts as a failure.
Dedupe by Slug Before You Write Anything
Before the harvester proposes a skill, it checks the skills directory for a slug that already covers the category. On September 4 five signals fired that all had skills on disk already (deployment-enforcement, message-discipline, mock-data-prevention, privacy-firewall, context-bloat-prevention), because a report generator had dropped the fields marking them resolved. The harvester read each skill file, confirmed it had real content, and authored nothing. That restraint is the whole point of the check.
# harvest.py: propose only when no existing skill owns the category
def propose(signal, skills_dir):
owner = find_skill_for(signal["category"], skills_dir)
if owner and has_body(owner):
return {"action": "resolve", "by": owner} # point at it, write nothing
slug = f"{signal['category']}-{today()}-{short_hash(signal)}"
if slug_exists(slug):
return {"action": "skip", "reason": "duplicate slug"}
return {"action": "propose", "slug": slug, "status": "pending_approval"}has_body is there because an empty skill file with the right name is worse than no file. It satisfies the dedupe check and teaches nothing.
The Approval Route Has to Exist Before the Proposal Does
Every guide says a human should approve new rules. I agree, and the human-in-the-loop tiers on this site treat a new skill as a change to how agents behave, which puts it above anything an agent may approve for itself. What the guides skip is checking that the approval channel works. My two September proposals were blocked by a missing route, and the only record of it was a line in a log that said so in plain words.
The fix I would build is small. The harvester checks the route at startup, and if it cannot reach the approver on the channel the approver actually reads, it still writes the proposal and adds one line to the morning digest saying how many proposals are pending and where to approve them. Anything pending for more than a week moves to the top of that digest. Proposals are cheap to write and expensive to forget, because the failure they describe keeps happening while they wait.
Pick the channel the operator already lives in. For mine that is a phone.
Approved Is Not Loaded
A skill file on disk changes nothing until a session reads it. In OpenClaw that happens through two paths, and both can fail quietly. The first is routing: a skill is surfaced when its trigger description matches what the session is doing, which the skill routing piece covers in detail. The second is boot context, the short block of text every session loads before it does anything, and that block is capped. My sessions print the last five entries from an errors file at startup. Five, on purpose, because every line in boot context is paid for in every session (the context window guide has the arithmetic).
The bug that taught me this was not in the learning loop at all. The fleet had a working router that sent hard problems to a stronger model, built on June 13 and confirmed working in August. The briefing file that served as one agent's actual operating instructions, 555 lines long, never mentioned it once. The agent had never known to call it. Weeks of "why does this one seem less capable on hard problems" came down to a capability nobody had wired into the place the agent reads.
The acceptance test I want for every new skill is boring: start a fresh session, give it a prompt that should trigger the skill, and check that the skill's name shows up in what the session loaded. If it does not show up, the skill is not done.
A Good Rule Carries Its Own Check
Generic lessons decay fast. "Be careful with print layouts" would have done nothing for the book interior that failed Amazon KDP review on August 30, when full-bleed chapter images ran past the physical page box and the upload came back with both image and margin errors. The rule that went into the errors file is narrow and testable: for this title, uniform 6x9 with no bleed, threshold art inset at least 0.5 inches from every trim edge, and an actual pass in KDP Previewer before anyone calls the geometry accepted.
That last clause is the part I would copy. A rule that names the check which proves it was followed can be enforced by the next agent without any memory of why it exists, and a rule that only names a feeling depends on the agent feeling the same way.
Write the date on every rule.
Where to Start
If you have nothing yet, start with the errors file and the boot hook that prints its tail, because that alone stops the same correction from being needed three times. Add the replay job once you have more than a week of logs to replay. The harvester comes last, and it should ship with its dedupe check and its approval route on the first day. Shipping it without them builds a machine that writes skills into a drawer.
The loop is only finished when a lesson from Tuesday changes what an agent does on Wednesday, and you can point at the line in the session's boot output that made it happen.
Internal Links & Further Reading
- OpenClaw Alert Architecture →
Where the errors-file rule came from, and why resolved state lives outside generated reports.
- OpenClaw Skill Routing Architecture →
How a skill on disk gets matched to the session that needs it.
- OpenClaw Human-in-the-Loop Architecture →
The approval tiers a new skill has to pass through.
- OpenClaw Fleet Registry Architecture →
The one-writer-per-fact rule the three learning jobs follow.
FAQ
Q: Should the harvester be allowed to approve its own skills?
No. A skill changes behavior across every session that loads it, so it belongs in the same tier as a config change to a production service. Let the harvester write proposals freely and make the approval cheap, one tap on the channel the operator already reads.
Q: How many entries should the boot hook print?
Few. Five works for my fleet. Rules that keep mattering should graduate into a skill with a proper trigger, which frees their slot in boot context for the next fresh lesson.
The Bottom Line
Keep the learning jobs separate, each owning one output. Check for an existing skill before proposing a new one. The approval route deserves the most suspicion, because a proposal that can't reach its approver fails without making a sound, so test it before the first proposal depends on it. Write rules that name the check proving they were followed.
Then open a fresh session and look for the skill in what it loaded. That is the test.
Skip the trial and error
Get the OpenClaw Starter Kit — config templates, 5 ready-made skills, deployment checklist. Everything you need to go from zero to running in under an hour.
$14 $6.99
Get the Starter Kit →Also in the OpenClaw store
Get the free OpenClaw deployment checklist
Production-ready setup steps. Nothing you don't need.