Founder pricing: Pro at $9.99/mo forever for the first 50 members. 18 of 50 left Claim yours →
All posts

How to stop AI coding agents from over-engineering

The SanuDesk team 5 min read
over-engineering code quality ai agents

You asked for a date formatter.

You got a DateFormatterFactory, an interface with one implementation, three config options, a new dependency, and 240 lines of tests for code that didn't exist an hour ago.

None of it is wrong. That's what makes it hard to reject: no bug to point at, just a fortnight of future maintenance you never agreed to. So it lands, and six months later somebody loses an afternoon working out why a formatter needs a factory.

Why agents build the big version

It isn't laziness, and it isn't a bad model. Three things push every coding agent the same way.

Its training is mostly library code. Public repos are full of software written to be general: reusable, configurable, built for callers the author will never meet. Your one-off internal script is the statistical oddity.

Bigger looks more helpful. An agent can't feel the cost of the code it writes; it will never onboard to this repo or get paged at 2am. Volume is free for it and expensive for you.

Vague asks leave room. "Add caching" doesn't say where, for how long, or at what layer. The agent fills that gap with everything caching could mean: the thorough answer looks like the safe one.

You can't prompt this away completely. You can constrain it, cheaply.

Know the tells

Over-engineering doesn't look like bad code. It looks like serious code. Scan the diff for:

  • An interface, factory or base class with exactly one implementation.
  • Config options nobody asked for, defaulting to the only value ever used.
  • A new dependency for something the standard library already does.
  • try/catch around code that can't fail, swallowing the error if it does.
  • A "while I was in there" refactor riding along in the same commit.

Any one can be the right call. Three in a 400-line diff means the agent designed for a problem you don't have.

Say how big, not just what

The highest-leverage fix is putting a size in the prompt. Agents follow explicit limits well; they just invent their own when you don't give one:

  • "Smallest change that makes this test pass."
  • "No new files, no new dependencies."
  • "Under 50 lines. If it needs more, stop and tell me why."
  • "One implementation. No interface until there's a second caller."

Make that last one a habit: most agent-written abstraction serves a second use case that never arrives.

Put the out-of-scope list in the brief

Scoped prompts win because they close the gaps an agent would otherwise fill for you. That's the case for writing a short brief before the work and the part everyone skips is the valuable one: an explicit not this list.

In scope: format dates in the invoice PDF.

Out of scope: timezones, locale config, changing the existing helper, or anything outside app/Invoices.

Acceptance criteria do the same job from the other end. If they're met in 40 lines, the other 360 have nothing to justify them.

Make the standing rules durable

Anything you'd repeat every session belongs in a file, not a prompt. Four lines in your AGENTS.md beat any single clever instruction:

  • No new dependencies without asking first.
  • Prefer a function to a class, and a class to a framework.
  • Don't add configuration for values that never change.
  • Match the file you're editing. This codebase is deliberately plain.

Say it once; it applies in every session, to every agent.

Review for what shouldn't exist

Normal review asks is this correct? Agent output needs a second question: why does this exist?

Read the diff for necessity before correctness: new files first, then new abstractions, then the logic. Anything you can't trace back to the brief is a deletion candidate.

The efficient move is to make the agent do that pass itself. "What could be deleted from this diff with the tests still passing?" gets a useful answer, because removing code is now the goal rather than a criticism. Fold it into your usual review of AI-generated code.

Small tasks are the structural fix

All of that is treatment. The cause is task size.

One prompt covering a whole feature invites invention: the agent guesses where the edges are, then builds scaffolding to cover every guess. Split that work into six scoped tasks and you get six small diffs, each obviously fine or obviously bloated.

So the real fix isn't a better prompt. It's a workflow where tasks arrive small by default.

Scope that lives on the board

That's the shape of SanuDesk. It's a desktop app where your Claude Code, Codex and Gemini sessions tile into one grid, with a Kanban board the agents take their work from.

A card is a scope boundary you write once. Deploying it opens a fresh session with that card's title, notes and acceptance criteria as the brief, out-of-scope list included, so the agent starts bounded instead of drifting there later. When it stops, the card moves to review with a what-changed note: exactly the moment to ask what could be removed. Splitting an oversized job into six cards takes ten seconds.

Loops handle recurring passes on a schedule: a weekly hunt for dead code, unused exports and dependencies nothing imports, each run journaled, so the tenth is sharper than the first. It drives the agent subscriptions you already pay for, and the free tier doesn't need one of ours.

Ask for less

Next time an agent hands you 400 lines for a 40-line problem, don't fix it in review. Throw the diff away, add one line of scope, and run it again. It's faster than trimming by hand, and the second version is usually the one you'd have written yourself.

Download SanuDesk free and point a workspace at your repo, or see how the grid, the board and Loops fit together on the features page.

Run your own fleet of agents

SanuDesk is a free desktop app that tiles your Claude Code and Codex sessions and gives every project a Kanban board your agents work from.