AgentsOpen SourceFreeActiveMachine-verified· beginner · ~10 min setup

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.

by Shilpa Mitra· verified today· v1.0.0

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. 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. 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 today
  • skill-okcontainstimeout 30s · max $0

    Expected: skill OK: /deploy-staging, description under 60 chars, 4 sections in house order

  • clean-exitexit_codetimeout 30s · max $0

    Expected: 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

Liked this workflow?

Get new verified workflows in WebAfterAI, three issues a week (Tue, Thu, Sat).