How To Write Agent Prompts That Produce Reviewable Pull Requests

Published · Programming

An AI coding agent does not need a clever prompt. It needs an assignment that a reviewer could recognize after the fact.

That distinction matters. “Fix the flaky test” may be enough for a human who already knows the service, its constraints, and the team’s habits. To an agent, it is an invitation to investigate, guess at the intended behavior, touch every similar call site, clean up nearby code, and present a confident summary of a diff that is much larger than the original problem.

The useful output is not a maximum-size patch. It is a pull request whose intent, boundaries, validation, and remaining uncertainty are obvious to someone who was not in the original prompt session. That is what makes an agent-generated change reviewable.

This builds on How To Keep AI Coding Agent Changes Small Enough To Review and Designing Guardrails for AI-Generated Pull Requests. Those articles cover patch size and repository-level controls. This one is about the prompt: the small operating contract that tells the agent what to learn, what to change, what not to change, and how to prove the result.

A Good Prompt Is A Change Contract

The best prompts contain the same information a strong engineer would put in a compact ticket or pull request description:

  • The observed problem and the desired behavior.
  • The reason this is the right slice of work.
  • Explicit scope and exclusions.
  • Constraints the patch must preserve.
  • The evidence that will count as validation.
  • A stopping condition and a place for follow-up ideas.

That is not bureaucracy. It is an interface. Agents are good at following a clear interface; reviewers are good at checking whether a change honored it. When neither is present, the agent is forced to infer policy from code and the reviewer is forced to reconstruct intent from the diff.

Start with a human-written problem statement. “Make caching better” is not one. “When a request has no authenticated user, avoid writing an empty cache entry; preserve the cache behavior for authenticated requests” is one. The latter says what changed and, more importantly, what did not.

Separate Investigation From Implementation

For anything beyond a tiny mechanical edit, ask the agent to investigate before it edits. The first prompt should produce a plan, not a patch.

Investigate the intermittent timeout in the invoice export job. Do not edit files.

Return:
- the likely code path and failure mode,
- the smallest behavior change that addresses it,
- the production and test files you would touch,
- behavior that must remain unchanged,
- one targeted validation command,
- risks or questions that need a human decision.

This is cheap insurance. It lets you reject a bad premise before it turns into a large diff. It also exposes ambiguity early: maybe the timeout is intentional, maybe the retry policy is owned by another service, or maybe the test is testing the wrong contract.

Only after reviewing the plan should you request the patch:

Implement only the smallest patch from the approved plan.

Scope:
- Edit `invoice/export.py` and `tests/test_export.py` only.
- Preserve retry behavior for every other export path.
- Do not add dependencies, reformat unrelated code, or rename public symbols.
- Add the regression test described in the plan.

Run `uv run pytest tests/test_export.py -q`.
Stop after the patch. Put other cleanup ideas under `Follow-ups` without editing them.

The two prompts are deliberately different modes. Investigation rewards broad reading. Implementation rewards narrow editing. Mixing them is how an agent turns an interesting discovery into an unreviewable pull request.

Give The Agent Boundaries It Can Obey

“Keep it small” is useful sentiment, but it is weak instruction. Give the agent three kinds of boundaries instead.

Name The Behavior Boundary

Say which outcome is in scope and which adjacent outcomes are not.

Fix duplicate webhook delivery for the `payment_succeeded` event only.
Do not redesign idempotency for other events in this patch.

This prevents pattern matching from becoming unauthorized generalization. If you do want all call sites changed, make that a deliberate discovery step: ask for the inventory and a slicing plan first.

Name The File Or Ownership Boundary

Files are not always the best boundary, but they are an excellent default:

Edit only `auth/callback.py` and its existing test module. Do not touch the
shared session library, generated clients, deployment configuration, or lockfile.

If the agent discovers that the boundary is impossible, it should stop and explain why. A prompt should permit that answer. “I need to edit three more files” is useful information, not a failure of the tool.

Name The Non-Goals

