<?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: Misbah</title>
    <description>The latest articles on DEV Community by Misbah (@misbah_56d7939d42429a2bc6).</description>
    <link>https://dev.to/misbah_56d7939d42429a2bc6</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%2F4148246%2F946fa8e9-4271-49da-93c4-c862eab3e458.png</url>
      <title>DEV Community: Misbah</title>
      <link>https://dev.to/misbah_56d7939d42429a2bc6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/misbah_56d7939d42429a2bc6"/>
    <language>en</language>
    <item>
      <title>Building ResolveIQ Lite: A Customer Support Agent That Remembers, with Hindsight</title>
      <dc:creator>Misbah</dc:creator>
      <pubDate>Tue, 29 Sep 2026 09:59:25 +0000</pubDate>
      <link>https://dev.to/misbah_56d7939d42429a2bc6/building-resolveiq-lite-a-customer-support-agent-that-remembers-with-hindsight-knm</link>
      <guid>https://dev.to/misbah_56d7939d42429a2bc6/building-resolveiq-lite-a-customer-support-agent-that-remembers-with-hindsight-knm</guid>
      <description>&lt;p&gt;Most support chatbots forget you the moment you close the tab. Report a damaged order today, come back tomorrow, and you're explaining it all over again.&lt;/p&gt;

&lt;p&gt;Our team of five built &lt;strong&gt;ResolveIQ Lite&lt;/strong&gt; to fix that one annoyance. It's a small customer-support agent that remembers each customer's past incidents and uses them in later sessions, with &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; as the memory layer. It's a prototype with fictional customers and orders, but the memory behavior is real.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;A customer reports: &lt;em&gt;"My order A104 arrived damaged. I want a replacement."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Later they write: &lt;em&gt;"I still haven't received my replacement."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Without memory, the agent has no idea which order or replacement this means. With memory, it can connect the message to A104, but it must not invent details like shipping dates or tracking numbers that were never provided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer message
      ↓
Streamlit UI
      ↓
Hindsight recall
      ↓
LLM (Groq) generates reply
      ↓
Hindsight retain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order matters: &lt;strong&gt;recall, then generate, then retain.&lt;/strong&gt; If you store the current message before recalling, the system can treat the current request as old history.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzwsszicoexixd80q89y7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzwsszicoexixd80q89y7.png" alt=" " width="556" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Team and responsibilities
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory layer (Hindsight):&lt;/strong&gt; Shaik Afreen Firdose&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM agent and prompt design:&lt;/strong&gt; Anjali Jakka&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit UI:&lt;/strong&gt; Heena Meheraj&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data and QA:&lt;/strong&gt; Muhammad Shazia&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Repo, Docs &amp;amp; Video Lead]:&lt;/strong&gt; Misbah&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Memory layer: one bank per customer
&lt;/h2&gt;

&lt;p&gt;The key design decision was one Hindsight memory bank per customer instead of one shared bank:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_bank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolveiq-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retain_incident&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&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;retain&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="nf"&gt;_bank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer support interaction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;recall_incidents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&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="nf"&gt;_bank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_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="k"&gt;return&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="n"&gt;text&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="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C101 maps to &lt;code&gt;resolveiq-c101&lt;/code&gt;, C102 to &lt;code&gt;resolveiq-c102&lt;/code&gt;, and so on. Because customers never query the same bank, one customer's history can't leak into another's. Recall failures return an empty list so a missing memory doesn't break the whole support flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcmlb0clzu4qap8greu4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcmlb0clzu4qap8greu4a.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fain2apaziagzbs9utd18.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fain2apaziagzbs9utd18.jpeg" alt=" " width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  LLM layer: memory needs boundaries
&lt;/h2&gt;

