Most autonomous agent demos look impressive for the same reason magic tricks do: you mainly see the part that worked.
The ugly part is what happens when the task is underspecified but still operational. The model does not just fill in one missing detail. It starts building guard rails, side systems, fallback logic, heuristics, backup plans, and recovery paths for problems nobody explicitly asked it to solve.
I ran into this while trying to make shared custom skills available to the same set of local agents across two laptops:
- Hermes
- Claude
- Codex
- Pi
- Agents
The requirement looked small.
- use one canonical repo
- keep the local path the same on both machines:
~/code/skills - make shared custom skills available everywhere
- have the Hermes agent on each laptop run the shared skill as a cron job
- do not accidentally publish packaged skill catalogs
- keep the whole thing simple enough to debug six months later
The short version is this: the moment an agent has to infer too many design decisions, it starts optimizing for control rather than maintainability.
That framing matters.
The failure mode is not random bad code. It is structural. The more you leave implicit, the more an agent expands the system boundary to reduce uncertainty for itself.
Let’s get into it.
The Problem Was Smaller Than The Solutions It Kept Producing
At the product level, this was not a hard problem.
I did not need a distributed control plane.
I did not need a plugin registry.
I did not need a synchronization protocol with multiple hidden states.
I needed one boring truth:
- shared custom skills live in
~/code/skills - both laptops pull from there
- all local agents can see the same shared skills
That is it.
But the moment ambiguity appeared, the solution surface expanded quickly.
Examples of ambiguity that turned into complexity:
- should the sync be push-only or bidirectional?
- should newly discovered local-only skills auto-publish or wait?
- should packaged skills be filtered by path, by timestamp, by prior membership in the repo, or by human review?
- should Hermes use direct discovery, external directories, symlinks, or something else?
- what should happen if local skill folders already exist?
Every unanswered question gave the model permission to invent architecture.
That one dynamic explains most overengineered agent output.
The Agent Was Not Optimizing For Simplicity
This is the key point.
The agent was not trying to make the system elegant.
It was trying to avoid being wrong.
Those are not the same objective.
If a model sees uncertainty, it does not naturally think:
- maybe I should ask
- maybe the smallest version is enough
- maybe the human wants operational clarity more than coverage
More often it thinks:
- what if this runtime cannot discover symlinked skill folders?
- what if packaged skills get misclassified?
- what if a local overwrite destroys data?
- what if cron needs fully autonomous behavior?
Each of those concerns is individually reasonable.
Together they become a complexity ratchet.
One helper script becomes a sync engine.
One install rule becomes a managed install model.
One uncertainty about discovery becomes a code patch.
One safety concern becomes a backup layer.
Nothing looks insane in isolation. That is exactly why it gets dangerous. Complexity arrives as a pile of locally defensible decisions.
The Real Design Smell Was Assumption Density
I think this is the better lens.
Overengineering is often just assumption density made visible.
When the model assumes too much, it starts solving the inferred problem instead of the stated one.
In this case, the stated problem was:
- share custom skills across runtimes and across two laptops
The inferred problem became something more like:
- build a robust, self-healing, ambiguity-tolerant, multi-runtime skill replication layer with bootstrap heuristics and safe install semantics
That is a completely different system.
And once the model steps onto that path, it becomes hard for it to stop. Every new layer creates the need for another layer to make the previous layer safer.
This is why simple prompts are not enough. If the missing decisions are structural, the model will fill them with architecture.
The Timestamp Heuristic Was Actually A Good Decision
Not every addition was bad.
One thing that held up was using SKILL.md modification time as the primary signal for telling custom skills apart from packaged catalogs.
That choice worked because it was not a new subsystem. It was just a decision rule.
The idea was simple:
- sort skills by
SKILL.mdmodification time within each root - look for obvious clusters and obvious time gaps
- treat the newer side of a clear gap as more likely user-authored
- if the pattern is ambiguous, ask instead of guessing
That is the kind of complexity I trust.
It is not invisible machinery.
It is a human-readable policy.
You can explain it in English.
You can inspect it quickly.
You can override it with judgment.
That is very different from embedding the whole decision into a large automation layer that nobody wants to debug later.
The Better Pattern: English First, Mechanism Second
This conversation pushed me toward a rule I now trust much more:
Write the workflow in English first.
Only after the workflow feels obviously correct should you decide whether any automation is needed at all.
For this class of problem, the English version was already the real design. I eventually forced that workflow into a plain-English skill instead of another layer of hidden machinery. You can read that skill directly here: sync-local-skills-to-github.
- Use
~/code/skillsas the shared source of truth on both laptops. - Treat local agent skill folders as install targets first.
- Update already-shared skills when the local copy is clearly newer.
- Use
SKILL.mdmodification times to reason about likely custom skills. - Do not auto-publish ambiguous new local-only skills.
- Ask before introducing invasive changes or runtime-specific patches.
That is a system.
It may not be fully automated, but it is operationally legible.
And operational legibility is more valuable than cleverness for this kind of tooling.
The Best Default Is Usually Smaller Than The Agent Wants
I think this is the practical lesson.
When an agent starts working on infrastructure-style coordination problems, you should assume it has a bias toward completeness.
That means you need to counterweight it explicitly.
Not with vague instructions like “keep it simple.”
With real decision boundaries:
- ask before changing local runtime code
- ask before introducing helper scripts
- ask before creating a new state model
- ask before replacing a direct file operation with a management layer
- ask before converting a policy into automation
That one boundary does a lot of work.
Because once the model has to stop and ask, it can no longer silently convert uncertainty into architecture.
The Rule I Am Keeping
The more you assume, the more you overengineer.
That applies to humans too, but it applies even harder to agents because they are rewarded for producing something that looks complete.
If you want maintainable systems from them, do not just constrain the output.
Constrain the number of decisions they are allowed to make without you.
In practice, the most useful agent is often not the one that can invent the most machinery.
It is the one that knows when to stop and ask a human where the boundary should be.
Related: Model overthinking is a control problem.