Refactoring before AI automation: agents amplify messy systems

AI agents do not fix broken systems. They make broken systems move faster. Refactoring before AI automation is not cleanup — it is infrastructure that turns ambiguous workflows into stable domains an agent can safely operate inside.

Engineering8 min read
RefactoringAI automationTechnical debtArchitectureCode quality
Share

AI agents amplify the structure they receive. A clean domain model with explicit states, named boundaries, and documented constraints becomes a reliable automation surface. A messy codebase with ambiguous ownership, implicit state transitions, and tribal knowledge becomes faster chaos — the same bugs, the same misrouted tickets, the same wrong answers, now generated at the speed of inference rather than the speed of a junior engineer reading Slack history.

The industry has quantified this: refactoring activity has dropped 60% since AI coding tools became widespread, while code churn — lines reverted or rewritten within two weeks — has doubled. Teams are generating more code and consolidating less. The architecture degrades faster because nobody is doing the structural work that keeps a system navigable. The result is codebases where AI agents pass tests but violate architecture, where generated code is behaviorally correct yet structurally wrong. Refactoring before AI automation is the intervention that breaks this cycle.

Automation magnifies structure — including bad structure

AI agents operate on the artifacts they can read: code, configuration, documentation, workflow definitions. When those artifacts are clear, the agent's output is predictable. When they are ambiguous, the agent's output is confidently wrong — and the confidence is what makes it dangerous.

A support automation agent fails because two modules define "customer" differently — one means the billing entity, the other means the end user. The agent resolves a ticket by updating the wrong customer record. A workflow automation breaks because escalation rules live in a Slack thread that three people remember but no system encodes. The agent routes tickets to the wrong team for two weeks before anyone notices the pattern.

These are not AI failures. They are structural failures that existed before the agent arrived. A human navigated them through institutional memory and context-switching. The agent navigates them through the only signals it has: the code, the schema, the configuration. If those signals are contradictory, the agent's behavior is contradictory — at scale, continuously, without fatigue or self-doubt.

AI agents need stable domain boundaries to operate safely

An agent that modifies code needs to know where a module begins and ends. An agent that routes support tickets needs to know which team owns which domain. An agent that generates reports needs to know which definition of "revenue" applies in which context. These are domain boundaries — and in most organizations, they are implicit, contested, or different depending on who you ask.

Refactoring before AI automation means making these boundaries explicit:

  • Named entities with single definitions. If "customer" means three things in three places, the agent cannot determine which meaning applies. A refactor that introduces BillingAccount, EndUser, and OrganizationMember gives the agent — and the team — an unambiguous vocabulary.
  • Explicit state machines. If a ticket can be "open," "pending," "escalated," or "resolved" but the valid transitions are undocumented, the agent will attempt invalid transitions. A refactor that encodes the state machine as a constraint makes invalid transitions impossible, whether triggered by a human or an agent.
  • Ownership boundaries in code. If changing one module silently affects another, the agent cannot scope its changes safely. The blast radius of agentic coding compounds when module boundaries are not enforced by the build system.
  • Documented invariants. If the billing system must never generate a negative invoice but this rule lives only in a senior engineer's memory, the agent will eventually generate a negative invoice. A constraint encoded as a validation rule, a test, or a schema check prevents it regardless of who — or what — triggers the operation.

Messy workflows create unpredictable tool use

AI agents do not just read code. They execute tools: API calls, database queries, file operations, notifications. The sequence of tool use depends on the agent's understanding of the workflow. When the workflow is ambiguous, the tool sequence becomes unpredictable.

Consider a refund workflow where the documentation says "refund the customer and notify them" but the actual process involves checking fraud signals, verifying the payment method is still active, calculating partial amounts based on usage, and logging an audit event. An agent operating from the documented workflow skips four critical steps. An agent operating from the actual code — if the code is clean — executes all of them.

The gap between documented workflows and actual behavior is where automation failures live. Refactoring closes this gap by:

  • Replacing implicit sequences with explicit orchestration (a state machine, a pipeline, or a choreography).
  • Extracting side effects from business logic so the agent can compose them rather than guess at them.
  • Making failure modes visible: what happens when the payment method check fails? The refactored workflow has an explicit branch. The messy workflow has a try/catch that silently swallows the error and moves on.

Refactoring is not cleanup — it is automation infrastructure

The framing matters. Refactoring positioned as "paying down tech debt" competes with feature work and loses. Refactoring positioned as "building the surface that AI agents operate on" is infrastructure investment with a measurable return: the agent works correctly, or it doesn't.