&lt;p&gt;The recalled memories go into the prompt under a &lt;strong&gt;PAST HISTORY&lt;/strong&gt; section, kept separate from the current message. The prompt rules tell the agent to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use past history when relevant&lt;/li&gt;
&lt;li&gt;never pretend to remember something that isn't available&lt;/li&gt;
&lt;li&gt;never invent tracking numbers, dates, or policies&lt;/li&gt;
&lt;li&gt;never claim a refund or replacement was completed without evidence&lt;/li&gt;
&lt;li&gt;ask for missing information when needed&lt;/li&gt;
&lt;li&gt;keep replies short, warm, and specific&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One failure shaped the prompt. The agent replied &lt;em&gt;"Thank you for confirming it's order A104"&lt;/em&gt;, but the customer had never confirmed anything. The model had retrieved A104 from memory and then treated it as something the customer just said. Retrieval wasn't the issue; the prompt needed clear rules separating what is known, what is remembered, and what the customer actually confirmed.&lt;/p&gt;

&lt;p&gt;We also added model fallback: the agent tries the configured models in sequence, and &lt;code&gt;&amp;lt;think&amp;gt;...&amp;lt;/think&amp;gt;&lt;/code&gt; sections are stripped before the reply reaches the customer.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI: making memory visible
&lt;/h2&gt;

&lt;p&gt;The Streamlit app has a sidebar with a customer selector, a Hindsight memory ON/OFF toggle, and a "Start new session" button. The main area shows three panels: the &lt;strong&gt;current query&lt;/strong&gt;, the &lt;strong&gt;generated response&lt;/strong&gt;, and the &lt;strong&gt;recalled memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Showing recalled memory in its own panel turned out to be the most useful design choice. It makes clear &lt;em&gt;why&lt;/em&gt; the agent answered the way it did.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkuodearwl0ta3kkusazm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkuodearwl0ta3kkusazm.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Before and after, same message
&lt;/h2&gt;

&lt;p&gt;We sent &lt;em&gt;"I still haven't received my replacement."&lt;/em&gt; with memory off and on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory OFF:&lt;/strong&gt; the agent asks generically for the order number and item details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F87l9ixqdiu4qf0u4b738.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F87l9ixqdiu4qf0u4b738.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory ON:&lt;/strong&gt; the recalled-memory panel shows facts Hindsight synthesized, such as the customer's order A104 arriving damaged and the replacement not yet received. The reply builds on that history instead of starting cold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsbn8o0735ryzo0vuox1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsbn8o0735ryzo0vuox1b.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;We seeded fictional customers (C101 to C106), orders, and past incidents, then ran five scenarios: initial complaint, recall in a new session, cross-customer isolation, a new customer with no history, and an ambiguous follow-up like "Any update?"&lt;/p&gt;

