My AI Support Agent Kept Forgetting Customers — Hindsight Fixed That
The first version of my customer support agent had a simple but frustrating problem: every new conversation felt like starting from zero.
A customer could explain an issue, come back later, and the agent would have no useful context about what happened before. The customer had to repeat themselves.
I wanted to solve that with long-term memory, so I built MemorySupport, a small AI customer support agent using Hindsight as its memory layer.
The goal was simple:
Let the support agent remember what a customer had already told it.
The Problem: Every Conversation Started From Zero
A normal chat-based support flow can look like this:
Customer → Message → AI → Response
The problem appears when the customer returns later.
For example:
Customer:
"My laptop keyboard is not working properly."
AI:
"Please try restarting your laptop..."
Later:
Customer:
"The keyboard issue is still happening."
Without memory, that second message doesn't contain enough information by itself.
The agent may not know:
- What device the customer was talking about
- What the original problem was
- Whether troubleshooting was already attempted
- Whether this is a continuing issue
That is where I wanted memory to become part of the architecture rather than just adding previous chat messages into a prompt.
Building MemorySupport
I kept the first version intentionally small.
The application has:
- A customer name field
- A support message field
- A Hindsight memory bank for each customer
- Memory retrieval
- Memory storage
- A simple support response
The basic architecture is:
Customer
|
v
Streamlit UI
|
+------+------+
| |
v v
Hindsight New Message
Recall |
| |
v |
Previous Memory |
| |
+------+-------+
|
v
Support Response
|
v
Hindsight Retain
The important part is that Hindsight sits between the conversation and the application's long-term memory.
I used the Hindsight documentation to work with memory retention and recall.
Giving Each Customer Their Own Memory
The first design decision was figuring out how to separate customers.
For the prototype, I created a memory bank based on the customer's name:
bank_id = (
"customer-"
+ customer.strip().lower().replace(" ", "-")
)
So if the customer is Madhuri, the memory bank becomes:
customer-madhuri
This means conversations don't all get mixed into one memory space.
For a production application, I would use a permanent customer ID from the authentication or customer database instead of a name.
Using Hindsight to Remember
The two operations that became central to my implementation were recall and retain.
First, I retrieve information relevant to the customer's current message:
memories = client.recall(
bank_id=bank_id,
query=message
)
Then I store the new interaction:
client.retain(
bank_id=bank_id,
content=f"Customer {customer} said: {message}",
context="Customer support conversation"
)
I think of these as two different jobs.
Recall asks:
What do I already know that might matter right now?
Retain asks:
What should I remember from this conversation?
That separation made the system much easier to understand.
The Test That Made the Difference
The most useful test was extremely simple.
I entered:
Customer: Madhuri
"My laptop keyboard is not working properly."
The interaction was stored in Hindsight.
The memory displayed:
Madhuri reports that her laptop keyboard is not working properly.
Then I sent another message from the same customer:
"The keyboard issue is still happening."
This time, Hindsight retrieved the earlier information.
The application could now connect:
Current message:
"The keyboard issue is still happening."
+
Previous memory:
"Madhuri reports that her laptop keyboard is not working properly."
The support agent could respond with context:
Hi Madhuri! I remember your previous conversation.
I can use that information to better understand your
current issue and continue helping you.
That was the moment the project actually started feeling different from a normal chatbot.
The second conversation wasn't completely new anymore.
Before vs After
The difference can be summarized like this.
Without memory
Customer:
"The keyboard issue is still happening."
AI:
"What issue are you experiencing?"
The customer has to explain it again.
With Hindsight
Customer:
"The keyboard issue is still happening."
Hindsight:
"Previous keyboard problem found."
AI:
"I remember your previous conversation..."
The agent can continue from existing context.
It's a small example, but it demonstrates why persistent memory can matter in customer support.
Keeping the Memory Layer Separate
One thing I wanted to avoid was putting all the memory logic directly inside the UI.
The Hindsight client is initialized separately:
client = Hindsight(
base_url="http://localhost:8888"
)
The Streamlit application handles the interface.
Hindsight handles the memory operations.
That separation gives the project room to grow.
The same memory layer could eventually be used by a web application, customer-support dashboard, API, or automated support agent.
Hindsight's agent memory capabilities helped me think about memory as a separate system component rather than just another prompt variable.
The Part That Didn't Go Smoothly
The integration wasn't completely straightforward.
At one point, I experimented with asynchronous calls and multiple event-loop executions. That resulted in:
RuntimeError:
This event loop is already running
I then tried changing the execution approach, which led to another event-loop error involving a closed loop.
This was a useful debugging lesson because the problem wasn't actually my memory design.
There were two separate concerns:
Memory architecture
+
Python execution model
Mixing those together made the problem harder to understand.
I eventually simplified the implementation and kept the Hindsight service running separately from the Streamlit application.
The local setup became:
Terminal 1
|
v
Hindsight API
localhost:8888
^
|
| HTTP
|
v
Terminal 2
|
v
Streamlit
MemorySupport
That separation made debugging much easier.
A Small Prototype, but a Bigger Lesson
One thing I learned from this project is that a chat transcript and memory are not necessarily the same thing.
A transcript answers:
What did the customer say?
Memory tries to answer:
What information from the customer's history is relevant now?
That difference becomes important when conversations become longer.
Imagine a customer has contacted support ten times.
You don't necessarily want to send every previous message into every new request.
You want to find the information that actually matters.
That's where a memory layer becomes useful.
What I Would Change for Production
The prototype intentionally keeps things simple.
For a real customer-support system, I would change several things.
1. Use a real customer ID
Names aren't reliable identifiers. I would use a permanent customer ID from the application's identity system.
2. Add authentication
Customer memory should only be accessible to authorized users or systems.
3. Add memory-management policies
A production system needs clear rules for:
- What information is stored
- How long it is stored
- Who can access it
- How information can be corrected
- How information can be deleted
4. Store richer support information
Instead of only storing:
"My keyboard is not working."
the system could eventually remember:
Issue: Keyboard not working
Device: Laptop
Status: Unresolved
Previous action: Restarted device
That could make future support interactions more useful.
What I Learned From Building It
Start small
I didn't need a complicated multi-agent system to prove the memory concept.
One customer, one recurring problem, and one recall operation were enough.
Recall and retain are different
Separating retrieval from storage made the application easier to reason about.
Order matters
I wanted the application to retrieve existing information before saving the new message.
That keeps the current request separate from the memory it is about to create.
Infrastructure matters
A memory system can work correctly while the application still fails because the memory service isn't running.
Keeping the Hindsight service separate made this much easier to debug.
Memory should be treated as a system component
Instead of thinking:
AI + prompt
I started thinking:
AI
+
Memory
+
Application
That is a more useful architecture for applications where conversations need continuity.
Where I Want to Take It Next
The next version of MemorySupport could make the retrieved memory more structured.
For example, the agent could distinguish between:
- Previous unresolved issues
- Resolved issues
- Customer preferences
- Previous troubleshooting steps
- Product information
- Support history
The support agent could then use those memories to provide more contextual responses.
The flow would remain simple:
New Customer Message
|
v
Retrieve Relevant History
|
v
Use History as Context
|
v
Generate Response
|
v
Remember New Interaction
The goal isn't simply to make an AI answer questions.
It's to make the conversation continuous.
Conclusion
My AI support agent started with a simple problem: it forgot customers between conversations.
Using Hindsight, I turned memory into an explicit part of the application.
The system can retain customer interactions, recall relevant history, and use that context when the customer returns.
The implementation is still a prototype, and there are plenty of things I would change before putting it into production.
But the core idea works.
A customer says something once.
The system remembers it.
The customer comes back later.
The conversation can continue from there.
For me, that was the biggest takeaway from building MemorySupport:
A useful support agent shouldn't just answer the current message. It should understand where that message came from.


Top comments (0)