<?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: Shivani Mallam</title>
    <description>The latest articles on DEV Community by Shivani Mallam (@shivani_mallam_4c4a21c4cc).</description>
    <link>https://dev.to/shivani_mallam_4c4a21c4cc</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%2F4150822%2F2e3a2761-1a8c-4d66-bcdb-2a189e2caf88.png</url>
      <title>DEV Community: Shivani Mallam</title>
      <link>https://dev.to/shivani_mallam_4c4a21c4cc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shivani_mallam_4c4a21c4cc"/>
    <language>en</language>
    <item>
      <title>How I Gave a Support Agent Memory With Hindsight</title>
      <dc:creator>Shivani Mallam</dc:creator>
      <pubDate>Tue, 29 Sep 2026 18:34:41 +0000</pubDate>
      <link>https://dev.to/shivani_mallam_4c4a21c4cc/how-i-gave-a-support-agent-memory-with-hindsight-4d4h</link>
      <guid>https://dev.to/shivani_mallam_4c4a21c4cc/how-i-gave-a-support-agent-memory-with-hindsight-4d4h</guid>
      <description>&lt;p&gt;Most customer-support agents remember the conversation until the conversation ends. I wanted mine to remember what happened before—and, more importantly, remember which fixes had already failed.&lt;/p&gt;

&lt;p&gt;That idea led me to build MemorySupport AI, a customer-support agent that uses Hindsight for persistent memory.&lt;/p&gt;

&lt;p&gt;The goal was not simply to generate better responses. I wanted to explore what changes when an AI agent can retrieve relevant customer history and use it during a later interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Wasn't Just Generating Better Answers
&lt;/h2&gt;

&lt;p&gt;A support agent can give a reasonable answer to a customer's current message while still missing important context from previous interactions.&lt;/p&gt;

&lt;p&gt;For example, imagine a customer reports that PDF uploads crash the application. Support suggests clearing the application cache, but the problem continues.&lt;/p&gt;

&lt;p&gt;If the customer contacts support again later, a stateless agent may suggest clearing the cache again.&lt;/p&gt;

&lt;p&gt;From the customer's perspective, that is frustrating because they already tried it.&lt;/p&gt;

&lt;p&gt;The problem is therefore not only response generation. It is also memory.&lt;/p&gt;

&lt;p&gt;I wanted MemorySupport AI to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Previous customer issues&lt;/li&gt;
&lt;li&gt;Important customer information&lt;/li&gt;
&lt;li&gt;Troubleshooting steps that were already attempted&lt;/li&gt;
&lt;li&gt;Which troubleshooting steps failed&lt;/li&gt;
&lt;li&gt;Unresolved issues&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;MemorySupport AI is a Python and Streamlit application with three main components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Streamlit provides the user interface.&lt;/li&gt;
&lt;li&gt;Groq provides the language model.&lt;/li&gt;
&lt;li&gt;Hindsight provides persistent long-term memory.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The basic flow is:&lt;/p&gt;

&lt;p&gt;Customer message → Hindsight recall → Relevant memory → Language model → Response → Hindsight retain&lt;/p&gt;

&lt;p&gt;I also use Hindsight's reflect capability to generate a concise summary of the customer's support history.&lt;/p&gt;

&lt;p&gt;[SCREENSHOT 1: Main MemorySupport AI application]&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MemorySupport AI — the Streamlit interface for context-aware customer support.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hindsight Integration
&lt;/h2&gt;

&lt;p&gt;The most important part of the project is the memory layer.&lt;/p&gt;

