I keep reaching for stricter specs because they make agent work feel safer. Write the plan, lock the acceptance criteria, tell the agent exactly what not to touch, then judge the PR against the box you drew around it. For a lot of engineering work, that is correct. It is also easy to turn into a tiny little prison and then act surprised when the agent only discovers things you already knew.

The question is not whether specs are good. Obviously they are. The question is when the spec is protecting the work and when it is protecting your first guess.

The fix is not weaker specs. It is separating exploration specs from execution specs, then handing off between them deliberately.

The control surface

A good spec is a control surface. It keeps the agent from wandering into vibes. It says: this is the bug, this is the contract, these are the files that matter, these are the invariants that are not negotiable. If the task is a privacy boundary, a data migration, a billing flow, an auth fix, or a regression with a known failure mode, you probably want that box to be small.

That is the version of agent work that currently feels most mature in my own usage: turn ambiguous human intent into a crisp executable contract, then run a model inside it. The agent is useful because it can fill in implementation details quickly, but the shape of the answer is owned by the spec.

There is a reason this works. The spec carries the local truth. It knows the product constraints, the weird repo-specific invariants, the thing the test suite does not express yet, the user's actual preference. The model's broad prior is less important than not breaking the thing in front of it.

For that class of work, a loose prompt is negligence wearing a hoodie.

The receipt: the frame changed

The receipt I keep coming back to is a draft that started with one frame and ended with a different one. The first version was about a feed-forward enforcement tool: read the spec, plan the work, enforce the plan, validate the result. One artifact. One source of truth. Very satisfying little box.

Then the box started lying. Claude Code already had hooks. Codex had its own runner shape. OpenCode had feed-forward-ish behavior inside the agent loop. If the article stayed inside the original execution frame, it would keep arguing for a mechanism the surrounding ecosystem was already absorbing.

The useful discovery was not a better implementation. It was deleting part of the job and changing the frame. The interesting primitive was traceability: what the repo can prove about why agent-authored work exists, what session produced it, and what survived review. A strict execution spec would have produced the obvious tooling story. The exploratory pass found the sharper article.

That gap is the discovery tax: every extra constraint buys safety, but it also charges rent on whatever the model might have found outside your framing.

The discovery surface

Not every problem needs an execution cage. Sometimes the target is known and you just need the agent to stop being cute. But sometimes the point of using an agent is that it can pattern-match across more examples than you are holding in your head: APIs, failure modes, refactors, package ecosystems, and weird tricks from other people's code.

That prior is only useful when it produces hypotheses you can cheaply test. Untested priors are just prettier guesses. The value is not "the model knows everything." It does not. The value is that it can suggest shapes you did not put in the spec, and some of those shapes are worth checking.

This shows up in the annoying tasks: architecture when the design space is still open, debugging when your first theory is probably wrong, library choices where the ecosystem has already had the argument without you, and those little moments where the right answer is deleting the task instead of implementing it.

In those cases, a rigid spec can become a blindfold. You told the agent what path to walk, so it walks it. Then you blame it for not discovering the adjacent path you never let it inspect.

The expensive lie: "just follow the spec"

"Follow the spec" sounds disciplined. Sometimes it is. Sometimes it is just a way to outsource execution while preventing the only useful disagreement.

The more precise the spec, the more it smuggles in the author's worldview. That is fine when the author's worldview is the source of truth. It is not fine when the goal is to learn from the model's prior.

This is where the model quietly stops being a collaborator and becomes autocomplete with a longer leash. It can still produce a good PR. It can pass tests. It can obey every acceptance criterion. It can also miss the better move because the better move was outside the permitted shape.

A strict execution contract answers questions like:

  • what should be preserved?
  • what does done mean?
  • what is out of scope?
  • what would make this unsafe?

An exploration brief should ask different questions:

  • what assumptions should the agent challenge?
  • what existing approaches should it compare against?
  • what evidence would change the plan?
  • what cheap spike would expose the shape of the problem?
  • where should the agent stop and ask for a human taste call?

Those are both specs. They are just not the same artifact. One closes the search space. The other opens it without letting the agent wander forever.

Two modes I want to separate

The mistake is pretending "agent task" is one bucket. It is not. At minimum there are two modes, and they want almost opposite behavior.

Execution mode: the human or system already knows enough to define the target. The agent's job is to get there without drifting. The spec should be narrow, testable, and slightly annoying. Acceptance criteria matter. Constraints matter. The best outcome is boring: the PR does exactly what it said it would do.

Exploration mode: the target is not stable yet. The agent's job is to search the design space, import outside patterns, find contradictions, and return with options. The spec should define the question, the constraints, and the evidence budget, but not the answer shape too early. The best outcome may be a plan, a deleted idea, a spike, or a sharper spec for execution mode.

Most real tasks are mixed. The point is not to classify the whole task once and then cosplay process maturity. The point is to know which part of the loop is allowed to widen the search space and which part is supposed to collapse it.

If the failure mode is drift, use execution mode. If the failure mode is your own wrong assumption, use exploration mode. If you cannot tell which failure mode you are in, that is already evidence that you need exploration before implementation.

The handoff matters

The useful pattern is not "looser specs." It is two different spec types with a handoff between them.

The first agent pass is not "build the thing." It is:

  • restate the problem in stronger terms
  • list plausible approaches
  • bring in outside priors from frameworks, tools, and known failure modes
  • argue against the user's first framing
  • run a tiny spike if needed
  • name the risks and taste calls
  • produce a tighter spec for the implementation agent

Then the second pass gets the boring contract. Build this. Preserve that. Tests here. Do not rewrite the universe. If the implementation agent discovers the spec is wrong, it should kick back into exploration instead of silently improvising.

The handoff needs receipts, or it becomes process theater. An exploration output should carry the assumptions it challenged, the options it rejected, the evidence it found, the spike result if there was one, and the exact trigger that should reopen exploration later.

That boundary is where I want multi-agent systems to live: not one giant agent with a mushy prompt, and not a single rigid spec pretending discovery is already done. A loop that alternates between opening the design space and closing it.

What I am still unsure about

The dangerous part is that exploration is also where agents waste the most time. Give a model too much room and it can produce a cathedral of plausible nonsense. Give it too little room and it becomes a fast intern trapped inside your own blind spots.

So the actual design problem is not whether specs should be strict. It is when strictness should attach.

The closest I can get is this: keep the safety invariants tight, keep the solution shape loose, demand evidence before changing direction, and then tighten the cage again once the direction is chosen. That is not as clean as "spec-driven development," but it is probably more honest.

Specs should not be cages. They should be valves: open when the system needs to learn, closed when the system needs to land.