Most AI debugging failures start before the agent touches code.
The founder pastes a wall of terminal output and writes, "fix this." The agent sees an error, guesses the cause, edits three files, and produces a new error. The founder pastes that one. The agent guesses again. After twenty minutes the app is worse, the diff is larger, and nobody remembers the original bug.
That is not debugging. That is feeding the agent smoke.
An AI agent can be a good debugger when the problem has a boundary. It needs the same thing a good human debugger needs: a reproduction, state, expected behavior, actual behavior, the first meaningful error, and a limit on what may change. Without that packet, the agent will optimize for movement. Movement feels like help right until it becomes damage.
The fix is a reproduction packet.
A bug report is a spec with evidence
A weak bug prompt says:
The dashboard is broken. Fix it.
A useful bug prompt says:
On
/command-center, signed in as a free user with no saved project, clicking "Add panel" opens the picker but selecting "Notes" does nothing. Expected: a Notes panel appears at the end of the board. Actual: picker closes, no panel appears, no toast. Console first error:Cannot read properties of undefined (reading 'panels')inCommandCenterPipeline.tsx. Reproduce before editing. Do not refactor unrelated panels. Return the smallest fix and the proof command.
The second prompt is longer because it carries the work the agent otherwise has to guess.
Good debugging is not "make the model smarter." It is removing ambiguity until the remaining task is small enough to solve.
The eight parts of a reproduction packet
Use this shape:
## Symptom
## Route or entry point
## Account and data state
## Steps to reproduce
## Expected behavior
## Actual behavior
## First meaningful error
## Change boundary and proof
Each part closes a loophole.
Symptom names the user-visible break. Not "React error." The symptom is "new users cannot create their first project."
Route or entry point prevents the agent from debugging a similar surface. A product often has three buttons with the same label.
Account and data state catches the hidden variable. Logged out, fresh account, Pro account, seeded localStorage, empty database row, old browser cache. State bugs hide here.
Steps to reproduce turn the problem into a loop. If the agent cannot reproduce it, it should not fix it yet.
Expected behavior gives the agent a target.
Actual behavior gives it the failure.
First meaningful error prevents terminal-dump archaeology.
Change boundary and proof stops a bug fix from becoming an architecture rewrite.
This is boring. Boring is what you want. Debugging should become less creative as it gets closer to code.
Find the first meaningful error
Beginners often paste the last error because it is closest to the prompt box. The first meaningful error is usually higher.
Modern dev servers are loud. One missing env var causes a failed request, which causes a React render error, which causes a hydration warning, which causes a retry, which causes another stack trace. The final line is often just the echo.
The first meaningful error is the earliest line that explains a cause:
- missing import
- undefined value
- failed network request
- invalid environment variable
- permission failure
- schema mismatch
- unhandled null state
- route not found
Ask the agent to explain that line before it edits:
Explain the first meaningful error in plain English. Identify the most likely layer. Do not edit files yet.
That one sentence saves a lot of bad diffs. If the agent cannot explain the error, it is not ready to patch the system.
Reproduce before repair
The most useful debugging instruction is also the one people skip:
Reproduce the bug before editing.
If the bug is in a browser, the agent should say which browser route, account state, and interaction it used. If the bug is in an API, it should show the request shape. If the bug is in a test, it should run the failing test alone before running the suite.
No reproduction, no fix.
There are exceptions. A syntax error can be obvious. A missing file can be obvious. But most product bugs are not syntax errors. They are state and boundary bugs. The agent needs to see the boundary fail.
This is also how you avoid collateral damage. If the agent can reproduce the bug in three steps, it can verify the fix in the same three steps. If it cannot reproduce the bug, it will verify by vibes.
Keep the change boundary small
AI agents are prone to politeness refactors. They see a bug in a component and decide the component could be cleaner. They see a null check and decide the state model needs a new abstraction. They see a failed request and decide the fetch layer needs a wrapper.
Sometimes they are right. During a bug fix, assume they are not.
Put the boundary in the packet:
- "Do not rename public types."
- "Do not change the data model."
- "Do not touch styling except where layout causes the bug."
- "Do not add a dependency."
- "Do not edit files outside
src/components/sections/command-centerunless you explain why first."
This is not micromanagement. It is blast-radius control.
For larger bugs, use the same discipline as big refactors: plan, slice, gate. The multi-file refactor guide applies to debugging too. If the fix needs more than a few files, pause and ask for a plan first.
Ask for the smallest falsifiable fix
The best bug-fix prompt includes the proof inside it:
Fix the smallest cause that explains the reproduction.
After the change, prove it by running:
1. the exact reproduction again
2. the nearest affected test or build command
3. one nearby negative case
If the smallest fix is not enough, stop and explain before widening scope.
The nearby negative case matters. If the bug is "fresh free user cannot add a panel," the negative case might be "returning user with an existing board still loads their saved panels." A lot of AI fixes solve the empty state by breaking the non-empty state.
You want the agent thinking in pairs: fixed case, adjacent case.
Save the lesson
The final step is not "ship." It is "write down what happened."
Every resolved bug should leave a small note:
Bug: Fresh users could not add first panel.
Cause: Empty workspace snapshot had no panels array.
Fix: Normalize workspace snapshot before panel mutations.
Proof: Reproduced on fresh account, added Notes panel, returning account still loaded saved board.
Watch next: any code path that reads workspace.panels before normalization.
That note becomes future context. Put it in the PR, the issue, the launch packet, or a project note inside Command Center. If the same bug shape appears again, the agent has a pattern to retrieve instead of rediscovering it.
This is how debugging compounds. Not by fixing faster once, but by leaving better traces for the next run.
What not to paste
Do not paste secrets. Do not paste full customer records. Do not paste private logs into a model without redaction. A debugging packet should be precise, not reckless.
Replace real emails with user@example.com. Replace tokens with [REDACTED]. Summarize private payloads by shape. If the bug depends on a secret value, say that and keep the secret out of context.
The same prompt-injection boundary applies to debugging external content. Logs, web pages, and issue text are data, not instructions. If an error message contains something that looks like a prompt, the agent should treat it as untrusted text. The stronger guidance in malicious README defense applies here too.
The grounded take
AI agents do not remove debugging discipline. They punish the lack of it faster.
Before asking for a fix, make the packet. Symptom, route, state, steps, expected, actual, first error, boundary, proof. Tell the agent to reproduce first, explain before editing, make the smallest falsifiable change, and verify both the fixed case and a nearby case.
The goal is not a smarter guess. The goal is to stop guessing.