<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maheen Shaik</title>
    <description>The latest articles on DEV Community by Maheen Shaik (@maheen_shed88).</description>
    <link>https://dev.to/maheen_shed88</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4235482%2F376000df-7a0b-4ad1-88a7-3e1f7af0a64b.png</url>
      <title>DEV Community: Maheen Shaik</title>
      <link>https://dev.to/maheen_shed88</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maheen_shed88"/>
    <language>en</language>
    <item>
      <title>My On-Call Agent Stopped Suggesting the Fix That Already Failed</title>
      <dc:creator>Maheen Shaik</dc:creator>
      <pubDate>Mon, 09 Nov 2026 16:55:49 +0000</pubDate>
      <link>https://dev.to/maheen_shed88/my-on-call-agent-stopped-suggesting-the-fix-that-already-failed-41bk</link>
      <guid>https://dev.to/maheen_shed88/my-on-call-agent-stopped-suggesting-the-fix-that-already-failed-41bk</guid>
      <description>&lt;p&gt;Hey everyone 👋,&lt;/p&gt;

&lt;p&gt;Remember that time our database pool ran dry, and our AI assistant told us to increase the connection pool? We had already done that months earlier, and it only made things worse: Postgres hit &lt;code&gt;max_connections&lt;/code&gt;, and every service slowed down. The real culprit was a nightly reconciliation job holding connections open.&lt;/p&gt;

&lt;p&gt;The assistant wasn’t being dumb — it just had no memory of what happened before. Every debugging session started from zero, doomed to repeat the same mistakes.&lt;/p&gt;

&lt;p&gt;So I built an on-call agent that remembers, using &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; as its memory layer. Here’s what we built together, what worked for us, and the challenges we hit along the way.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;An engineer pastes an alert into our little UI page. The agent recalls similar past incidents and human corrections, proposes a root cause and a fix, and shows which past memories it relied on. The engineer then marks the answer right or wrong and can log the real cause, the fix that actually worked, and any fix that failed. All of that gets written back into the memory bank.&lt;/p&gt;

&lt;p&gt;The tech stack is intentionally simple: &lt;strong&gt;FastAPI&lt;/strong&gt;, &lt;strong&gt;Groq for the LLM&lt;/strong&gt;, and &lt;strong&gt;Hindsight for agent memory&lt;/strong&gt;. One page of UI, with an obvious &lt;strong&gt;Memory ON/OFF toggle&lt;/strong&gt; so we can compare fairly. &lt;/p&gt;

&lt;p&gt;The loop is deliberately crisp:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recall&lt;/strong&gt; similar incidents and corrections before answering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Answer&lt;/strong&gt;, with recalled memories baked into the prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retain&lt;/strong&gt; the alert and the verdict, then later the human’s feedback.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Recall Before Every Verdict
&lt;/h2&gt;

