My On-Call Agent Stopped Suggesting the Fix That Failed
The last time our production database ran out of connections, an AI assistant gave me the exact advice you would find in any standard system design textbook: increase the connection pool size. On paper, that sounds compl
The last time our production database ran out of connections, an AI assistant gave me the exact advice you would find in any standard system design textbook: increase the connection pool size.
On paper, that sounds completely reasonable. In reality, we had tried that exact configuration change a few months earlier, and it turned a minor bottleneck into a full-blown outage. Raising the pool ceiling at the application layer caused our services to slam directly into the database's hard connection limit, throttling queries across the entire stack and slowing every downstream microservice to a crawl. The actual root cause had nothing to do with pool sizing—it was a rogue nightly reconciliation job holding connections open indefinitely because it lacked an explicit timeout.
The AI assistant wasn't broken, and its reasoning wasn't flawed in a vacuum. Raising the pool limit is textbook advice. However, it was dangerously wrong for our architecture, and the assistant had no way of knowing that because every single conversation with a standard LLM starts from zero.
Closing that operational amnesia is the exact problem I set out to solve.
The Problem With Stateless AI Assistants
During a live production incident, the most valuable debugging context is almost never sitting neatly in your official documentation. It lives in the scars your engineering team earned the hard way:
- The textbook fix that backfires: A configuration tweak that looks right in theory but triggers cascading latency under your specific traffic patterns.
- The recurring phantom load: A month-end cron job or batch script that silently starves worker nodes of memory at the exact same hour every thirty days.
- The unwritten deployment dependency: A feature flag that will break authentication if toggled on before a specific downstream service finishes rolling out. In most organisations, that tribal knowledge is scattered across closed Jira tickets, buried Slack threads, postmortem docs nobody re-reads, and the memory of one senior engineer who happened to be on shift six months ago. Because a generic AI assistant has zero access to this operational history, it defaults to giving plausible, confident, textbook answers—including the exact fixes your team has already tested, rolled back, and rejected. What I Built: An On-Call Agent With Persistent Memory To move beyond stateless prompting, I built an on-call diagnostic agent backed by a persistent memory layer using Hindsight (https://github.com/vectorize-io/hindsight). The system is architected with FastAPI handling the backend orchestration, Groq providing ultra-low-latency LLM inference (crucial when you are debugging under pager pressure), and Hindsight managing long-term agent memory (https://vectorize.io/what-is-agent-memory). The operational loop follows five strict steps:
- Alert Ingestion: An on-call engineer pastes a raw incoming alert or error trace into the interface.
- Contextual Recall: Before generating a single token of advice, the agent queries Hindsight to recall similar historical incidents, architectural quirks, and past human corrections.
- Evidence-Backed Diagnosis: The agent proposes a root cause and a remediation plan, explicitly surfacing which historical memories it relied on to reach that conclusion.
- Human-in-the-Loop Verification: Once the incident is resolved, the engineer marks the agent's hypothesis as right or wrong and logs three structured pieces of data: the verified root cause, the fix that actually worked, and any attempted fix that failed.
- Memory Consolidation: Every verified outcome is written back into the memory layer so the system starts the next shift smarter than the last. The Architectural Decision That Mattered Most When I started designing the schema for this agent, I assumed the highest-leverage data to store would be the fixes that worked. I was completely wrong. The single biggest unlock was remembering the fixes that failed. In incident response, ruling out a destructive path is often more valuable than guessing the right one on the first try. Once "raising the database connection pool size failed here and caused connection exhaustion" is committed to memory as a verified fact—paired with a strict system instruction never to recommend a known failed action without explicitly warning the engineer why it failed previously—the agent stops walking into the same trap twice. What Changed: Stateless vs. Stateful Performance The difference in behaviour is immediate when you toggle the memory layer off and on:
- With Memory Off: The agent behaves like any off-the-shelf chatbot. It reads the connection exhaustion alert and tells you to inspect your pool settings and raise the maximum connection limit.
- With Memory On: After logging a single correction from the first outage, a later alert triggered by a completely different microservice—even with different log wording—retrieves the earlier incident. The agent immediately flags the nightly reconciliation job as the prime suspect and steers clear of the connection pool setting. It runs on the exact same language model, the exact same base prompt, and the same class of alert. The only variable is persistent memory. To test this systematically, I evaluated the agent across 24 synthetic incidents spanning 8 recurring failure categories:
- Pass 1 (Cold Start / Zero History): The agent matched 0 out of 8 root causes, which is expected when the system has no prior context on team-specific failure modes.
- Pass 2 (After 1 Round of Corrections): Accuracy jumped to 6 out of 8 matched failure types.
- Pass 3 (After 2 Rounds of Corrections): The agent successfully matched all 8 out of 8 recurring incident patterns.
- Control Group (Stateless / Memory Disabled): Remained stuck at 0 out of 8 across every single pass. An honest engineering caveat: These 24 scenarios were synthetic, and I evaluated the responses using a straightforward keyword-overlap check. That is a rough proxy metric rather than a deep semantic evaluation, and 24 incidents is a small sample size. This benchmark proves that the feedback loop works conceptually—it does not mean the codebase is ready to take over your production pager tomorrow. A real production rollout requires strict role-based authentication, durable storage guarantees, and rigorous benchmarking against your own messy, real-world incident logs. 5 Lessons for Teams Building With Agent Memory If you are experimenting with stateful agents for DevOps, SRE, or internal tooling, here is what I learned the hard way:
- Store verified outcomes, not raw chatter. Confirmed root causes and failed fixes are high-density signal. Dumping raw, unedited debugging chat logs into vector storage just pollutes retrieval with noise.
- Enforce strict epistemic labels. Unconfirmed hypotheses and mid-outage guesses must never be saved into long-term memory as established facts.
- Explicitly instruct the model on how to use recalled memory. Retrieving context into the prompt achieves nothing unless your system instructions dictate how past failures should constrain future recommendations.
- Build a memory on/off kill switch from Day 1. Running side-by-side comparisons with memory disabled is the only honest way to verify that your memory layer is actually improving accuracy.
- Target problems where the answer is unique to your stack. Stateless LLMs already know generic textbook patterns. Agent memory earns its keep where the right answer depends on your team's specific architecture and history. When your team closes a tough incident today, do those hard-won lessons actually get reused by your tooling—or do they end up buried in a postmortem document nobody ever reads again? Links & Resources:
- Full Technical Write-Up & Code Breakdown: [Insert your blog/article link here]
- GitHub Repository: [Insert your GitHub repo link here]
- Hindsight Documentation: https://hindsight.vectorize.io/ Special thanks to Code.in for providing the free coding credits to build and test this project. #AIEngineering #SoftwareEngineering #SiteReliabilityEngineering #DevOps #LLMs #SystemDesign #FastAPI #AgenticAI
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.