From Failure to Skill: Designing a Universal /learn Command for Coding Agents
Run the same agent task twice on two different machines and you will often see the same pattern: it fails the second time for a reason it already recovered from in the first session.
The agent fixed the issue in-session, but the skill did not change. The next invocation starts blind again.
After seeing this loop repeat across multiple repositories and environments, the root cause is consistent: there is no built-in feedback path from execution recovery to durable skill logic.
In this article, skill means a reusable task instruction layer, regardless of host:
- Claude Code: custom slash-command files in
.claude/commands/ - OpenCode: command definitions and reusable prompt instructions
- Codex: command/macro prompts that encode repeatable procedures
A /learn command closes this gap.
After a task is completed, /learn converts runtime fixes and user guidance into reusable behavior: update the relevant skill when one exists, or create a new skill when none was used.
Why this matters for teams
Without a learning step, each task is isolated and expensive:
- repeated failures consume engineering time,
- repeated retries increase token usage,
- repeated intervention lowers trust in automation.
By implementing /learn, teams continuously improve skill quality and reduce manual rescue work over time.
| Situation | Without /learn | With /learn |
|---|---|---|
| Agent fails due to missing precheck | Same bug reappears later | Skill gets a new precheck and fallback |
| Agent succeeds only after manual intervention | Knowledge stays in chat history | Resolution is encoded as reusable procedure |
| Skill is almost correct but needs user guidance | Repeated back-and-forth every run | User guidance is converted into explicit skill behavior |
| No skill existed for the task | Agent improvises each time | New skill is created for future runs |
A broader pattern: Execution-Driven Skill Refinement (EDSR)
/learn is the command interface.
The methodology behind it is Execution-Driven Skill Refinement (EDSR):
- Observe the real execution trace.
- Extract the concrete failure and successful recovery path.
- Refine the skill system with minimal, verifiable changes.
- Reuse that refinement on the next run.
This framing matters because the value is not the command name itself; the value is the repeatable learning loop.
What /learn must do
A robust /learn command should follow five rules:
- Evidence first: learn from the real execution trace, not from generic advice.
- Minimal edits: patch only what caused the failure.
- Dual path:
update existing skillorcreate new skill. - Portable behavior: same logic in OpenCode, Claude Code, and Codex.
- User-guided focus: accept a short user hint about what to prioritize.
Optional user hint in /learn
/learn should accept a short prompt after the command so the user can specify what the agent must learn.
Example:
/learn prioritize permission prechecks and non-root fallbacks for this environmentThis hint should guide prioritization, not replace execution evidence.
Universal decision logic
This is the core rule set (EDSR decision gate):
IF one or more skills were used during the failed task:
update the most relevant skill
ELSE:
create a new skill from the successful recovery pathIn practice, the decision can be slightly stricter:
- Update skill when failure is inside its scope.
- Create new skill when no existing skill owns that scope.
- Return "no_change" only when failure was unrelated to process (e.g., external outage).Recommended /learn prompt (portable contract)
Use this as the command prompt body:
You are in LEARNING MODE.
Your task is to improve the agent's skill system using evidence from the just-finished task.
INPUTS
- Task transcript
- Tool call history and errors
- List of skills used (if any)
- Final successful sequence (what actually worked)
- Optional user hint (short prompt passed after `/learn`)
OBJECTIVE
Convert the failure + recovery into reusable skill logic.
DECISION POLICY
1) If at least one skill was used and the failure is inside that skill's scope, PATCH that skill.
2) If no skill was used, or no existing skill owns the solved problem, CREATE a new skill.
3) If evidence is insufficient, output no_change with missing evidence.
4) Use the optional user hint as a prioritization signal, never as a substitute for evidence.
CONSTRAINTS
- Keep changes minimal and concrete.
- Do not add secrets, tokens, personal paths, or machine-specific constants unless unavoidable.
- Prefer prechecks before expensive actions.
- Add explicit fallback steps for known failure modes.
- Include verification steps that confirm the fix.
- If user hint conflicts with evidence, follow evidence and report the conflict.
- Before modifying an existing skill, check whether a Git repository is defined.
- If no Git repository is detected, create a backup copy of the skill file first, then apply the modification.
OUTPUT FORMAT (JSON)
{
"action": "update_skill | create_skill | no_change",
"target_skill": "skill_name_or_null",
"problem_summary": "short description",
"root_cause": "technical cause",
"user_hint_applied": "how the optional hint influenced the change",
"backup": {
"required": "true_if_no_git_repo_else_false",
"created": "true_or_false",
"path": "backup_file_path_or_null"
},
"skill_patch": {
"trigger_conditions": [],
"prechecks": [],
"steps": [],
"fallbacks": [],
"verification": []
},
"new_skill": {
"name": "if action=create_skill",
"purpose": "what it solves",
"when_to_use": [],
"procedure": [],
"failure_handling": [],
"done_checks": []
},
"risk_notes": []
}Example (permissions in PDF-to-text workflow)
Imagine a subagent using a pdf-to-text skill in a real local environment.
Before /learn
Run 1 looked normal at first, then failed:
tool: pdftotext ./docs/report.pdf ./out/report.txt
error: Permission denied: ./out/report.txtThe agent asked for help, the user suggested writing to /tmp, and the task finished manually:
tool: pdftotext ./docs/report.pdf /tmp/report.txt
result: successThe task was completed, but nothing in the skill changed yet.
/learn is executed
The user ran:
/learn prioritize permission prechecks and safe fallbacks for local restricted environmentsFrom that trace, /learn updated the existing skill by adding:
- a write-permission precheck on the output path,
- a fallback branch to
/tmpwhen the target directory is not writable, - a verification step that confirms the output file exists and is not empty.
After /learn
Next time, on the same machine, the skill handled the issue without extra user interaction:
precheck: ./out is not writable
fallback: switching output to /tmp/report.txt
tool: pdftotext ./docs/report.pdf /tmp/report.txt
verification: output exists and size > 0
result: successThis is the key value: the first failure required back-and-forth, the next run did not. The fix moved from chat memory into skill behavior.
Example 2 (missing binary fallback in JSON workflows)
The same pattern also applies when required tools are unavailable.
Before /learn
tool: jq -r '.items[].id' ./data/records.json
error: jq: command not foundThe user suggested a Python fallback and the task succeeded:
tool: python3 -c "import json; d=json.load(open('./data/records.json')); print('\n'.join(str(i['id']) for i in d['items']))"
result: successAfter /learn
The skill can be updated to:
- precheck
command -v jq, - use
jqwhen available, - fallback to Python parsing when
jqis missing, - verify that at least one ID was produced.
This validates the pattern beyond one domain: permission failures and missing-binary failures can both be converted into stable, reusable logic.
Host integration
The core behavior is portable if the host passes the same contract.
Contract each host must provide
At runtime, /learn needs:
- the just-finished task transcript,
- tool call history and errors,
- list of skills used,
- final successful sequence,
- optional user hint,
- writable access to skill files.
Concrete implementation: Claude Code
Create .claude/commands/learn.md in your repository:
---
description: Convert the just-finished task's failure and recovery into a reusable skill update or new skill.
---
You are in LEARNING MODE.
Your task is to improve the agent's skill system using evidence from the just-finished task.
[Paste the full portable /learn prompt contract from this article]Then run it inside the project:
/learn prioritize permission prechecks and safe fallbacks for this environmentBecause Claude Code exposes files in .claude/commands/ as slash commands, this registration is enough to make /learn callable per project.
OpenCode and Codex mapping
For OpenCode and Codex, register /learn using each host's command/macro mechanism, but keep the prompt contract and JSON output shape unchanged.
Portability comes from a stable contract, not from identical host APIs.
Safety checks before applying changes
Before persisting an update, /learn should enforce a mechanical gate:
-
Scope check The agent maps the failure to specific skill sections (
trigger_conditions,prechecks,fallbacks,verification) and rejects edits outside that scope. If unrelated sections change, the action must downgrade tono_changeor request narrower evidence. -
Regression check The agent replays at least one previously successful scenario (from history or documented done-checks) against the new logic. If a prior success path no longer passes, the patch is rejected or split into guarded branches.
-
Specificity check The agent verifies that new steps are executable and concrete (real commands, explicit conditions), not vague advice. It also checks for overfitting: machine-specific constants, usernames, absolute paths, and secrets must be removed or parameterized.
-
Verification check Every new fallback must include a success condition (
file exists,exit code,non-empty output,expected schema). If success cannot be observed, the patch is incomplete and should not be persisted.
Risks and limitations
/learn improves reuse, but it also introduces failure modes that must be managed.
Skill drift can accumulate as environments change; conflicting updates can appear when multiple machines learn different behaviors; and unsafe learned steps can leak into CI/CD if security boundaries are not enforced.
To reduce these risks, keep skill updates versioned in Git, require review for high-impact skills, run lightweight regression checks before merge, and explicitly block secrets or privileged commands in learned patches.
Why this over other approaches?
/learn does not replace model fine-tuning or long-term memory. It complements them.
- Fine-tuning (for example LoRA) is strong for broad behavioral shifts, but too heavy for frequent environment-specific operational fixes.
- Conversation memory features retain context, but memory alone is not a structured, auditable skill artifact.
- ReAct-style memory augmentation helps retrieval, but still needs a deterministic procedure for turning recovery traces into maintained instructions.
/learn focuses on the operational layer: small, explicit, reviewable changes that can ship quickly.
Conclusion
/learn is not a convenience command.
It is the execution-to-skill feedback loop that turns one-time recoveries into durable behavior.
When the agent fails and then succeeds, that path should not disappear in chat history. It should become part of the skill system.
That is how agents stop repeating the same mistakes:
- update the skill that failed,
- or create the skill that was missing,
- and carry that improvement into the next task.
