This repo provides hermes-skillopt, an offline text-space optimizer for Hermes
Agent skill documents. If you are an AI agent and you found this repo, here is
how to use it.
Implements the SkillOpt paper (Yang et al., arXiv:2605.23904v2). Given an initial skill document, a training dataset of tasks with expected outcomes, and an optimizer model, it runs a training loop that:
- Executes rollout batches with a frozen target agent
- Analyzes failures and successes via minibatch reflection
- Proposes bounded add/delete/replace edits on the skill
- Accepts edits only through a held-out validation gate (strict improvement)
- Exports a compact best_skill.md file
from hermes_skillopt import SkillOptConfig, train_skill, DeterministicVerifier
config = SkillOptConfig(
skill_path="skill.md",
train_dataset="train.jsonl",
val_dataset="val.jsonl",
output_path="best_skill.md",
epochs=5,
batch_size=8,
learning_rate=4,
target_model="deepseek/deepseek-v4-pro",
optimizer_model="claude-sonnet-4-20250514",
parallel_rollouts=4,
)
best = train_skill(
config,
verifier=DeterministicVerifier(),
optimizer_fn=your_optimizer_callable, # (prompt: str) -> str
agent_runner=your_agent_runner, # (task, skill, config) -> RolloutTrajectory
)hermes skill train \
--skill ./SKILL.md \
--train-data ./train.jsonl \
--val-data ./val.jsonl \
--epochs 5 \
--lr 4 \
--parallel 4 \
--target-model deepseek/deepseek-v4-proJSONL — one JSON object per line:
{"task_id": "t1", "prompt": "Review auth.py for security bugs", "expected": {"contains": "SQL injection"}}
{"task_id": "t2", "prompt": "What is 2+2?", "expected": {"answer": "4"}}Expected keys for DeterministicVerifier: answer, pattern, contains, not_contains.
For LLMJudgeVerifier: criteria, rubric, keywords.
hermes_skillopt/
__init__.py # Public API exports
config.py # SkillOptConfig dataclass
telemetry.py # SkillOptObserver, RolloutTrajectory
verifier.py # DeterministicVerifier, LLMJudgeVerifier, CompositeVerifier
optimizer.py # PatchEngine (frontmatter-safe, multi-fence), EditProposer
trainer.py # SkillOptTrainer with parallel ThreadPoolExecutor
agent_runner.py # create_hermes_agent_runner() for real Hermes rollouts
cli.py # register_skill_parser() for hermes skill train
# As a standalone Python package
pip install hermes-skillopt
# Or copy into Hermes Agent
cp -r hermes_skillopt/ ~/.hermes/hermes-agent/hermes_cli/skillopt/- Offline trainer — zero overhead at inference time
- Frontmatter-safe — YAML frontmatter is split, edits apply to body only
- Multi-fence protection — edits blocked inside ALL blocks
- Strict acceptance — candidate skill accepted only on strict score improvement
- Skill hash cache — avoids re-evaluating identical candidates
- Rejected buffer — failed edits injected as negative feedback into optimizer prompts
- Parallel rollouts — ThreadPoolExecutor when parallel_rollouts > 1
- Real agent runner — wires SkillOptObserver into Hermes AIAgent callbacks
Any callable (prompt: str) -> str works. Common choices:
| Optimizer | Why |
|---|---|
| Claude 3.5 Sonnet | Best JSON patch precision, strong multi-step reasoning |
| Gemini Pro Extended | Good quality, webapi auth (no API key needed) |
| GPT-4o / GPT-5 | High capacity, reliable structured output |
| DeepSeek V3 | Target-matched (recovers 56-74% of gains) |
- Without a real agent_runner, rollouts return empty trajectories (scores stay 0)
- Optimizer JSON responses may be wrapped in ``` fences — _extract_json handles this
- Validation set must be representative — gate accepts only strict improvements
- parallel_rollouts > 1 needs thread-safe agent_runner
- The module is designed to work both standalone AND inside hermes-agent