&lt;p&gt;For the demo, I seed a customer's previous support history into Hindsight.&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="c1"&gt;# My AI agent remembered my mistake — so I didn't have to make it twice
&lt;/span&gt;
&lt;span class="n"&gt;Most&lt;/span&gt; &lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="n"&gt;agents&lt;/span&gt; &lt;span class="n"&gt;treat&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;black&lt;/span&gt; &lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;You&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="n"&gt;happens&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;scenes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;When&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;wrong&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;idea&lt;/span&gt; &lt;span class="n"&gt;whether&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;hallucinated&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;wrong&lt;/span&gt; &lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;simply&lt;/span&gt; &lt;span class="n"&gt;ignored&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;was&lt;/span&gt; &lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;wanted&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;opposite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;When&lt;/span&gt; &lt;span class="n"&gt;MemorySupport&lt;/span&gt; &lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;see&lt;/span&gt; &lt;span class="n"&gt;exactly&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt; &lt;span class="nb"&gt;long&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="n"&gt;facts&lt;/span&gt; &lt;span class="n"&gt;Hindsight&lt;/span&gt; &lt;span class="n"&gt;returned&lt;/span&gt; &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;language&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;ever&lt;/span&gt; &lt;span class="n"&gt;ran&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;That&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="n"&gt;requirement&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="n"&gt;how&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;designed&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;whole&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="c1"&gt;## What the system actually does
&lt;/span&gt;
&lt;span class="n"&gt;MemorySupport&lt;/span&gt; &lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Streamlit&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;triggers&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Hindsight&lt;/span&gt; &lt;span class="sb"&gt;`recall`&lt;/span&gt; &lt;span class="n"&gt;pulls&lt;/span&gt; &lt;span class="n"&gt;relevant&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Groq&lt;/span&gt; &lt;span class="n"&gt;generates&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="n"&gt;plus&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;recalled&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;plus&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;chat&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Hindsight&lt;/span&gt; &lt;span class="sb"&gt;`retain`&lt;/span&gt; &lt;span class="n"&gt;stores&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;There&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;also&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="sb"&gt;`reflect`&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;synthesizes&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;short&lt;/span&gt; &lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="n"&gt;briefing&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;everything&lt;/span&gt; &lt;span class="n"&gt;stored&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;UI&lt;/span&gt; &lt;span class="n"&gt;exposes&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;live&lt;/span&gt; &lt;span class="n"&gt;conversation&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;dedicated&lt;/span&gt; &lt;span class="n"&gt;panel&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;lists&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;memories&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;were&lt;/span&gt; &lt;span class="n"&gt;retrieved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;deliberately&lt;/span&gt; &lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Streamlit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Hindsight&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vectorize&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hindsight&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;persistent&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;Groq&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Nothing&lt;/span&gt; &lt;span class="n"&gt;exotic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;interesting&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;how&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;treated&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;inspectable&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt; &lt;span class="n"&gt;rather&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;invisible&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="c1"&gt;## The design decision that mattered
&lt;/span&gt;
&lt;span class="n"&gt;Early&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;almost&lt;/span&gt; &lt;span class="n"&gt;did&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;usual&lt;/span&gt; &lt;span class="n"&gt;thing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;concatenate&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;That&lt;/span&gt; &lt;span class="n"&gt;would&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;been&lt;/span&gt; &lt;span class="n"&gt;faster&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="n"&gt;also&lt;/span&gt; &lt;span class="n"&gt;would&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;made&lt;/span&gt; &lt;span class="n"&gt;debugging&lt;/span&gt; &lt;span class="n"&gt;almost&lt;/span&gt; &lt;span class="n"&gt;impossible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Support&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;noisy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Names&lt;/span&gt; &lt;span class="n"&gt;conflict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="n"&gt;gets&lt;/span&gt; &lt;span class="n"&gt;retained&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="n"&gt;once&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;An&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;looked&lt;/span&gt; &lt;span class="n"&gt;useful&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;irrelevant&lt;/span&gt; &lt;span class="n"&gt;later&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="n"&gt;tell&lt;/span&gt; &lt;span class="n"&gt;whether&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ignoring&lt;/span&gt; &lt;span class="n"&gt;good&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inventing&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;correctly&lt;/span&gt; &lt;span class="n"&gt;declining&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;conflicting&lt;/span&gt; &lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;So&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;made&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;recalled&lt;/span&gt; &lt;span class="n"&gt;memories&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;part&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;every&lt;/span&gt; &lt;span class="nf"&gt;turn &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;demand&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;refresh&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="n"&gt;shows&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;What&lt;/span&gt; &lt;span class="n"&gt;Hindsight&lt;/span&gt; &lt;span class="n"&gt;Recalled&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="n"&gt;section&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;Hindsight&lt;/span&gt; &lt;span class="n"&gt;returned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deduplicated&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;labeled&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
unique_memories = []&lt;br&gt;
seen = set()&lt;/p&gt;

&lt;p&gt;for memory in memories.results:&lt;br&gt;
    mem_text = getattr(memory, "text", str(memory))&lt;br&gt;
    mem_type = getattr(memory, "type", "memory")&lt;br&gt;
    key = (mem_type, mem_text.strip())&lt;br&gt;
    if key not in seen:&lt;br&gt;
        seen.add(key)&lt;br&gt;
        unique_memories.append((mem_type, mem_text.strip()))&lt;/p&gt;