&lt;p&gt;The most important one was isolation. C102 sent the same message as C101, and Hindsight returned an empty list for C102. The agent asked for the order ID instead of mentioning A104.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Customer&lt;/th&gt;
&lt;th&gt;Expected&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Report damaged order A104&lt;/td&gt;
&lt;td&gt;C101&lt;/td&gt;
&lt;td&gt;Log incident&lt;/td&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Still haven't received replacement"&lt;/td&gt;
&lt;td&gt;C101&lt;/td&gt;
&lt;td&gt;Recall A104&lt;/td&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same message&lt;/td&gt;
&lt;td&gt;C102&lt;/td&gt;
&lt;td&gt;No memories returned&lt;/td&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Where is my order?"&lt;/td&gt;
&lt;td&gt;C106&lt;/td&gt;
&lt;td&gt;Ask for order ID, no invention&lt;/td&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Any update?"&lt;/td&gt;
&lt;td&gt;C101&lt;/td&gt;
&lt;td&gt;Link to pending replacement&lt;/td&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmemxjta0wj2ag2gvs2q1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmemxjta0wj2ag2gvs2q1.jpeg" alt=" " width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcsrop6nzamqdo7dzl7b4.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcsrop6nzamqdo7dzl7b4.jpeg" alt=" " width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftcdso68h5lhff95yv2v5.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftcdso68h5lhff95yv2v5.jpeg" alt=" " width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems we hit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configuration:&lt;/strong&gt; the Hindsight base URL and environment variables (&lt;code&gt;HINDSIGHT_BASE_URL&lt;/code&gt;, &lt;code&gt;HINDSIGHT_API_KEY&lt;/code&gt;, &lt;code&gt;GROQ_API_KEY&lt;/code&gt;) were initially wrong or empty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;402 Payment Required:&lt;/strong&gt; memory operations stopped until account credits were available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;404 on missing banks:&lt;/strong&gt; recalling a bank that doesn't exist yet throws an error, so we handle it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interface mismatch:&lt;/strong&gt; the UI's stand-in &lt;code&gt;retain_incident()&lt;/code&gt; had a different signature from the real one in &lt;code&gt;memory.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Silent failures:&lt;/strong&gt; a generic "please try again" message briefly hid a real model error. Log the actual exception.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval ranking:&lt;/strong&gt; in one run, the reply still asked the customer to confirm the order number even though A104 was in their history. Hindsight recalled several memories, but the one naming A104 didn't rank first. That's a retrieval-tuning problem worth exploring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Indexing delay:&lt;/strong&gt; in early tests, recalling within a few seconds of a retain occasionally returned nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Very short queries&lt;/strong&gt; like "Status?" retrieved less reliably than queries with a bit of context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synthetic data:&lt;/strong&gt; everything is fictional and pre-seeded. A real system would need integrations with platforms like Shopify or Zendesk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Memory needs boundaries. More context doesn't automatically mean more accuracy.&lt;/li&gt;
&lt;li&gt;Isolate memory by key from day one.&lt;/li&gt;
&lt;li&gt;Always test with and without memory using the identical input.&lt;/li&gt;
&lt;li&gt;Test failure cases: missing tracking numbers, dates, and policies reveal invention fast.&lt;/li&gt;
&lt;li&gt;Prompt engineering is part of system design, because it defines what the agent can claim.&lt;/li&gt;
&lt;li&gt;Make recall visible in the UI so people can see why the agent answered as it did.&lt;/li&gt;
&lt;li&gt;Coordinating five people on one integration was harder than the code. Small, frequent commits helped.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hindsight GitHub: &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;https://github.com/vectorize-io/hindsight&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hindsight platform: &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;https://hindsight.vectorize.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;What is agent memory: &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;https://vectorize.io/what-is-agent-memory&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Project repo: [&lt;a href="https://github.com/misbah318/resolveiq-lite" rel="noopener noreferrer"&gt;https://github.com/misbah318/resolveiq-lite&lt;/a&gt;]&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>machinelearning</category>
      <category>llm</category>
    </item>
    <item>
      <title>How Hindsight Turned My Chatbot Into an Agent That Remembers</title>
      <dc:creator>Misbah</dc:creator>
      <pubDate>Tue, 29 Sep 2026 01:26:23 +0000</pubDate>
      <link>https://dev.to/misbah_56d7939d42429a2bc6/how-hindsight-turned-my-chatbot-into-an-agent-that-remembers-22od</link>
      <guid>https://dev.to/misbah_56d7939d42429a2bc6/how-hindsight-turned-my-chatbot-into-an-agent-that-remembers-22od</guid>
      <description>&lt;h1&gt;
  
  
  What Happens When Your Support Agent Finally Remembers You
&lt;/h1&gt;

&lt;p&gt;Every support chatbot I'd used before had the same problem: it forgot me the second I closed the tab. Tell it about a damaged order today, come back tomorrow, and you're explaining it from scratch again. So my team of five set out to fix that one specific annoyance, using &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; as the memory layer.&lt;/p&gt;

&lt;p&gt;We built ResolveIQ Lite, a small customer-support agent that remembers a customer's past incidents and uses them the next time that customer writes in, even in a brand-new session. It's a prototype with fictional customers and orders, not a real support system, but the memory behavior is real.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem in one sentence
&lt;/h2&gt;

&lt;p&gt;A support agent without memory treats every message as the first message. Ask it "I still haven't received my replacement" with no context, and it has nothing to work with. That's the gap we wanted to close.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's wired together
&lt;/h2&gt;

