Hermes /learn: author a reusable skill from a source, not by hand
Use Hermes Agent's /learn to turn a doc, a repo, or a workflow you just performed into a standards-compliant SKILL.md (and an automatic slash command), instead of hand-writing a skill file that drifts from the real docs.
Run this workflow
CI-verified, 2/2 fixtures passing.
Build this with your agent
One copy-paste hands Claude Code, Codex, or Cursor the full recipe, steps included, nothing to fetch.
Intended Use
Anyone using Hermes who wants reusable skills authored from real sources. CI validates a SKILL.md against the format contract a /learn skill must meet: it parses, name is set, the description is under the 60-char house limit, the canonical sections appear in order, and the derived slash command name is valid. The agent actually sourcing the material and writing a faithful skill is fenced, because no green check can promise a model read your docs right.
Not for
- Trusting a captured workflow blindly, a procedure the agent over-fits to one-off state is the easiest kind to get wrong; review it before you rely on it
- Unattended skill writing without the gate, the background self-improvement review writes freely unless skills.write_approval is true
- Treating the badge as a faithfulness check, it covers the format, not the judgement
The Stack
Tested Against
Hermes Agent (Nous Research, 2026-06)agentskills.io SKILL.md standardruby@3.x (YAML stdlib)Side effects & data flow
- Network
- none, local only
- Writes
- ./skills/deploy-staging/SKILL.md
- Credentials
- none required
Prerequisites
- Hermes Agent installed with a working chat (curl install + hermes model), to actually run /learn
Steps
- 1
Validate the SKILL.md format contract a /learn skill must meet
After /learn writes a skill, CI checks the output against the house standard: frontmatter parses with a name, the description is under 60 characters, the canonical sections (Overview, When to use, Steps, Verification) appear in that order, and the slash command derived from the name is valid. The fixture below stands in for a /learn output; the agent actually authoring it is fenced.
mkdir -p skills/deploy-staging cat > skills/deploy-staging/SKILL.md <<'MD' --- name: deploy-staging description: Deploy the app to staging and verify health. --- ## Overview Deploy the current branch to the staging server and confirm it is healthy. ## When to use When you need a fresh staging deploy of the current branch. ## Steps 1. Push the current branch. 2. Trigger the staging deploy. 3. Wait for the health check to pass. ## Verification Confirm the staging health endpoint returns 200. MD ruby -ryaml -e ' text = File.read("skills/deploy-staging/SKILL.md") parts = text.split("---", 3) abort "BAD: no frontmatter block" unless parts.length >= 3 fm = YAML.safe_load(parts[1]) || {} body = parts[2].to_s name = fm["name"].to_s desc = fm["description"].to_s abort "BAD: frontmatter must set a name" if name.empty? abort "BAD: frontmatter must set a description" if desc.empty? abort "BAD: description must be under 60 chars (house standard)" unless desc.length < 60 cmd = name.downcase.gsub(" ", "-") abort "BAD: derived slash command name is not valid" unless cmd =~ /^[a-z][a-z0-9-]*$/ required = ["## Overview", "## When to use", "## Steps", "## Verification"] positions = required.map { |h| body.index(h) } abort "BAD: a required section is missing" if positions.any? { |p| p.nil? } abort "BAD: sections are out of house order" unless positions == positions.sort puts "skill OK: /" + cmd + ", description under 60 chars, " + required.length.to_s + " sections in house order" ' - 2
Run /learn for real (the model step, not checked by CI)
In Hermes, point /learn at a source: a local dir (/learn the REST client in ~/projects/acme-sdk, focus on auth), an online doc (/learn https://docs.example.com/api/quickstart), or a workflow you just walked it through (/learn how I just deployed the staging server). Read the resulting SKILL.md before you trust it, and set terminal.backend docker if the skill contains shell steps. The sourcing and authoring are fenced.
Eval, 2 fixtures
Last passed: verified todayskill-okcontainstimeout 30s · max $0Expected:
skill OK: /deploy-staging, description under 60 chars, 4 sections in house orderclean-exitexit_codetimeout 30s · max $0Expected:
0
Results
Most hand-written skills rot: the SKILL.md drifts from the source and later tells the agent to call a flag that no longer exists. /learn flips the order, the live agent reads the source with its own tools (read_file, search_files, web_extract) and authors the skill, following the agentskills.io standard. This recipe mechanically validates that output format. It does NOT and cannot promise the agent summarized your source faithfully, that judgement is fenced. Flip skills.write_approval on before letting the background review write skills unattended.
Did this work for you?
Our CI checks the setup runs. You tell us if the whole thing worked. Tell us straight.
Related workflows
- Text your own AI assistant on WhatsApp: Hermes wired to FreeLLMAPI
- FreeLLMAPI: one socket, sixteen free model tiers with auto-fallback
- Flue: define a sandboxed headless agent and deploy it anywhere
- Build the Fugu pattern in the open: fan out, assign roles, verify
- Sakana Fugu: A/B it on your own task before you migrate
- Run GLM-5.2 fully local on a Mac Studio and drive it with Hermes
Liked this workflow?
Get new verified workflows in WebAfterAI, three issues a week (Tue, Thu, Sat).