&lt;p&gt;for index, (mem_type, mem_text) in enumerate(unique_memories[:8], start=1):&lt;br&gt;
    st.markdown(f"&lt;strong&gt;{index}. [{mem_type}]&lt;/strong&gt; {mem_text}")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
That panel is not a nice-to-have. It is the main reason I trust the rest of the pipeline. When the agent correctly skips a failed troubleshooting step, I can see that the failed step was present in the recall. When the agent avoids using a name, I can see that the name memories conflicted. The model is no longer a mystery box.

## How recall is wired

On every customer message the app builds a query that includes the customer ID and the current prompt, then asks Hindsight for a mid-budget recall:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
recall_result = hindsight.recall(&lt;br&gt;
    bank_id=BANK_ID,&lt;br&gt;
    query=f"Customer {customer_id}: {prompt}",&lt;br&gt;
    max_tokens=3500,&lt;br&gt;
    budget="mid",&lt;br&gt;
)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The results are turned into a short bullet list and injected as a second system message, separate from the behavioral instructions:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
response_messages = [&lt;br&gt;
    {"role": "system", "content": SYSTEM_PROMPT},&lt;br&gt;
    {&lt;br&gt;
        "role": "system",&lt;br&gt;
        "content": (&lt;br&gt;
            "RELEVANT LONG-TERM MEMORY FROM HINDSIGHT:\n"&lt;br&gt;
            + recall_text&lt;br&gt;
            + "\n\nCURRENT CUSTOMER ID: "&lt;br&gt;
            + customer_id&lt;br&gt;
        ),&lt;br&gt;
    },&lt;br&gt;
] + recent_history&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Keeping memory in its own system message made the boundary explicit. The model is told, in plain language, that this block is long-term context from Hindsight and that it must not invent history when the block is empty or contradictory.

## The system prompt is the real policy layer

Memory retrieval alone does not change behavior. You still need rules for what the agent is allowed to do with what it retrieves. The system prompt is where those rules live:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
text&lt;br&gt;
You have access to long-term customer memory supplied below.&lt;br&gt;
Use remembered facts when they are relevant to the customer's current request.&lt;br&gt;
Never invent customer history.&lt;br&gt;
If memories conflict, do not guess which one is correct.&lt;br&gt;
...&lt;br&gt;
Do not ask the customer to repeat information that is already available in memory.&lt;br&gt;
Avoid repeating troubleshooting steps that memory shows have already failed.&lt;br&gt;
...&lt;br&gt;
If the customer's name is conflicting or unclear, do not use a name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Those constraints matter more than the retrieval quality. Without them, a model will happily invent a consistent story from sparse or conflicting memories. With them, the agent is allowed to say “I do not have a reliable name for you” or to skip a step it knows already failed.

I learned this the hard way. Early test runs produced confident-sounding replies that used a name I had never stored cleanly, or that suggested clearing the cache again even when the failed attempt was sitting in the recall. The fix was not better embeddings. It was stricter instructions and the visible memory panel so I could catch the failures.

## Seeding history and closing the loop