&lt;p&gt;All the Hindsight calls live in a single file, &lt;code&gt;app/memory.py&lt;/code&gt;. Recall is a one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bank_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bank_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[])][:&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those memories go straight into the prompt, along with a few rules for using them. The rule I care about most:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- If a memory says a fix FAILED or was rejected, never suggest
  that fix again; say why you are avoiding it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Memory is only useful if the model is told what to do with it. Without that instruction, recalled text is just background noise the model might ignore.&lt;/p&gt;




&lt;h2&gt;
  
  
  Retaining Corrections (Not Just Chats)
&lt;/h2&gt;

&lt;p&gt;Early on, my first instinct was to store every alert and every answer. That was a trap: if the agent guesses wrong and you store the guess as fact, you’re teaching it a mistake.&lt;/p&gt;

&lt;p&gt;So we built two kinds of retention. After triage, we store the alert and the verdict — explicitly tagged as &lt;em&gt;not yet confirmed by an engineer&lt;/em&gt;. After feedback, we store the confirmed outcome:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CONFIRMED ROOT CAUSE: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actual_cause&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FIX THAT WORKED: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actual_fix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FIX THAT DID NOT WORK (do not suggest again &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;for this kind of alert): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;failed_fix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feedback goes under its own &lt;code&gt;document_id&lt;/code&gt;, so it never overwrites the triage record. Storing failed fixes as first-class negative constraints turned out to be the most useful decision in our project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before vs. After: A Real Example
&lt;/h2&gt;

&lt;p&gt;Take a connection-pool alert like &lt;code&gt;HikariPool-1 - Connection is not available, request timed out after 30000ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory OFF&lt;/strong&gt; — The answer is the textbook one: "the pool is too small or connections are leaking," so you look at pool settings and raise the maximum. Reasonable, and exactly the advice that failed for us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory ON, after one correction&lt;/strong&gt; — We logged the real cause: a nightly reconciliation cron with no statement timeout. Terminating those sessions fixed it, and raising the pool did not. When a similar alert comes in next time (from a different service, even different wording), the recalled memories surface. It flags the cron as the likely cause and explicitly avoids the pool-size fix.&lt;/p&gt;

&lt;p&gt;Nothing changed except memory — same model, same prompt template, same alert format. Just the ability to remember.&lt;/p&gt;




&lt;h2&gt;
  
  
  Watching the Learning Curve
&lt;/h2&gt;

&lt;p&gt;I wanted to see this as a curve, not just a single example. We built 40 synthetic incidents across 8 recurring failure patterns, each with a root cause specific to our team (the cron job, a feature flag, a retention setting). These specifics matter — if the cause is guessable from the log line alone, a stateless model does well, and memory shows no benefit.&lt;/p&gt;

&lt;p&gt;The demo runs incidents in waves: one per pattern per wave, running each alert twice — once with memory off and once with memory on. After every memory-on run, the "human" confirms the true cause, so Hindsight retains it.&lt;/p&gt;

&lt;p&gt;Our results on 24 incidents (3 waves of 8 patterns):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Wave&lt;/th&gt;
&lt;th&gt;Memory OFF&lt;/th&gt;
&lt;th&gt;Memory ON&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 (cold start)&lt;/td&gt;
&lt;td&gt;0/8&lt;/td&gt;
&lt;td&gt;0/8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0/8&lt;/td&gt;
&lt;td&gt;6/8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0/8&lt;/td&gt;
&lt;td&gt;8/8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Wave 1 scores zero for both because there’s nothing to recall yet. From Wave 2, the memory-enabled agent begins recalling confirmed causes from earlier waves.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Things That Bit Us
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recall quality depends on what you retain.&lt;/strong&gt; Vague memories gave vague recalls. Writing each correction as a self-contained paragraph (alert, cause, fix, failed fix) worked far better than short notes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retain isn’t instant.&lt;/strong&gt; Hindsight extracts facts when you retain, which takes seconds. An async option exists, but then recall might not see the newest memory immediately. In our demo, where we retain and recall back‑to‑back, that matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability code is not optional.&lt;/strong&gt; LLMs sometimes return malformed JSON. We validate output with Pydantic, retry three times, fall back to a second model, and finally return a clearly labeled safe default. Hindsight errors become warnings, so the agent keeps working with empty memory instead of crashing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the memory‑off path honest.&lt;/strong&gt; In memory‑off mode, we skip recall and retain entirely. Otherwise, the baseline quietly learns too, and the comparison loses its integrity.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Honest Limitations
&lt;/h2&gt;

&lt;p&gt;The incidents are synthetic and generated from templates — real incident data would be messier. We scored answers with keyword-overlap against the true root cause, which is a crude proxy, not a real accuracy measure. 24 incidents is a small sample. This shows that the idea works, not that it’s ready to run your pager. A real deployment would need authentication, durable stats, and evaluation on your own incident history.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I’d Tell You If You Build Something Similar
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Store outcomes, not chatter.&lt;/strong&gt; Confirmed causes and failed fixes are worth far more than raw conversation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Label uncertainty.&lt;/strong&gt; Mark unconfirmed guesses as unconfirmed so they never become "facts."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tell the model how to use memory.&lt;/strong&gt; Recall alone does nothing without explicit rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build a memory‑off switch from day one.&lt;/strong&gt; It’s the only honest way to know whether memory helps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use data where the answer is team‑specific.&lt;/strong&gt; That’s where memory truly earns its keep.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The code is on GitHub: &lt;a href="https://github.com/FirdaushAnwer/Memory-Agent" rel="noopener noreferrer"&gt;Memory-Agent&lt;/a&gt;. To try the memory layer yourself, start with the &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight docs&lt;/a&gt; and the &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to Code.in for the free coding credits.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>automation</category>
      <category>debugging</category>
    </item>
  </channel>
</rss>