Non-goals preserve the reviewer’s ability to reason locally:

  • No dependency upgrades.
  • No formatting-only edits outside touched lines.
  • No API or schema changes.
  • No logging or metrics changes unless required to verify the fix.
  • No opportunistic refactoring.

Agents are particularly susceptible to the last one because nearby cleanup often looks easy. Easy is not the same as in scope.

Ask For Evidence, Not A Victory Lap

“Run tests” is better than nothing. It is still too vague for a useful pull request. Ask what evidence addresses the particular risk.

For a bug fix, request a failing regression test before the production change. For a parser change, ask for representative valid and invalid inputs. For a CI change, ask for the exact local command and any limitation of local reproduction. For a migration, ask for an explicit rollback or compatibility statement.

Validation requirements:
- Add a test that fails on the old behavior and passes with the patch.
- Run the focused test command and the package lint target.
- State what was not run and why.
- In the final summary, distinguish observed results from assumptions.

That last line matters. A polished agent summary can accidentally turn a guess into a fact. Make the distinction visible: “verified locally” is different from “likely compatible with the production configuration.”

If the work is high-risk, require the agent to describe the failure mode it did not eliminate. Passing tests are a filter, not a proof that the behavior is right. For that review discipline, see How To Review CI Failures With AI Without Turning Off Your Judgment.

Require A Review-Ready Response Shape

The final agent response should be easy to turn into a pull request description. Ask for a fixed structure:

Return exactly:
1. Intent: one or two sentences in plain language.
2. Changed: files and behavior changed.
3. Not changed: important exclusions.
4. Validation: commands run and results.
5. Risks: assumptions, unrun checks, or rollout concerns.
6. Follow-ups: useful work deliberately left out of this patch.

This is not a substitute for reading the diff. It makes the reading more efficient. The reviewer knows where to challenge scope, where to check tests, and where the agent believes uncertainty remains.

It also makes it harder for the author to blindly paste an agent-written description. The author still owns the intent. Before opening the PR, rewrite anything that is unclear or does not reflect the actual change.

Prompt Templates That Work In Real Repositories

Here are three templates worth keeping nearby.

Small Bug Fix

Fix [specific observed behavior] in [module or feature].

Desired behavior: [concrete outcome].
Preserve: [behavior that must not change].

Scope:
- Touch only [files or directory].
- Do not change [dependencies, public APIs, config, formatting, etc.].
- If a wider change is needed, stop and explain before editing it.

Validation:
- Add a regression test.
- Run [focused command].

Final response: Intent, Changed, Not changed, Validation, Risks, Follow-ups.

Mechanical Change With Many Files

First inventory every use of [symbol or pattern] under [directory]. Do not edit.
Classify each match as required, optional, generated, or unsafe to change.
Propose pull-request-sized slices and the validation for each.

Wait for approval before implementing a slice.

Mechanical work is where teams most often confuse a large diff with a broad change. The inventory gives reviewers a map and gives the author a chance to split the work by package, API boundary, or risk level.

Test Or CI Failure

Investigate why [test or job] fails. Do not suppress, retry, skip, or loosen the
assertion unless the evidence shows the assertion is wrong.

Return the reproduction, likely root cause, smallest safe fix, and the test that
would distinguish a real fix from a masked failure. Do not edit until the plan is approved.

This wording is intentionally defensive. AI agents can be very good at making a red check turn green. A green check is only useful when it represents the right contract.

The Prompt Cannot Transfer Responsibility

Even an excellent prompt does not make an agent accountable for a production change. It gives the human a better artifact to own.

Read the diff. Check the changed behavior against the stated intent. Run or inspect the validation that matters. Challenge surprising edits. Treat the agent’s confidence as a signal to investigate, not evidence by itself.

The goal is not to make agents behave like senior engineers. The goal is to make their output fit inside a senior engineer’s review process. Write prompts as change contracts, keep investigation separate from implementation, require evidence, and give the agent a stopping point. You will get smaller pull requests, sharper reviews, and a much better chance that speed actually turns into reliable delivery.

For more practical engineering guidance, visit Slaptijack.

Slaptijack's Koding Kraken