For demos I seed a small, deliberate customer history so the first recall is not empty:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
demo_memories = [&lt;br&gt;
    f"Customer {customer_id} is named {customer_name}.",&lt;br&gt;
    f"Customer {customer_id} uses Windows 11 and Chrome for work.",&lt;br&gt;
    f"Customer {customer_id} previously reported that PDF uploads caused the application to crash.",&lt;br&gt;
    f"For customer {customer_id}, clearing the application cache was tried previously and did not permanently solve the PDF upload crash.",&lt;br&gt;
    f"Customer {customer_id} prefers step-by-step troubleshooting instructions.",&lt;br&gt;
    f"Customer {customer_id} had a previous high-priority support ticket TKT-1042 about PDF upload crashes; the issue remained unresolved after cache clearing.",&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;for memory in demo_memories:&lt;br&gt;
    hindsight.retain(&lt;br&gt;
        bank_id=BANK_ID,&lt;br&gt;
        content=memory,&lt;br&gt;
        context="Customer support history",&lt;br&gt;
        metadata={"customer_id": customer_id, "source": "demo_seed"},&lt;br&gt;
    )&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
After every live turn the interaction is retained as well:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
interaction = (&lt;br&gt;
    f"Customer {customer_id} support interaction at "&lt;br&gt;
    f"{datetime.now(timezone.utc).isoformat()}.\n"&lt;br&gt;
    f"Customer message: {prompt}\n"&lt;br&gt;
    f"Assistant response: {answer}"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;hindsight.retain(&lt;br&gt;
    bank_id=BANK_ID,&lt;br&gt;
    content=interaction,&lt;br&gt;
    context="Customer support conversation",&lt;br&gt;
    metadata={"customer_id": customer_id, "source": "live_chat"},&lt;br&gt;
)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The loop is intentionally simple: recall → respond → retain. There is no sophisticated conflict resolution yet. That is a deliberate trade-off. I wanted a working, inspectable memory path first. Cleanup and ranking can come later once I can see what is actually being stored and retrieved.

## Reflect as a support briefing, not a chat feature

Hindsight’s `reflect` operation is used for a different purpose. Instead of feeding the conversation, it produces a concise briefing that a human (or another agent) could read before picking up a ticket:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
summary = hindsight.reflect(&lt;br&gt;
    bank_id=BANK_ID,&lt;br&gt;
    query=(&lt;br&gt;
        f"Summarize the most important support history, environment, "&lt;br&gt;
        f"preferences, failed troubleshooting steps, and unresolved issues "&lt;br&gt;
        f"for customer {customer_id}."&lt;br&gt;
    ),&lt;br&gt;
    context="Prepare a concise support-agent briefing.",&lt;br&gt;
    budget="mid",&lt;br&gt;
)&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


This is useful precisely because it is not the same as recall. Recall answers “what is relevant to this message?” Reflect answers “what should a support agent know about this customer right now?” Keeping those two operations separate made the architecture clearer.

## What actually changed in the conversation

The concrete test case is a returning customer whose PDF upload still crashes.

Without memory the agent asks for the OS again and suggests clearing the cache. With Hindsight in the loop the recall contains Windows 11, Chrome, the previous crash, the failed cache clear, and the preference for numbered steps. The reply acknowledges the earlier attempt and moves on. You can open the memory panel and confirm that those facts were present before the model wrote a single word.

That is the whole product difference. The agent stops treating every conversation as a fresh start because the relevant past is available, labeled, and visible.

## What I would not do again

I would not hide the memory layer. The cost of showing a few bullets is tiny. The cost of debugging a silent retrieval failure is high.

I would also not treat every retained string as ground truth. Duplicates and name conflicts appeared quickly. The system prompt already refuses to guess when memories conflict; a production version needs stronger validation and deduplication on the write path as well.

Finally, I would not collapse recall and reflect into one call. They answer different questions. Mixing them muddies both the UI and the mental model.

## Practical takeaways

- Make retrieved memory visible. If you cannot inspect it, you cannot trust or improve it.
- Keep behavioral policy in the system prompt and facts in a separate context block. Blurring the two invites invention.
- Prefer relevant retrieval over dumping the entire history. A mid-budget recall with a customer-scoped query is enough to change behavior without flooding the context.
- Failed troubleshooting steps are high-value memory. Knowing what did not work prevents the most annoying form of repetition.
- Use `reflect` for synthesis and briefings, not as a substitute for per-turn recall.
- Assume memory will be messy. Design the agent to refuse to invent rather than to force a consistent story.

MemorySupport AI is still a focused system: one bank, one customer ID at a time, a Streamlit UI, and three Hindsight operations. The useful lesson is not the stack. It is the decision to treat memory as an inspectable input instead of an invisible optimization. Once you can see what the agent remembered, you can start to care whether it remembered the right things.

## Resources

- Project repository: https://github.com/shivanimallam1234-cloud/memorysupport-ai
- [Hindsight on GitHub](https://github.com/vectorize-io/hindsight)
- [Hindsight documentation](https://hindsight.vectorize.io/)
- [What is agent memory?](https://vectorize.io/what-is-agent-memory)
![ ](https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/j3xb2orhkixc3p6vw9nj.png)
![ ](https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/tvlku85nvwi1r4bbq4l9.png)
![ ](https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/gsz1zfht9sivzt9xlswc.png)
![ ](https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/rwk7amn6n3afyit6v50w.png)
![ ](https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/3bdle8sxtg9jhtuleyoc.png)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>llm</category>
      <category>streamlit</category>
    </item>
  </channel>
</rss>