&lt;p&gt;The flow is short on purpose:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The customer types a message in a Streamlit screen.&lt;/li&gt;
&lt;li&gt;We recall that customer's history from &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;An LLM (via Groq) writes a reply using the current message plus whatever was recalled.&lt;/li&gt;
&lt;li&gt;We retain the new exchange back into Hindsight.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_bank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolveiq-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retain_incident&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&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;retain&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="nf"&gt;_bank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer support interaction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;recall_incidents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&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="nf"&gt;_bank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_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="k"&gt;return&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="n"&gt;text&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="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The one design decision I'd point to is the bank naming: one Hindsight memory bank per customer (&lt;code&gt;resolveiq-c101&lt;/code&gt;, &lt;code&gt;resolveiq-c102&lt;/code&gt;, and so on). It's a small line of code, but it's what guarantees customer isolation — C102 can never see C101's damaged order, because they're not even querying the same bank.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that made memory feel real
&lt;/h2&gt;

&lt;p&gt;The moment that convinced me this wasn't just a chat log was the recalled-memory panel. It doesn't show the raw conversation history — it shows what Hindsight actually surfaced as relevant:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The customer has not received their replacement item. | When: 2026-09-28 | Involving: customer"&lt;/p&gt;

&lt;p&gt;"Customer's order A104 arrived damaged, they requested a replacement, and as of September 28, 2026, they have not yet received it."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are synthesized facts, not copy-pasted messages. That's the difference between memory and a transcript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before and after, same message
&lt;/h2&gt;

&lt;p&gt;We sent the exact same line, "I still haven't received my replacement," with memory off and memory on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory OFF:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff906wzqk4qyhm4tu79ew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff906wzqk4qyhm4tu79ew.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory ON:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F92yje35g6xx4measp941.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F92yje35g6xx4measp941.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I see you're still waiting for the replacement item you mentioned on 2026-09-28. Could you please confirm the order number and the shipping address it should go to? I'll pass this information to our support team for review, and they'll follow up with the next steps."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The second reply references a real date from the customer's own history instead of starting cold. That's &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;agent memory&lt;/a&gt; doing its job.&lt;/p&gt;

&lt;h2&gt;
  
  
  What surprised me
&lt;/h2&gt;

&lt;p&gt;Honestly, less than I expected. The core loop — recall, generate, retain — worked close to how we designed it on paper. If anything, that was the surprising part: memory retrieval that "just works" from a documented API is not something I'd experienced before this project.&lt;/p&gt;

&lt;h2&gt;
  
  
  An honest limitation
&lt;/h2&gt;

&lt;p&gt;The reply above still asks the customer to "confirm the order number," even though an earlier message in the same customer's history mentions order A104 by name. Hindsight recalled several memory lines, but the most specific one (the one naming A104) didn't rank first for this particular query. It's not a failure of memory, it's a retrieval-tuning problem: worth exploring further, and worth admitting rather than papering over. For a prototype with fictional data and a small seeded history, it's a reasonable rough edge, not a dealbreaker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons I'd pass on
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Isolate memory by key early.&lt;/strong&gt; Deciding "one bank per customer" on day one saved us from ever worrying about data leaking between customers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Show, don't just build, the recall.&lt;/strong&gt; Putting "recalled memory" in its own visible panel made the value of memory obvious to anyone watching the demo, not just to us.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coordinating five people on one Hindsight instance was the actual hard part.&lt;/strong&gt; Not the code — waiting on teammates to push their piece before you could test yours. Small, frequent commits made this bearable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A generic fallback message can hide a real bug.&lt;/strong&gt; Ours briefly failed silently behind a "please try again" message before we found the underlying model issue. Log the real error, always.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory only feels valuable when the "before" is genuinely broken.&lt;/strong&gt; The clearest way to prove memory matters is a clean before/after with the identical input.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're building anything where a user comes back more than once, plain chat history isn't enough. Structured, queryable memory is a different thing, and it changes what the agent is capable of saying.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
