Hermes Agent skills are the engine behind reliable, repeatable AI agent behavior. A skill is a markdown file that captures exactly how to perform a task — which commands to run, what pitfalls to avoid, and how to verify success. When you version-control those skills with Git and test them in Docker containers, you turn one-off agent sessions into a maintainable, production-grade system.
A skill is a SKILL.md file with YAML frontmatter and a markdown body. It lives in the agent's profile directory and is loaded automatically when the task matches. Here's a minimal example — a skill for deploying Docker containers:
---
name: docker-deploy
description: Deploy a Docker Compose stack to a remote server.
category: devops
---
# Docker Deploy
Deploy Docker Compose stacks via SSH.
## Triggers
- "deploy the stack"
- "push to production"
## Workflow
### 1. Build images
docker compose build
### 2. Test locally
docker compose up -d && curl -f http://localhost:3000/health
### 3. Push to server
scp docker-compose.yml root@server:/opt/stack/
ssh root@server "cd /opt/stack && docker compose up -d"
## Pitfalls
- Always test locally before pushing
- Check disk space on target server first
The frontmatter (name, description, category) is how Hermes discovers and organizes skills. The markdown body is loaded into the agent's context when a task matches the trigger keywords or description.
Skills follow a four-stage lifecycle that mirrors software development:
Let's walk through each stage with real commands. First, verify that Hermes can manage skills:
$ hermes skills list --category devops
docker-deploy Deploy a Docker Compose stack to a remote server.
fullstack-docker-deployment Deploy full-stack Node.js + Prisma + SPA (Vite) apps
overseas-nodejs-deployment Deploy Node.js + PostgreSQL Docker Compose apps
Create a skill after you've successfully completed a complex, multi-step task. The best skills come from tasks that took 5+ tool calls and overcame errors. Use the skill_manage tool through Hermes:
$ hermes skill create \
--name "postgres-backup-restore" \
--category "devops" \
--description "Backup and restore PostgreSQL databases in Docker"
Skill created: ~/.hermes/profiles/default/skills/devops/postgres-backup-restore/SKILL.md
Or write the SKILL.md directly and place it in the right directory. The skill format is straightforward — every skill needs a clear trigger condition, numbered workflow steps, a pitfalls section, and verification steps.
Testing a skill means running Hermes Agent in an isolated Docker container and asking it to use the skill. This catches missing dependencies, wrong paths, and environment assumptions baked into the skill.
Start a fresh Hermes container with your skill mounted:
$ docker run -d --name hermes-skill-test \
-v $(pwd)/skills/postgres-backup-restore:/root/.hermes/profiles/default/skills/devops/postgres-backup-restore \
-e HERMES_API_KEY=$HERMES_API_KEY \
hermes-agent:latest
$ docker logs -f hermes-skill-test
Then ask Hermes to use the skill on a test task:
$ echo "Backup the test database" | docker exec -i hermes-skill-test hermes run -
The key insight: Docker gives you a clean slate every time. No leftover environment variables, no stale cache, no packages you forgot to document. If the skill works in a fresh container, it'll work on any server.
Skills are text files — they belong in version control. A dedicated Git repository for your Hermes profile's skills/ directory gives you audit history, rollback capability, and a clean deploy path:
$ cd ~/.hermes/profiles/default/skills
$ git init
$ git add .
$ git commit -m "Initial skill set: docker-deploy, postgres-backup, content-publisher"
$ git remote add origin git@github.com:team/agent-skills.git
$ git push -u origin main
Now your skill set is versioned. When you patch a skill during a live session (more on that below), commit the change:
$ git add devops/docker-deploy/SKILL.md
$ git commit -m "docker-deploy: add disk space check before SCP, fix SSH port"
$ git push
On the production server, pull to update:
$ ssh production-server
$ cd ~/.hermes/profiles/production/skills
$ git pull origin main
git log to see which skill version was active. You can bisect skill changes to find exactly when a regression was introduced.This is the most powerful part of the workflow. During a live session, when you discover that a skill is missing a step or has wrong commands, patch it immediately — don't wait to be asked:
$ hermes skill patch \
--name "docker-deploy" \
--old "scp docker-compose.yml root@server:/opt/stack/" \
--new "scp -P 2222 docker-compose.yml root@server:/opt/stack/"
The agent also patches skills automatically. When Hermes loads a skill and hits a pitfall that the skill doesn't cover, it updates the skill to include the new pitfall. This means your skill library gets better with every session rather than decaying.
A well-organized skill can include supporting files — references, templates, scripts, and assets. The directory structure follows a convention:
skills/devops/docker-deploy/
├── SKILL.md # Main skill document
├── references/
│ └── server-details.md # Server addresses, ports, paths
├── templates/
│ └── docker-compose.yml # Template compose file
├── scripts/
│ └── health-check.sh # Validation script
└── assets/
└── architecture.png # Diagram
Lists skills to see what's available:
$ hermes skills list
Available skills (12):
devops/
docker-deploy Deploy a Docker Compose stack
postgres-backup-restore Backup and restore PostgreSQL
overseas-nodejs-deployment Deploy Node.js to cheap VPS
content/
content-site-publisher Publish articles to SEO network
baoyu-article-illustrator Article illustrations
mlops/
llama-cpp Local GGUF inference
fine-tuning-with-trl TRL: SFT, DPO, PPO
...
The category-based organization (e.g., devops/, content/, mlops/) helps both the agent and human operators find skills quickly. Use skill_view(name) to inspect a skill without loading it into context:
$ hermes skill view docker-deploy
# Returns SKILL.md content without taking up context window space
Treat your skills repository like any production codebase. Use feature branches for new skills and pull requests for review:
$ git checkout -b skill/add-health-check-pattern
# ... create new skill ...
$ git add devops/health-check/SKILL.md
$ git commit -m "Add health-check skill: Docker + curl pattern"
$ git push -u origin skill/add-health-check-pattern
Open a PR and have it reviewed. The review checks for:
For teams running multiple Hermes profiles (development, staging, production), use a branching model:
$ git branch -a
main # Production skills
staging # Staging environment skills
skill/experimental-mcp # New skill under development
fix/pitfall-docker-deploy # Bug fix for production skill
Merge to main only after the skill has been tested in staging and reviewed. The production Hermes instance pulls from main on a schedule or on deploy trigger.
A robust testing pipeline catches skill regressions before they hit production. Here's a shell script that tests every skill in isolation:
#!/bin/bash
# test-skills.sh — Run each skill through a fresh Hermes container
SKILLS_DIR="$HOME/.hermes/profiles/default/skills"
RESULTS_DIR="/tmp/skill-tests"
mkdir -p "$RESULTS_DIR"
for skill_dir in $(find "$SKILLS_DIR" -name SKILL.md -exec dirname {} \;); do
skill_name=$(basename "$skill_dir")
echo "Testing: $skill_name"
docker run --rm \
-v "$skill_dir:/root/.hermes/profiles/default/skills/test-category/$skill_name" \
-e HERMES_API_KEY="$HERMES_API_KEY" \
hermes-agent:latest \
hermes skill view "$skill_name" > "$RESULTS_DIR/$skill_name.log" 2>&1
if [ $? -eq 0 ]; then
echo " ✓ $skill_name — loaded successfully"
else
echo " ✗ $skill_name — FAILED (see $RESULTS_DIR/$skill_name.log)"
fi
done
Run this in CI on every push to main. It's fast (each skill takes seconds to validate) and catches the most common failures: broken YAML frontmatter, missing required fields, and syntax errors that break skill loading.
For deeper testing, run a real task through each skill:
# Advanced: actually exercise a skill
docker run --rm \
-v "$skill_dir:/skills" \
-v /tmp/test-workspace:/workspace \
hermes-agent:latest \
hermes run --input "Use the docker-deploy skill to deploy to staging"
For production systems, track every skill invocation in PostgreSQL. This gives you a queryable history of which skills ran, when, and with what result:
CREATE TABLE skill_runs (
id SERIAL PRIMARY KEY,
skill_name TEXT NOT NULL,
profile TEXT NOT NULL,
started_at TIMESTAMPTZ DEFAULT now(),
finished_at TIMESTAMPTZ,
exit_code INTEGER,
tool_calls_count INTEGER,
error_message TEXT,
git_commit TEXT -- the skill's git SHA at runtime
);
CREATE INDEX idx_skill_runs_name ON skill_runs(skill_name);
CREATE INDEX idx_skill_runs_started ON skill_runs(started_at);
Query to find unreliable skills:
SELECT skill_name,
COUNT(*) AS total_runs,
SUM(CASE WHEN exit_code != 0 THEN 1 ELSE 0 END) AS failures,
ROUND(100.0 * SUM(CASE WHEN exit_code != 0 THEN 1 ELSE 0 END) / COUNT(*), 1) AS failure_pct
FROM skill_runs
WHERE started_at > now() - INTERVAL '7 days'
GROUP BY skill_name
HAVING SUM(CASE WHEN exit_code != 0 THEN 1 ELSE 0 END) > 0
ORDER BY failure_pct DESC;
Skills with high failure rates get priority attention. Combine this with Git history to see if a recent patch introduced the failures.
Here's a production skill from the Agent Rule network — the content-site-publisher skill that generates this very article. It's 200+ lines of YAML and markdown, versioned in Git, and handles three sites across multiple languages:
$ git log --oneline skills/productivity/content-site-publisher/
d42f8c3 fix: add RTL arabic footer links for arablawguide
c71a2b1 feat: add agent-rule.com dark-theme publishing flow
b8e3f9a fix: zh date format — use 分钟 not "min read"
a1d5c7e feat: initial content-site-publisher skill
Every change is documented, reviewable, and revertible. When a new edge case appears (e.g., the jump host changed ports), the fix is one skill_manage(action='patch') call away — and it's in Git history forever.
git log tells you exactly when a skill changed and whyHermes Agent skills turn the agent from a one-shot tool into a system that improves with every use. Git gives you the safety net — every change is tracked, every mistake is revertible. Docker gives you the sandbox — every test runs in a clean environment. Together, they make AI agent automation predictable, auditable, and production-grade.