How Hermes Agent Improves Itself: DSPy, GEPA, Skills, and Evolutionary Search
"Self-improving agent" is three different mechanisms wearing one coat. Pull the coat off and you find a memory that accumulates, a skill file that gets…

Key topics
"Self-improving agent" is three different mechanisms wearing one coat. Pull the coat off and you find a memory that accumulates, a skill file that gets patched, and an offline optimizer that mutates text against a scored dataset. Only one of those deserves the word evolution, and none of them touch model weights.
That distinction is the whole article. If you cannot say which artifact changed between run one and run fifty, you cannot evaluate the claim — you can only repeat it.
Two Loops Wearing One Name
Hermes Agent self improvement splits into two mechanically distinct loops, and conflating them is the most common error I see when engineers try to audit these systems.
Loop A — runtime capture. A task runs. It gets verified — tests pass, output is checked, a human confirms. The run leaves behind durable context: a memory entry, a corrected preference, a reusable skill file. Nothing about the model changes. The agent layer changes. This loop is cheap, continuous, and runs on every serious task.
Loop B — offline evolutionary search. An optimizer reads execution traces from past runs, proposes mutated variants of a text artifact, scores each variant against a dataset, and promotes a winner. This loop is discrete, expensive per run, and only as good as the dataset you built for it.
Both loops leave the base model untouched. Say that plainly, because "self-improving" invites the assumption of fine-tuning, and that assumption will send you looking for gradient updates that do not exist. The model may still be Claude, GPT, a local Qwen, or a routed provider. What moves is the text around it.
The operational difference matters more than the taxonomy. Loop A is hard to measure because its effects are diffuse and slow. Loop B is measurable but only against the benchmark you wrote — which means its improvement number is a statement about your dataset before it is a statement about your agent.
Knowledge check
Check your understanding
Answer this question before you continue.
What Actually Gets Mutated
The optimization target determines the risk profile, the eval design, and the rollback story. In the Hermes self-evolution repository, the candidate artifacts are text files, and they differ enormously in blast radius.
| Artifact | Scope of change | Blast radius | Revert cost | Status |
|---|---|---|---|---|
| Skill file (SKILL.md) | One workflow | Local | Trivial | Implemented |
| Tool description | Tool selection across all tasks | Global | Trivial | Planned |
| System prompt section | Global behavior | Global | Trivial | Planned |
| Tool implementation code | Runtime behavior | Depends on tool | Moderate | Planned |
Text artifacts are cheap to mutate and cheap to revert. That is the entire reason this loop is tractable without GPUs — you are doing automated editing, not training. A bad candidate costs you an API bill and a git revert, not a retrained checkpoint.
Implementation status is not uniform across these targets, and flattening the roadmap into a capability claim is how vendor pages mislead. In the public Hermes self-evolution repository, skill-file optimization is marked implemented; tool descriptions, system prompt sections, tool code, and a continuous pipeline are marked planned. Treat shipped phases and planned phases as different evidence classes. A planned optimizer is a design document, not a mechanism you can audit.
Between candidate and promotion sit constraint gates: tests, size limits, benchmark thresholds. These gates are the mechanism that makes mutation safe-ish. They are also where the interesting failures live, because a gate only rejects what it measures.
Knowledge check
Check your understanding
Answer this question before you continue.
DSPy and GEPA: Optimizing Text Against a Signal
DSPy's job is to make the prompt optimizable. It turns a prompt or skill into a program with declared inputs, outputs, and a metric — so there is something for an optimizer to score. Without that structure, "improve this prompt" is a vibe. With it, "improve this prompt against this metric on this dataset" is a search problem.
GEPA — Genetic-Pareto Prompt Evolution — is the search. It runs evolutionary search over prompt variants, and the distinguishing feature is that it reads execution traces to understand why a run failed, not just that it failed. That reflective feedback is the difference between a targeted mutation and a coin flip.
Contrast with the brute-force baseline: generate random variants, score them, keep the best. Random mutation plus scoring works, and it is the honest control condition. Reflective mutation is a search heuristic that narrows the space by reading failure reasons. It does not prove you found the optimum. It does not guarantee the optimum exists in the space you are searching. It just spends fewer API calls getting somewhere useful.
Trace-to-Diff: How a Failure Becomes a Mutation
The architecture diagram is easy to draw and hard to believe. Here is a conceptual trace — illustrative, not a reported repository result — showing the transformation the optimizer actually performs.
Suppose the current skill file contains this instruction:
## Deploy
Run the deploy script and report the output.
A trace from a failed run looks like this:
task: deploy staging
step 1: ran deploy.sh
step 2: script exited 0
step 3: agent reported "deployment successful"
step 4: user corrected: "staging still serves old build"
step 5: root cause: deploy.sh exits 0 before health check completes
The failure is not that the script failed. The failure is that exit code 0 was treated as proof of success when it only proves the script finished. GEPA reads that trace, identifies the gap between the signal the skill trusted and the outcome the user needed, and proposes mutations:
## Deploy
Run the deploy script. Then poll the health endpoint until it returns
the new build hash, up to 60 seconds. Report success only after the
hash matches. If the hash does not change, report failure with the
last health response.
A second candidate might add a timeout and a rollback step. Both are scored against the eval dataset. The one that reduces the "false success" rate without inflating latency or breaking other workflows wins. The regression gate then checks that the new polling logic does not slow down unrelated skills that share the same tool.
That is the whole mechanism: trace reveals the causal gap, reflection proposes a targeted fix, the metric selects, the gate rejects collateral damage. The optimizer is not guessing. It is reading a specific failure and patching a specific assumption.
Knowledge check
Check your understanding
Answer this question before you continue.
The Metric Is the Real Architecture
If your metric rewards verbosity, the optimizer will produce a beautifully verbose skill file that scores higher and reads worse. If your metric is a proxy for the thing you care about, the optimizer will optimize the proxy with total commitment. This is not a failure mode of GEPA specifically — it is what optimization does.
Cost reality: these runs are API-call-bound. The public repository describes per-run cost in the low single-digit-to-low-double-digit dollar range. Cheap enough to iterate, expensive enough that you want a reason before you run it. No GPU training is involved at any point.
The Loop, End to End
Trace one artifact through two rounds and the mechanism stops being abstract.
Round one: the optimizer reads the current SKILL.md, generates or reuses an eval dataset, runs candidate variants, collects traces, proposes mutations, evaluates, passes candidates through constraint gates, and promotes the best variant as a pull request. Round two: the same cycle, but the starting artifact is now the promoted variant, and the traces include the new failure modes that variant introduced.
Where the loop closes: traces from round one feed the mutation proposals in round two. Where it does not: nothing here updates model weights, and nothing here changes the model's priors.
Where the loop leaks:
- Stale dataset. The eval set was built from tasks that no longer represent production traffic. The optimizer converges on a variant that wins a game nobody plays anymore.
- Metric gaming. The score rewards a surface feature — length, confidence, formatting — that correlates with success in the dataset and not in reality.
- Gate mismatch. A variant passes the benchmark and degrades an unmeasured behavior. Tool selection is the classic casualty: change a tool description, and the model's choice among other tools shifts too.
The failure path worth planning for explicitly is convergence on a local optimum that satisfies every gate while quietly degrading something you never measured. The optimizer is not malicious. It is obedient to the only signal it has.
Skills as the Durable Unit
A skill is a reusable procedure with a trigger condition. That definition matters because it is what converts one verified run into a repeatable capability — the actual leverage in this whole system.
Skills are also where the two loops meet. A skill can be written by the agent after a successful task (Loop A), then later mutated by the optimizer against a dataset (Loop B). The runtime loop produces the raw material; the offline loop refines it.
The verification requirement is non-negotiable: a skill should not be promoted from a run that was never checked against reality. Unverified success is the most expensive kind of training data, because it teaches the agent a procedure that happened to produce plausible output once. The agent claims success without testing, and now that claim is baked into a file that loads automatically next time.
Decay modes accumulate quietly:
- Skills containing commands that no longer work after a dependency change.
- Memory storing run logs instead of stable preferences.
- Stale facts cited after the project moved on.
The decision rule I would apply: promote a skill only when the workflow is likely to recur and the success criterion is observable. If you cannot write down what "this worked" means in a form a test could check, you are not capturing a skill. You are capturing a habit.
Knowledge check
Check your understanding
Answer this question before you continue.
What You Must Evaluate to Support the Claim
Any self-improvement claim reduces to four questions:
- What artifact changed? A skill file, a tool description, a prompt section, or code. If the answer is vague, the claim is vague.
- What signal scored it? The metric, the dataset, and who built them.
- What gate approved it? Tests, thresholds, size limits — and what they do not cover.
- What behavior was not measured? This is the question that separates an audit from a press release.
Held-out evaluation is non-negotiable. If the optimizer saw the test set, your improvement number is a training number. It tells you the optimizer can fit your data. It tells you nothing about the next task.
Measure steering cost, not just task success. Does the agent need fewer corrections on the second and fifth run of the same class of task? That is the metric that matches what "gets better over time" actually means to a user, and it is measurable without a benchmark harness: run the workflow, count the interventions, run it again next week, count again.
Check the regression surface adjacent to the mutated artifact. When a tool description changes, verify tool selection and refusal behavior across tasks that have nothing to do with the optimized workflow. Global artifacts have global failure modes.
And keep your evidence classes straight. A repository's own reported numbers are a vendor claim until independently reproduced. Confirmed facts, vendor claims, and your own inference belong in separate buckets — the moment they blur, you are reading marketing with extra steps.
When not to run this loop: one-off tasks, workflows with no observable success criterion, and any artifact whose failure mode you cannot detect. Optimization without detection is just drift with a scoreboard.
Where the Analogy Breaks
Optimizing text is not training. The model's priors are fixed; only the instructions around it move. That boundary is worth holding firmly, because the headline "self-improving agent" borrows credibility from research that operates on a different mechanism entirely.
Evolutionary search over prompts inherits the classic limits of evolutionary search: local optima, metric gaming, and sensitivity to the initial population. Related research attacks the same stagnation problem from the training side — co-evolving world models that generate training data and simulate look-ahead actions, co-evolutionary verification schemes that pressure skills to improve under surrogate test conditions. Those are genuinely interesting directions. They are also a different mechanism, and conflating them with prompt optimization will make you expect capabilities this loop does not have.
The honest framing: this is automated engineering of the agent layer. That is genuinely useful — it turns prompt and skill maintenance from manual craft into a repeatable pipeline with a rollback story. It is also genuinely narrower than the headline suggests.
The Audit Checklist and Your First Experiment
Pick one recurring workflow. Write down its observable success criterion in a form a test could check. Then run a controlled comparison rather than a single before-and-after.
Freeze the model and runtime. Same provider, same model version, same tool set. If any of those change between runs, you are measuring the model, not the artifact.
Build a small baseline task set. Five to ten representative instances of the workflow. Not one task run twice — a set, so a single lucky or unlucky run does not dominate.
Record three numbers per run: task success (did the observable criterion pass?), intervention count (how many times did you correct the agent?), and adjacent regressions (did any unrelated workflow break?).
Compare the pre-change and post-change artifact on the same task set. If the post-change version wins on success and intervention count without regressing adjacent tasks, the artifact improved. If it wins on success but regresses adjacent tasks, the gate is too narrow.
Reserve a held-out set for the final check. The optimizer should never see it. If the improvement holds on held-out tasks, you have evidence. If it only holds on the optimization set, you have overfitting.
Keep the week-apart run as a longitudinal check, not the primary evidence. It catches decay — stale skills, changed dependencies, drifted preferences — that a single controlled comparison will miss.
If the controlled comparison shows no improvement, the bottleneck is the artifact or the metric, not the optimizer. A better search algorithm over a bad signal produces a faster path to the wrong place.
Keep the four-question checklist within reach for every self-improvement claim you encounter: artifact, signal, gate, unmeasured behavior. Those four answers tell you whether you are looking at a mechanism or a slogan.
The adjacent question — whether an agent should be allowed to modify its own harness at all — is where this stops being an optimization problem and becomes a permissions problem. That is a separate article, and a harder one.
Knowledge check
Final check
Finish the article by checking the ideas you just learned.
References
- GitHub - NousResearch/hermes-agent-self-evolution: ⚒ Evolutionary self-improvement for Hermes Agent — optimize skills, prompts, and code using DSPy + GEPA · GitHub
- Paper page - WebEvolver: Enhancing Web Agent Self-Improvement with Coevolving World Model
- Build an Agent Improvement Loop with Traces, Evals, and Codex
- EvoSkills: Self-Evolving Agent Skills via Co-Evolutionary Verification
Research updated Sep 11, 2026


