Skip to content
Goatfied

agent-loop

Plan-then-edit or edit-then-verify: comparing agent architectures

Comparing AI coding agent architectures that plan changes before execution versus those that edit first and validate afterward, with tradeoffs for each approach.

2026-07-288 min readBy Goatfied
Plan-then-edit or edit-then-verify: comparing agent architectures

Every AI coding agent eventually faces the same design fork: should it plan the entire change up front and then execute, or should it make edits immediately and verify afterward? The distinction sounds academic until you watch an agent spend three minutes drafting a detailed plan only to discover the target file uses a different ORM than it assumed, or watch another agent apply fifteen edits before realizing the tenth one broke the build.

These aren't implementation details. The sequencing of plan, edit, and validation phases determines whether your agent can recover from mistakes, how much compute it wastes on dead ends, and whether it produces mergeable code or a pile of half-working diffs that require human triage.

Plan-first architectures: when up-front investment pays off

A plan-first agent generates a structured intent before touching any files. In its purest form, it reads relevant context, outputs a JSON or structured natural language plan describing files to modify and changes to make, gets that plan approved (by a human, validator, or itself in a reflection step), and only then applies edits.

The advantage is obvious when changes span multiple files. If you're adding a new API endpoint, you probably need to touch a route handler, a service layer function, a database migration, and tests. Planning all four together lets the agent ensure consistent naming, shared types, and coordinated argument shapes before writing a single line of code.

Plan-first also creates a natural checkpoint for human review. Instead of interrupting an agent mid-edit, you can approve or reject the entire intent. This works well in regulated environments where every code change requires audit trails—your plan becomes the documented rationale.

The cost is speed and adaptability. Real codebases surprise you: the function you planned to modify turned out to be deprecated, or the test framework doesn't support the mocking approach you sketched out. A rigid plan-first agent either fails outright or needs an expensive re-planning loop. Worse, planning at high fidelity requires the agent to effectively write pseudocode for changes it hasn't made yet, which can consume as many tokens as just writing the real code.


// Plan-first output might look like this

{

  "files": [

    { "path": "src/routes/users.ts", "action": "modify", "changes": "Add POST /users/:id/verify endpoint" },

    { "path": "src/services/user.ts", "action": "modify", "changes": "Implement verifyUser(id, code) function" },

    { "path": "prisma/schema.prisma", "action": "modify", "changes": "Add verificationCode and verifiedAt fields to User model" }

  ]

}

// Then the agent executes this plan sequentially

Edit-first architectures: optimizing for iteration speed

An edit-first agent skips explicit planning and jumps straight to modifying code. It might read a few context files, generate a diff, and apply it. Verification happens after—linters, type checkers, tests—and if something breaks, the agent gets error output and tries again.

This model bets on fast feedback loops. Instead of spending 30 seconds planning and 20 seconds editing, it spends 10 seconds editing and learns from real compiler errors. For small, localized changes—fixing a typo, updating a function signature, adding a guard clause—edit-first is dramatically faster because planning overhead exceeds editing time.

The catch is error amplification. If your first edit introduces a type error and your second edit depends on that first change being correct, you're now debugging two layers of mistakes simultaneously. Edit-first agents tend to produce longer retry chains, especially on changes that require multiple files to be consistent.


// Edit-first: just make the change

// Before:

export function verifyUser(id: string) {

  // ...existing logic

}



// After (agent's first attempt):

export function verifyUser(id: string, code: string) {

  if (code !== user.verificationCode) throw new Error("Invalid code");

  // ...existing logic

}

// Compiler error: Property 'verificationCode' does not exist on type 'User'

// Agent sees error, plans to update schema, retries

Hybrid approaches: plan boundaries, not implementations

Most production agent systems land somewhere in between. They plan at the level of file selection and high-level intent, but skip detailed pseudocode. The agent might decide "I need to update the user service and add a database field," fetch those files, and then edit directly with a validator in the loop.

Goatfied's agent loop is deliberately hybrid: we plan which files to touch and what kind of change to make (add function, modify signature, refactor structure), but we constrain the planning phase to stay lightweight. The agent doesn't write full pseudocode plans—it identifies targets and constraints, then moves into an edit phase where it generates real diffs against real code.

The key insight is that compile and lint errors are a form of planning feedback. If your agent edits a TypeScript function and the type checker complains about a missing import, that's not a failure—it's the environment telling the agent what the correct plan should have included. This only works if your validation is fast (sub-second for linting, a few seconds for type checking) and your agent can parse structured error output.


# Constraint phase in Goatfied

goat constrain --changed-files src/services/user.ts,prisma/schema.prisma

# Outputs: "Must maintain UserService interface compatibility, migration must be reversible"



# Edit phase

goat edit --apply



# Validate phase (automatic after edit)

# Runs: prettier, eslint, tsc --noEmit, jest --findRelatedTests

# If errors: agent sees structured output and retries with error context

When planning actually prevents errors vs. when it just delays them

Planning helps when the problem space is well-defined but the solution space is large. Refactoring a module's exports, adding end-to-end feature scaffolding, or coordinating changes across service boundaries all benefit from up-front structure because the cost of backtracking is high.

Planning doesn't help when the problem itself is unclear. Debugging a flaky test, optimizing a slow query, or fixing a subtle race condition all require iterative exploration. You need to run the code, observe behavior, form hypotheses, and retry. A plan-first agent will burn cycles generating speculative fixes, while an edit-first agent can test small changes and let the environment guide it.

The hybrid model works because it matches planning fidelity to problem complexity. For a one-line fix, the "plan" is implicit in the edit itself. For a five-file refactor, you want to know those five files up front, but you don't need a line-by-line edit plan for each.

Validation loops as the equalizer

Regardless of architecture, the make-or-break capability is a tight validation loop. An agent that edits blind and only checks correctness at the end will fail on non-trivial changes. An agent that plans perfectly but has no way to validate its plan against reality will also fail, just more slowly.

Fast, structured validation—linters that run in milliseconds, type checkers that highlight errors with file-line-column precision, test frameworks that isolate failures—is what lets both plan-first and edit-first agents recover. The plan-first agent validates its plan by simulating edits and checking constraints. The edit-first agent validates by making real edits and reading real errors.

Goatfied enforces this with mandatory gates: every edit triggers lint and compile checks before the agent moves to the next file. If validation fails, the error output gets fed back into the agent's context and it retries with smaller, more targeted diffs. This prevents the classic failure mode where an agent makes twelve edits, the twelfth breaks everything, and it has no idea which of the previous eleven is actually wrong.

Choosing an architecture for your agent system

If you're building an agent for a specific domain—say, adding tests to an existing codebase—edit-first makes sense because the structure is predictable and validation is fast. If you're building for open-ended feature development, hybrid with strong constraints and fast validation is safer.

The worst outcome is a plan-first agent with slow validation. You pay the cost of planning, then wait 30 seconds for a test suite to tell you the plan was wrong, then re-plan and wait again. The second-worst outcome is an edit-first agent with no validation until the end. You get speed, but you also get broken code that requires human cleanup.

Both plan-first and edit-first can work. What doesn't work is treating planning and validation as optional steps instead of core architectural constraints. The agent loop isn't plan or edit—it's plan, constrain, edit, validate, and retry, with each phase tuned to fail fast and feed information back into the next attempt.

Related posts

Plan-then-edit or edit-then-verify: comparing agent architectures | Goatfied Blog