Find the mechanism behind a code or system failure, fix it when the user asks for a fix, and show that the fix removes the symptom the user reported. The work ends in one of two results: a cause confirmed by a check that shows the symptom and loses it when only that cause changes, or an evidence-limited diagnosis that names the most likely cause, its confidence, and the evidence that would settle it.
Route other questions elsewhere
This skill looks for a defect in code, configuration, data flow, or environment. Some reported bugs ask a different question:
- Expected behavior or a quality criterion is not yet defined, as in "is this output good enough?":
evaluation-design. - The answer is a rate or a comparison across stochastic samples, models, prompts, or data, such as whether a change makes a model fail less often:
ml-experiment. - The question is whether a result, score, or benchmark number can be trusted:
evaluation-audit. - A run in an evaluation campaign failed or stalled:
evaluation-operations, which owns campaign status and diagnosis. When that work isolates a defect in harness or pipeline code and the user asks for the fix, this skill can take the defect.
A single agent or model failure still belongs here when the question is mechanical: a truncated tool result, a parser that drops a field, a timeout, a retry that resends stale state. Ask whether the answer is a mechanism to find or a rate to estimate.
Pin the reported symptom
Start from what the user observed: the exact error, wrong value, timing, or behavior, the input and environment where it happened, and what they expected instead. Collect when it began and what changed around then. Keep this symptom as the target of every later step. A different failure found nearby is a separate finding; fixing it does not close the reported bug.
Redact secrets before showing commands, logs, or captured requests. Keep credentials in environment variables so loops and quoted output never carry them, and quote only the lines needed to show the failure. If redaction removes what the diagnosis needs, say so and ask.
Build a feedback loop when one is possible
A feedback loop is a command that drives the failing code path and reports whether the reported symptom occurred. With one, hypotheses become cheap to test and the fix becomes checkable, so spend real effort here before reading code at length. A useful loop is:
- specific: it checks the reported symptom, not merely that something ran;
- repeatable: the same verdict on every run, or for an intermittent failure a known and usefully high reproduction rate;
- fast enough to run many times;
- runnable by the agent alone, or with a person guided by a script that records their observations.
Read feedback loops when the right loop is not obvious, when the loop is slow or noisy, when an intermittent failure needs a higher reproduction rate, when an agent or pipeline failure needs a replay, or when shrinking a reproduction.
For an intermittent failure, raise the reproduction rate instead of waiting for a clean reproduction. A failure that appears in half the runs can be debugged; one that appears once in a hundred runs usually cannot until something raises the rate, and each condition that raises it is evidence about the cause.
Once the loop fails, shrink the scenario by removing inputs, steps, configuration, and callers one at a time, running the loop again after every removal, until every remaining piece is needed for the failure. A small reproduction leaves fewer places for the cause to hide. Keep the original scenario as well, because the final check runs on it.
Show the loop command and its failing output before relying on it.
Diagnose with limited evidence when no loop is possible
Some failures resist a fast loop: a rare agent failure seen once in a long trajectory, behavior that occurs only in production, a run that costs hours or real money to repeat, or an environment the agent cannot reach. Do not stall waiting for a loop, and do not claim one exists. State what was tried and why no loop is available, then reason from the evidence that exists: logs, traces, transcripts, metrics, saved inputs, version and configuration diffs, and above all contrasts between failing and succeeding cases that otherwise match. The earliest point where a failing case diverges from a succeeding one is usually the most informative place to look.
Ask for what would cheaply strengthen the evidence: access to the environment that reproduces the failure, a captured artifact such as a log excerpt, trace, request dump, or screen recording, or permission to add temporary instrumentation there. Repeating an expensive run, instrumenting production, or changing a shared system needs the user's approval.
State confidence in plain terms and give the reason:
- confirmed: a check shows the symptom and loses it when only the suspected cause changes, such as a loop that fails before the fix and passes after it;
- likely: the evidence fits one hypothesis and has eliminated the main rivals, but no such check exists;
- possible: rivals remain that the evidence cannot yet separate.
For anything short of confirmed, name the specific evidence that would raise the confidence or eliminate each remaining rival, so later work knows what to collect.
Test rival hypotheses against the evidence
Before testing, write several competing explanations, usually three to five, and rank them. A single favored story fixes attention on whichever explanation came first and reads every new observation as support for it. Each hypothesis states a prediction that separates it from the others, for example: "If the cache key ignores the locale, the failure appears only after a request in another locale and disappears with the cache disabled." A hypothesis with no distinguishing prediction is a hunch; sharpen it or drop it.
Choose the next check by how many hypotheses it can separate, not by which one it might confirm. Keep a short record of which observation eliminated which hypothesis, so the conclusion rests on eliminated rivals as well as on matching evidence. Share the ranked list when the user is present, since they often know about a recent change or an explanation they have already ruled out; continue without waiting when they are not.
When every hypothesis falls, return to the symptom and the loop before generating more. The loop may check a different failure, or the reproduction may have lost a condition the failure needs.
Instrument for a specific prediction
Every probe answers a question that a hypothesis raises, and each probe varies a single factor. Prefer a debugger or REPL at the boundary where the hypotheses diverge; otherwise add a few targeted logs there. Logging everything and searching the output buries the signal.
Give each temporary log line or probe a unique tag, such as [dbg-7f3a], so a single search finds and removes all of them.
For a performance regression, measure before changing anything. Establish a baseline with a timing harness, profiler, or query plan, compare it with the slow case, and bisect between a known fast state and a known slow one. Logs rarely locate a timing problem.
Fix and verify against the original symptom
Fix the cause the evidence supports, not the last visible step of the symptom. Rerun the loop on the original, unshrunk scenario and confirm the reported symptom is gone; a passing minimal case is not enough on its own. When the fix changes behavior that other callers rely on, check those callers too.
Follow the project's own policy on tests. Read its instructions and its existing test layout before adding one. Add a regression test when the project expects one and a seam exists where the test drives the same chain of calls that produced the failure. A test at a seam too shallow to reproduce the chain that caused the failure gives false confidence, and the missing seam is itself worth reporting. Some projects forbid adding tests to certain code, such as evaluation code, and verify through real run logs instead; there, the verification is a real run whose log shows the symptom gone. A reproduction script written only as a loop does not have to become a kept test.
For an evidence-limited diagnosis, say what verification is possible now and what remains. A fix may become checkable only at the next production occurrence or the next long run; name the signal to watch for.
Clean up and report
Before calling the work done, remove tagged instrumentation by searching for the tag, delete throwaway harnesses or move them to a clearly marked location, and restore any configuration changed for the reproduction. When the fix lands in a commit or pull request, state the confirmed cause in its message so the next reader learns the mechanism.
Report the symptom as reported, the cause and its evidence, the hypotheses eliminated and how, the fix, the verification command with its output, and any residual uncertainty. For an evidence-limited diagnosis, lead with the confidence level and the evidence that would change it.
Source
The feedback-loop, reproduction-rate, ranked-hypothesis, and tagged-instrumentation ideas are adapted from the diagnosing-bugs skill in mattpocock/skills at commit 49dd158 (MIT License, Copyright (c) 2026 Matt Pocock) and rewritten here. This version replaces that skill's rule against hypotheses before a deterministic loop exists with an evidence-limited path, and it follows each project's test policy instead of requiring a regression test.