The automation readiness checklist:

  • Names: every entity, state, and operation has one canonical name used consistently across code, config, and documentation.
  • States: every workflow has an explicit state machine with valid transitions encoded as constraints, not documentation.
  • Ownership: every module, service, and workflow has a single owning team. CODEOWNERS files, schema ownership, and runbook assignment are all aligned.
  • Tests: critical paths have characterization tests that lock current behavior. The agent can modify code without silent regression because the test suite catches behavioral drift.
  • Rollback: every automated action has a defined undo path. If the agent makes a mistake, the system can recover without manual intervention.

Each item on this list is a refactoring target. None is optional if the goal is reliable automation. The quality tax that AI imposes on unmaintained codebases compounds with every agent-generated change that passes tests but violates structure.

The difference in practice is measurable. A team that spent two weeks encoding their deployment pipeline's state machine into explicit, named stages before connecting an AI agent to it reported zero misrouted deployments in the first month. A team that connected an agent to an undocumented pipeline spent three weeks debugging why staging builds were being promoted to production — the agent inferred the promotion rule from a pattern in the git history that happened to correlate with deploys but was actually a coincidence. The refactoring cost two weeks. The debugging cost three weeks plus an incident. The math favors preparation every time.

What should be refactored before adding AI automation?

The refactoring scope depends on where the agent will operate. Not everything needs to be perfect — but the domain the agent touches must be legible.

Which code areas need refactoring before AI automation?

Prioritize the paths the agent will execute. If the agent generates code in the billing module, the billing module needs explicit boundaries, typed interfaces, and characterization tests. If the agent routes support tickets, the escalation logic needs to exist as code — not as a Slack message from 2023. The refactoring scope is defined by the agent's operational surface, not by a global "pay down all debt" mandate.

How do you turn tribal knowledge into executable constraints?

Every rule that lives only in a person's memory is a rule the agent will violate. The conversion process: interview the domain experts, document the constraint in plain language, encode it as a validation rule or test, and wire it into the path the agent exercises. A domain glossary that defines terms like "active subscription," "churned customer," and "billable event" with precise, computable criteria eliminates the ambiguity that causes agent misbehavior.

When is the codebase ready for safe AI automation?

Readiness is not a binary state. A module is ready when: entity names are unambiguous within the agent's context, state transitions are explicit and enforced, critical paths have test coverage that detects behavioral regression, and failure modes have defined recovery paths. If any of these conditions are missing in the domain the agent will operate on, the refactoring is not done.

A practical litmus test: can a new engineer — someone who has never seen this module — read the code and predict what the agent will do in each state? If the answer requires tribal knowledge, the module is not ready. The agent is permanently a new engineer. It will never build the institutional context that humans accumulate over months. The code must be legible without that context, or the agent will act on incomplete information with full confidence.

The opposing view: AI can clean the mess while automating

A common argument holds that AI itself is the best tool for refactoring. Agents can generate characterization tests, propose dependency graphs, suggest module extractions, and execute mechanical transformations faster than humans. Waiting to refactor before automating delays the value that automation delivers — and in competitive markets, speed matters more than structural purity.

This argument is correct about AI's utility as a refactoring tool. It is wrong about the sequencing. An agent generating characterization tests for a module it does not understand produces tests that lock in the wrong behavior or miss the invariants that matter. An agent proposing a dependency graph without knowledge of business ownership produces a technically accurate but operationally useless map. The human judgment that determines what to refactor — which definitions are wrong, which boundaries are contested, which states are implicit — must precede the automation that executes the refactoring. AI accelerates the mechanical work. It cannot replace the domain decisions that make the mechanical work meaningful.

Key takeaways

  • AI agents amplify structure — including bad structure. A messy system automated is a messy system moving at machine speed.
  • Refactoring before AI automation is infrastructure investment, not cleanup. It builds the surface agents operate on safely.
  • Named entities, explicit state machines, enforced ownership boundaries, characterization tests, and defined rollback paths are the five prerequisites for safe automation.
  • The refactoring scope is defined by the agent's operational surface, not by a global tech-debt mandate.
  • Tribal knowledge that only lives in memory is a rule the agent will violate. Convert it to executable constraints before the agent encounters it.
  • AI can accelerate the mechanical work of refactoring, but the domain decisions about what to refactor must come from humans first.

Conclusion

The teams that extract the most value from AI automation are not the ones with the most agents. They are the ones whose systems were legible enough for agents to operate without amplifying every ambient flaw. The refactoring that makes a codebase navigable for a new engineer is the same refactoring that makes it safe for an agent — explicit names, bounded domains, enforced invariants, testable behavior. The question is not whether to refactor. It is whether to do it before the agent arrives, when the cost is a planned sprint, or after, when the cost is an incident at scale.

Related articles

Command Palette

Search for a command to run...