Debug and bug fixing 🐛
Debugging is the use case where the agent is most useful and most dangerous at the same time. Useful because it can correlate stack traces, logs, and code in seconds. Dangerous because an agent that “fixes” a bug by hiding its symptoms is worse than no fix at all. The difference lies in the quality of context you provide and your ability to evaluate whether the diagnosis makes sense.
A bug fixed without understanding its root cause is not a fix: it is a bridge to the next bug.
When to use the agent for this use case 🎯
- Clear stack trace — you have a complete stack trace and want to understand the cause.
- Reproducible bug — you know how to replicate the problem and want a quick diagnosis.
- Structured logs available — you have runtime logs the agent can correlate to code.
- Simple to medium bugs — null pointer, out of bounds, type error, wrong logic.
- Adding regression tests after the fix — you want the bug to stay fixed.
When NOT to use the agent ⛔
- Race conditions and concurrency — the agent cannot observe thread interleaving at runtime.
- Performance and bottlenecks — requires profiling, not static analysis.
- Architectural bugs — design problems that require redesign.
- You lack the context — if you cannot describe the problem, neither can the agent.
- Agent is in a loop — after 2 failed attempts, reset the session.
Opening prompt 📝
“CONTEXT: [problem description]. STACK TRACE: [complete stack trace]. RELEVANT FILES: [list]. TASK: analyze the root cause and propose the minimal fix. DO NOT apply changes.”
Concrete example:
“CONTEXT: the GET /orders endpoint returns 500 when the user has no orders. TEST: TestGetOrdersEmpty fails with ’nil pointer dereference’. STACK TRACE: orders/handler.go:47 → orders/service.go:112. RELEVANT FILES: orders/handler.go, orders/service.go, orders/repository.go. TASK: analyze the root cause and propose the fix. DO NOT apply changes.”
Workflow 🔧
1. Bug reproduction 🎯
First, make sure you can replicate the problem deterministically. If no failing test exists, create one before asking the agent to fix.
|
|
The failing test is your validation anchor. Without it, you cannot know if the fix actually works.
2. Hypothesis formulation 🧠
Ask the agent to analyze the context and formulate three distinct hypotheses about the root cause, ordered by probability. Without applying changes.
“Analyze the stack trace and code. Formulate 3 hypotheses about the root cause, ordered by probability. For each hypothesis: (1) what condition triggered the error, (2) the propagation mechanism, (3) what to inspect to confirm it. DO NOT apply changes.”
This step is critical: if the agent jumps directly to the fix without formulating hypotheses, it is doing shotgun debugging.
3. Hypothesis verification 🔍
For each hypothesis, verify that it is testable. If the agent cannot determine the cause with certainty, ask it to insert temporary logs or assertions to verify empirically.
“Insert temporary logs to verify hypothesis #2: [description]. Run the test and report the output.”
4. Atomic fix ✏️
Once the hypothesis is confirmed, ask for the minimum necessary fix. You do not want a module refactoring: you want the bug fix.
“Apply the strictly necessary fix in [file] to resolve [confirmed hypothesis]. Verify the test passes. Remove all temporary logs.”
5. Validation and regression ✅
After the fix:
- Run the reproduction test: it should pass.
- Run the full test suite: no regressions.
- Review the diff: no collateral changes.
|
|
Prompt templates 📋
Template 1 — Diagnosis
|
|
Template 2 — Fix
|
|
Anti-patterns 🚫
- Shotgun debugging — letting the agent randomly change code hoping the error disappears. Reproduce first, then diagnose, then fix.
- Error loops — if the agent proposes the same solution after 2 attempts, reset the session with new constraints.
- Exception masking — accepting fixes that wrap problematic code in empty try-catch blocks or return arbitrary default values.
- Complete delegation — “fix my bug” without context is like asking a doctor to treat you without describing symptoms.
- Permanent logs — do not leave debug instructions in the final code.
Acceptance criteria 📏
| Criterion | Requirement | Validation |
|---|---|---|
| Minimal repro | Test that reproduces the error before the fix | Verify it fails before and passes after |
| No regressions | Full test suite green | go test ./... or equivalent |
| Code hygiene | No temporary logs in final diff | git diff |
| Root cause | The fix addresses the triggering mechanism | Code review of hypothesis and patch |
Important notes ⚠️
Debugging is an iterative but controlled process. Each cycle must have: context → hypothesis → verification → fix → validation. If a cycle fails more than twice consecutively, terminate the session and restart with a prompt that integrates the negative outcome as an explicit constraint.
When to stop and ask for help
The agent is not the right tool for all bugs. If the problem involves:
- Concurrency and race conditions
- Performance and profiling
- Architecture and design
- Execution environment (production vs development)
…then the agent can help you insert logs and telemetry, but the diagnosis and decision remain yours.
Series references 📚
- Writing prompts that work — prompt templates in this context
- Surviving sessions — error loop management
- Adding features to an existing codebase — when bugs emerge during development