AI can write code quickly. That is useful, but code generation is not the hard part of software engineering. The hard part is deciding what should change, choosing a design that fits the system, and proving that the result works.
The best way to code with AI is to build a tight feedback loop around those decisions. A human owns the goal and the important tradeoffs. An AI agent helps inspect the repository, write a plan, make a focused change, run checks, and review the result. Each step produces evidence for the next one.
This is not just a cautious way to use AI. It is also a practical way to get more value from it. A 2026 analysis of about 400,000 Claude Code sessions found a common division of labor: people made most of the decisions about what to do, while the agent made most of the decisions about how to do it. The same study found that domain expertise still improved the chance of success. AI did not remove the need to understand the problem.
The research on speed is less simple than the marketing. A 2025 controlled study from METR found that experienced open-source developers took 19% longer on the tasks in that study when they could use AI. METR's follow-up work with newer tools showed signs of a speedup, but the researchers said selection effects made the size hard to estimate. DORA's 2025 research reached a useful broader conclusion: AI acts as an amplifier. It can strengthen a good engineering system, and it can make a weak one produce mistakes faster.
So the goal is not to maximize the amount of code an agent writes. The goal is to reach a correct, maintainable result with less wasted effort.
AI raises the bar for human developers
Today's strongest coding agents are far beyond autocomplete. They can explore an unfamiliar repository, propose an architecture, change many files, run tests, find mistakes, and revise their work. They can often produce code that is clean, consistent, and professional.
In my experience, a strong agent can sometimes perform like a principal or distinguished engineer at the keyboard. That does not mean the agent is a principal engineer. Senior engineering includes sustained judgment, product context, influence across teams, and accountability for the result. An agent can show remarkable judgment in one part of a change and miss an obvious constraint in another.
The outcome depends heavily on how the human uses the agent. A capable agent under weak direction can build the wrong system very well. Under clear direction, with strong feedback and checks, the same agent can complete work that would once have required much more time.
This puts a higher expectation on human developers. The agent can produce code faster than a person can read it, so the human must keep pace at the level of decisions and evidence. Developers need to be able to:
- Review a proposal, understand its tradeoffs, and make the final decision.
- Ask questions that expose assumptions. What could fail? What evidence supports this choice? Is there a simpler option? Which fact are we least sure about?
- Find suspicious details in long plans and large diffs. Look for confident claims without sources, new abstractions without a real consumer, missing failure paths, and tests that repeat the same assumption as the code.
- Read code quickly and strategically. Trace inputs, outputs, state changes, trust boundaries, error handling, and the paths that tests do not cover.
- Know how to control the agent. Set scope, permissions, checkpoints, stopping conditions, and required verification before the work begins.
- Bring product and domain knowledge. The agent cannot choose the right outcome when it does not understand what matters to the user or the business.
This is not a lower-skill form of engineering. The bottleneck moves from writing every line to directing work, judging decisions, and verifying results. Developers who practice those skills can use agents as a large force multiplier. Developers who blindly trust polished output may only discover the mistakes after they become expensive.
This does not mean that only senior engineers can benefit. Less-experienced developers can use agents to learn and ship useful work. They should slow down when they cannot explain a decision, and they should ask an experienced human for help when the risk exceeds their understanding.
The workflow in one page
For any change that has meaningful design or product risk, use this loop:
- Understand the current system and define the outcome.
- Write a plan with decisions, alternatives, tests, risks, and open questions.
- Ask a fresh reviewer to challenge the plan.
- Resolve important questions before implementation starts.
- Implement one small phase.
- Run deterministic checks and inspect the real result.
- Ask a fresh reviewer to compare the diff with the plan and the repository rules.
- Open a focused pull request and get human review.
- Merge only after the evidence is clear, then watch the result.
This loop is deliberately ordinary. Good AI-assisted development still looks like good software development. The agent increases the speed and depth of each step. It does not make the steps optional.
Step 0: decide whether the task is ready for an agent
An agent works best when the task has a clear boundary and a result that can be checked. Before planning, answer four questions:
- What problem are we solving?
- Who benefits, and what should improve for them?
- What would prove that the work is complete?
- Which decisions require a human because they affect product direction, security, money, privacy, or an irreversible migration?
If the task is vague, do not ask the agent to turn the vagueness into code. Use the agent to research the system and list the missing decisions. Then answer those questions first.
GitHub gives similar advice for its coding agent. Its documentation recommends a clear problem statement, complete acceptance criteria, and a useful scope. It also suggests that complex, sensitive, or ambiguous tasks need more human involvement.
Not every change needs a long design document. A typo or a local rename may need only a short checklist. Match the plan to the cost of being wrong. The rest of this guide targets changes where a bad direction would waste hours or damage the system.
Step 1: write the plan before the code
This is the most important step.
An AI agent can follow a bad plan with impressive speed. It can also make the code look consistent enough that the design error survives a quick review. A detailed plan moves the most important reasoning to the point where changes are still cheap.
A useful plan contains the following sections.
Current state
Describe what exists today. Name the relevant files, boundaries, dependencies, commands, and constraints. Link to the source instead of relying on memory.
Ask the agent to inspect the repository before it proposes a solution. A plan based on the actual code is much safer than one based on a task description alone.
Goal and non-goals
State the user-visible or system-visible outcome. Then state what this change will not do. Non-goals keep an agent from adding attractive features that nobody requested.
Acceptance criteria
Write conditions that can be checked. "Improve the settings page" is vague. "A keyboard user can change and save each setting at a 375-pixel viewport, and the saved value remains after reload" is testable.
Acceptance criteria should cover behavior, not only implementation. A file can exist and a test can pass while the user problem remains unsolved.
Design decisions
For every important choice, record:
- the options considered
- the benefits and costs of each option
- the constraints that rule options in or out
- the recommended choice and why it wins
- the facts that are uncertain or may change
This section deserves most of the engineer's attention. The agent can gather options and trace dependencies. A human should own tradeoffs that depend on product goals or business context.
Do not hide uncertainty. If a decision depends on an API limit, an unclear requirement, or an untested assumption, say so. Run a small experiment when evidence is cheaper than debate. Update the plan with the result before implementation continues.
Implementation phases
Split the work into small vertical slices. Each phase should leave the repository in a valid state and have its own proof of completion. Prefer a working path through the system over a large horizontal layer that nobody can use yet.
For each phase, list:
- the exact outcome
- the files or components likely to change
- dependencies on earlier phases
- tests and manual checks
- documentation that will become stale
- a clear stopping condition
Large work may need one pull request per phase. Smaller work may fit in one pull request with several checkpoints. The right unit is the smallest change that a reviewer can understand and validate without reconstructing the whole project.
Test plan
The test plan should match the ways the change can fail. Include the relevant layers:
- formatting, linting, and type checks
- unit tests for local rules and edge cases
- integration tests across important boundaries
- end-to-end tests for user flows
- build or packaging checks for the artifact that ships
- manual checks for visual behavior, accessibility, or operations
Tests should run offline and produce the same result each time when that is possible. If a test needs a model or external service, use a recorded fixture or a local substitute. A test that depends on a live service is weak evidence because an agent and CI may not be able to repeat it.
For a bug, start with a test that reproduces the failure when practical. For a feature, test the behavior at the boundary the user cares about. Avoid tests that only confirm the agent's private implementation choices.
Rollout, rollback, and caveats
Explain how the change reaches users, what should be monitored, and how to recover. Record data migrations, compatibility risks, feature flags, security concerns, and known gaps.
Finally, list open questions. Do not let an agent silently answer a question that changes the scope or architecture.
Treat the plan as a tested hypothesis
A plan is not correct because it is detailed. It is a model of the change, based on the evidence available at the time.
This distinction protects the work from context pollution. If an early assumption is wrong, a long conversation can keep pulling the agent toward it even after a correction. Use a few simple safeguards:
- Put settled facts and decisions in the plan, not only in chat history.
- Label assumptions and unresolved questions.
- Require the implementation agent to inspect the relevant code again.
- Start a fresh session after a major correction.
- Update the plan while work is active. Record why the approach changed.
- Keep the old reasoning in version control so reviewers can see the change.
The plan should guide the work, but evidence from code and tests outranks it. If the plan and the repository disagree, stop and resolve the difference. Do not force the code to match a stale assumption.
Step 2: have a fresh agent review the plan
The authoring agent has already built a story about why its plan makes sense. A fresh agent is more likely to notice a missing constraint or a cheaper design.
Give the reviewer the task, the plan, the repository instructions, and access to the relevant code. Ask for findings, not a rewrite. A useful review prompt is:
Review this plan as a skeptical senior engineer. Check every claim against the current repository. Find missing requirements, invalid assumptions, unnecessary scope, weak test coverage, security risks, and simpler alternatives. For each finding, explain the concrete failure it could cause and the smallest fix to the plan. Do not comment on style.
The reviewer should answer questions such as:
- Does the plan solve the stated user problem?
- Does it respect the existing architecture and repository rules?
- Are the alternatives real, and are the tradeoffs accurate?
- Can every phase be implemented and verified on its own?
- Are failure paths, migrations, and rollback covered?
- Does the plan create speculative abstractions or unrelated work?
- Which claims need a source or a small experiment?
Review does not transfer ownership to the second agent. The human resolves disagreements, especially when both answers are plausible. If the review changes a major decision, update the plan and use a fresh context for implementation.
Anthropic calls this general pattern an evaluator-optimizer workflow. It works best when the evaluation criteria are clear and feedback can improve the result. That is exactly why the plan needs acceptance criteria before the reviewer arrives.
Step 3: implement one phase at a time
Give the implementation agent one phase, not the entire roadmap, unless the change is small. Include the approved plan and point it to the repository instructions. Ask it to inspect the current state before it edits files.
Each phase should follow a short loop:
- Restate the phase outcome and the proof required.
- Inspect the files that define the current behavior.
- Make the smallest coherent change.
- Run the relevant checks.
- Inspect the diff for unrelated edits.
- Report the result, any plan deviation, and the remaining risk.
Do not use several agents merely because parallel work is available. Parallel agents are helpful when tasks are independent, such as research across separate systems or reviews with different focuses. They are risky when several tasks touch the same design or files. The coordination cost and conflicting assumptions can exceed the time saved.
Simple workflows are often enough. Anthropic's public guidance on agent systems recommends starting with simple, composable patterns and adding complexity only when it improves the result. The same rule applies to coding with agents.
Step 4: verify the result after every phase
The agent should not say "done" because the code looks right. It should present evidence.
Run the full required verification command when the repository has one. Also run focused checks that cover the changed behavior. Build the same artifact that will ship. If the change affects a user interface, open it at the required viewports and use the flow. If it affects a migration, run the migration against a realistic local fixture and test rollback or forward recovery.
Passing tests are necessary, but they are not enough. The same agent may write code and tests that share the same mistaken assumption. Compare the result with the acceptance criteria. Inspect logs, rendered pages, API responses, database state, or other observable outputs.
Read the diff yourself
Do not let the agent's summary replace the Git diff. Some agent clients provide their own review interface. For example, Codex has a review pane with several Git scopes and line-specific feedback. These interfaces will keep changing, and they may still be less comfortable than the editor you use every day.
I prefer to review changes in Visual Studio Code. Open View > Source Control, or select the Source Control icon in the Activity Bar. Then select a file under Changes or Staged Changes. VS Code opens its diff editor and compares the file with the last committed version. It uses a side-by-side view when there is enough space, and it can switch to an inline view. The official VS Code source control guide shows the same workflow.
You do not need to switch to Cursor, or any other AI-focused editor, just to review code written by an agent. Let Codex, Claude, or another agent make the change, then use the Git tools in the editor you already know.
Skimming the diff is still valuable, especially for a developer who can read the language. It gives you a fast sense of the shape and risk of the change. On the first pass, look for:
- files that should not have changed
- dependencies or abstractions that the plan did not require
- changes to authentication, permissions, persistence, migrations, or configuration
- deleted validation and error handling
- tests that became weaker or now avoid the important behavior
- large generated sections that hide a small hand-written mistake
Then read the high-risk paths closely. Trace data across boundaries and inspect the tests beside the code. You do not need to understand every harmless formatting change with equal depth, but you should understand the behavior and risk before you approve the work.
Then ask a fresh reviewer to review the implementation. This is an important refinement to the original loop: after a phase, do not ask only for another review of the plan. Ask the reviewer to compare four things:
- the user goal
- the approved plan
- the actual diff
- the verification evidence
The reviewer should focus on defects caused by the change. It should check correctness, security, missing tests, unwanted scope, maintainability, and plan drift. It should not fill the review with style preferences.
A separate review helps, but it is not independent proof. Agents may share blind spots, especially when they use the same model or instructions. GitHub's guidance makes the same boundary clear: AI code review can support human reviewers, but it does not replace human review. Never apply review suggestions without testing them.
Step 5: open a pull request that explains the change
A good pull request should let a reviewer understand the work without replaying the agent conversation. Include:
- the problem and the chosen solution
- the relevant plan or design decision
- the user-visible behavior
- the important files and boundaries
- the exact checks that passed
- screenshots or recordings for visual changes
- known risks, follow-up work, and rollback notes
- any deviation from the plan and why it was necessary
Keep the pull request focused. AI makes it easy to produce a large diff, but reviewers do not gain matching review capacity. DORA has warned that faster code generation can lead to larger batches, which are harder to review and more likely to create instability. Small batches preserve the feedback loop.
Use an AI reviewer before or during pull request review to catch routine issues and explain unfamiliar parts of the diff. A human still decides whether the design belongs in the system and whether the evidence is strong enough.
Step 6: merge, observe, and improve the system
Merge when the following statements are true:
- The acceptance criteria are met.
- Required checks pass from a clean state.
- Review findings are resolved or consciously accepted.
- The documentation matches the new current state.
- A human can explain the important design and risk.
- Rollout and recovery are understood.
The loop does not end at merge. Watch the signals named in the plan. Confirm that users get the expected result. If production reveals a gap, add a regression test and record the lesson where future agents will read it.
Repeated review comments often point to missing repository guidance, weak automation, or a poor interface. Fix the system, not only the latest diff. Add a clear instruction, a lint rule, a test helper, or a better error message when it will prevent the same mistake.
Keep permissions proportional to the risk
An agent that can edit code may also be able to run commands, access credentials, publish packages, change infrastructure, or send messages. These are different levels of authority.
Use a sandbox for routine work. Do not place production secrets in the agent's environment unless the task truly requires them. Require approval for destructive commands, production deployments, data deletion, permission changes, and external communication. Treat issue text, web pages, logs, and repository files from unknown sources as untrusted input.
More autonomy can be useful on low-risk, reversible work. High-risk work needs smaller steps and explicit human checkpoints. Anthropic's 2026 work on trustworthy agents frames the same tension around human control, transparency, secure interaction, and privacy.
Common failure modes
One enormous prompt
The agent receives a broad goal and disappears for an hour. The result is a large diff with many hidden decisions. Split the work at decision and verification boundaries.
A plan written from the ticket alone
The ticket describes intent, not the current system. Require repository inspection and links to the source of important constraints.
A plan treated as law
New evidence appears, but the agent keeps following the old design. Treat the plan as a versioned hypothesis and update it on purpose.
The same agent acts as author and only reviewer
Self-review is useful, but it often repeats the original assumptions. Add a fresh review and keep human review for consequential changes.
Tests that prove the implementation, not the outcome
An agent tests its helper functions while the user flow is broken. Start from acceptance criteria and observable behavior.
Too much context
More context is not always better. Give the agent the goal, approved plan, repository rules, and relevant source. Avoid a long chat transcript full of discarded ideas.
Parallel work without independent boundaries
Several agents edit related files with different assumptions. Parallelize research and independent components. Serialize work that shares a design or state.
Merging because every automated check is green
Automation checks known properties. It cannot prove that the product decision is right. The human owner still signs off on intent and risk.
A compact checklist
Before code:
- Inspect the current system.
- Define the user outcome, non-goals, and acceptance criteria.
- Record decisions, alternatives, tests, risks, and open questions.
- Get a fresh plan review.
- Resolve decisions that need human judgment.
After each phase:
- Run focused tests and the repository's full verification command.
- Inspect the real output and the diff.
- Record deviations from the plan.
- Get a fresh implementation review against the plan.
Before merge:
- Keep the pull request small and explain the evidence.
- Get human review for the design and risk.
- Confirm rollout and recovery.
- Update documentation that describes the current system.
After merge:
- Observe the result.
- Turn failures into regression tests.
- Improve repository instructions and tools when a mistake repeats.
The main idea
AI changes the cost of producing code. It does not change what makes code trustworthy.
The practical advantage comes from a better loop: think carefully, write down the plan, challenge it, implement a small piece, verify the real result, review the diff, and keep a human responsible for the decisions that matter. When that loop is strong, a more capable agent makes the whole system faster. When the loop is weak, the same agent simply helps the team get lost sooner.
Further reading
Sources checked on August 14, 2026:
- Agentic coding and persistent returns to expertise (Anthropic, 2026)
- We are changing our developer productivity experiment design (METR, 2026)
- State of AI-assisted Software Development 2025 (DORA, 2025)
- Best practices for using GitHub Copilot to work on tasks (GitHub Docs)
- Building effective agents (Anthropic, 2024, with a later update notice)
- Accelerating pull requests with GitHub Copilot (GitHub Docs)
- Trustworthy agents in practice (Anthropic, 2026)
- Code review in Codex (OpenAI Docs)
- Quickstart: use source control in VS Code (Microsoft)