cd /news/ai-agents/one-symptom-ten-problems-a-kotlin-sp… · home topics ai-agents article
[ARTICLE · art-123348] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

One symptom, ten problems: a Kotlin + Spring Boot + Kafka debugging case

Explyt product manager reviews a debugging session in which a developer used the company's AI agent for JetBrains IDEs to resolve a single symptom in a Kotlin, Spring Boot, and Kafka payments system, uncovering multiple defects, about half unrelated to the original symptom. The session revealed that the agent was strategically passive, did not distinguish verified facts from guesses, and proposed fixes before problems were fully localized, though it did provide accurate code explanations and SQL queries.

read9 min views2 publishedSep 8, 2026

A single visible symptom led to many defects, half unrelated to it but all tied to one invariant about async TID processing. Debugging is invariant discovery.

One visible symptom opened the session. By the end of it the developer and the agent had fixed many defects, about half of them unrelated to that symptom. All of them, though, sat inside the same scope, and the developer summed that scope up in one sentence:

Any operation on a TID must go through the single asynchronous path and must not let TMS and EMV drift apart.

I am the product manager at Explyt, where we build an AI agent for JetBrains IDEs. This session ran in our own agent, in regular chat mode, with a current frontier model, on a Kotlin and Java codebase with Spring Boot and Kafka in a payments system. I did not run it myself; I went through the log afterwards as part of our review of how people debug with an agent in practice. Debug mode was not used. What follows is a review of the shape of the work, with the session's own details left out. The defects are described as kinds, and the number in the title is the topic's working name; the log gives no count I could verify.

Previously on the Explyt blog, we compared two agent runs on one JVM bug, one working from the log and one from a breakpoint: Superpowers vs Plain Old Debugger in Explyt. That case was one bug with one cause. This one has the opposite shape, one symptom with many causes, and it stresses a different part of the debugging loop.

I cannot show you the symptom or the defects; the log belongs to the developer's project. What I can describe is the shape.

The developer came in with one observable problem. Working through it with the agent, they found a defect, fixed it, and something else broke, in a different way. Then another defect, another fix, another different breakage. About half of what they fixed had nothing to do with the original symptom. Every fix, however, touched the same scope: how the system handles a terminal ID (TID) across its asynchronous path and keeps two downstream systems, TMS and EMV, consistent. The sentence in bold above is how the developer described that scope.

A few times the developer asked the agent to add something and later asked it to roll that back. That is the texture of the session: iterative, exploratory, with the agent along for the ride.

The agent proposed SQL queries to inspect the current state in TMS and EMV, so the discussion started from actual rows. It warned about risks in code it was asked to change. It explained what a given piece of code did, when asked, and got it right. It did not add new debug logging; it worked from the log statements that already existed, which kept the diff clean.

All of that is real help; a developer working alone would have done that typing themselves.

The first failure was strategic passivity. The agent did not run the investigation. It waited for the developer to bring the next piece of evidence, reacted to it, and waited again. At no point did it say: here is my current theory, here is what would falsify it, let me check. The developer decided what to look at next, every time.

The second: verified facts and guesses came out in the same confident voice. The developer had to keep track of which statements had been checked and which had not. In a session with many defects that bookkeeping is most of the job, and the agent was not doing it.

Third, the agent proposed fixes before the problem was localized. The developer applied them; the log shows no rollback of those fixes, at least not in the chat. The agent checked that each change compiled and passed lint. It did not check that the fix removed the symptom. Several fixes turned out to be ineffective: something else broke afterwards, differently. Reading that part was uncomfortable. I have accepted a plausible fix at the end of a long day for the same reason: it compiled.

The fourth failure is the one that matters for tooling. The agent never built a model of how the entities relate: what TID is, what TMS and EMV each own, what "consistent" means between them. Without that model, every defect looked like a separate bug; with it, they are one invariant violated in several places.

The developer pasted into the chat, by hand, fragments of SQL scripts and their results, Spring Boot and Kafka log excerpts, HTTP responses, messages from Kubernetes and Docker Compose, and configuration files. The agent's own use of the terminal was limited to git.

So the agent's picture of the running system was whatever the developer chose to show it, in the order they chose, with their framing already applied. That is a poor position from which to form an independent theory, and it explains the passivity. This is the failure I keep coming back to, and I do not have a tidier answer than "give it instruments".

The review proposed two fixes. Give the agent a browser and a terminal, and make it use them. And give it a debugging method with a written journal: hypotheses, experiments, results, and a working theory that includes the data model and its invariants, along the lines of the Superpowers systematic-debugging skill and the parallel-debugging variant. Both fixes assume the agent can run an experiment and read its result without a human in between. A method without instruments is a checklist.

The framing I took away from this log: debugging a distributed system is a search for the sentence that all the defects violate, and the individual fixes are almost a byproduct. A debugging agent therefore needs four things.

The session failed on all four. The model was a current frontier model. The harness gave it chat, file access and git, and asked it to debug an asynchronous payments pipeline. That is where the four failures come from, and it is our harness.

Explyt covers part of this loop today, and I want to be precise about which part.

Explyt's documented Debug mode exists for the "observe state directly" requirement: for a bug you can reproduce by running a test, an application or an existing IDE run configuration, the agent is asked to confirm the cause under the debugger first, with breakpoints, variable values and the call stack, before it changes any code. Then a minimal fix, then a rerun of the original scenario and the related tests. That is the experiment loop this session never had.

Run configurations close the other gap: the agent runs the build or the test through the IDE and gets back console output, test results and compilation errors as a structured tool result, so it has something to read beyond "compiles and lints". The docs are explicit that a single debugger run confirms the fix only for that scenario and does not replace the related tests.

Nothing in the Explyt documentation reads Kafka topics, runs SQL against your database or pulls logs from Kubernetes on its own. Those sources still enter the session the way they did in this log, through the developer, or through an MCP server you connect yourself; the tools documentation describes MCP as the way to attach browsers, knowledge bases and other external services, and what a given server exposes is up to that server. Explyt's Memory Bank keeps facts and project agreements across chats, which is useful, and it is a different thing from a per-session hypothesis journal. The working theory is still the developer's to keep.

So if this symptom can be reproduced by a test or a run configuration, Debug mode would have changed the middle of the loop: the agent could have seen the actual state at the moment of the write, and rerun the scenario after each fix, with lint no longer the last check. It would not have changed the edges. Someone still has to bring the Kafka and infrastructure evidence, and someone still has to notice that the latest defect rhymes with the first one.

This part is a suggestion for your next session, and nothing here describes what happened in the one above.

Whatever agent you use, put the invariant question into its instructions so it stops being your job to remember it. A repository-level rule along these lines works with most agents that read AGENTS.md or a vendor equivalent:

## Debugging

Keep a written working theory in a file under .tasks/, updated after
every experiment: what is verified (with the command or breakpoint that
verified it), what is assumed, and the current hypothesis.

Before proposing a fix, localize: reproduce the failure under a test or
run configuration and confirm the cause at a breakpoint or in a query
result you ran yourself.

After a fix, rerun the original scenario. "Compiles and lints" is not a result.

After the second defect in the same area, stop and write down what the
two have in common before fixing either.

Then reproduce one failing test in the debugger and make the agent read the variables before it edits anything. If the agent has no debugger, the rule still helps; it just makes the missing instrument visible.

The evidence here is one session log from one developer using our agent, reviewed by me after the fact. I did not run it and I am not publishing its details, defect list or code. Whether the symptom was reproducible under a local test, which is what Debug mode requires, I do not know from the log. Nothing here is a benchmark.

If you already work in a JetBrains IDE, install Explyt from the Marketplace and reproduce one failing test in Debug mode. Ask the agent to confirm the cause at a breakpoint before it edits anything, then make it rerun the scenario after the fix.

When your agent fixed a bug and something else broke, did you go back and ask what the two had in common? I am collecting the invariants people found that way; the comments are open.

── more in #ai-agents 4 stories · sorted by recency
── more on @explyt 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/one-symptom-ten-prob…] indexed:0 read:9min 2026-09-08 ·