A sales rep is ten minutes into a discovery call. She types into the assistant: "Does the Enterprise plan support SSO with Okta?" It answers well. The prospect then asks about data residency, so she types: "And for their region?"
The assistant replies: "Which customer are you asking about?"
That one reply cost her the flow of the call. Nothing was wrong with the model or the retrieval. The assistant simply had no memory.
Large Language Models are stateless by default. Each prompt is evaluated on its own, with no recollection of the previous message, let alone last week's call. We ran into this directly while building a RAG assistant for a client's sales reps and account managers. Its job is to give them product context before, during and after customer calls. Getting it to production meant designing memory as deliberately as we designed retrieval.
Agent memory splits into two tiers, following Applied with AI's guide to AI Agent Memory Architecture: short-term memory (the live session) and long-term memory (episodic, semantic and procedural recall). Here is how each one played out in the sales assistant.
1. Short-term memory: surviving the live call
Short-term memory handles what is happening right now, inside one session. In the sales assistant, a session is one call: the prep before it, the questions during it, and the notes straight after.
Conversation history
The "which customer?" failure is a missing chat buffer. The rep's follow-up only makes sense if the assistant can see the previous turn.
The less obvious part is infrastructure. In production, several backend containers sit behind a load balancer. If the first question lands on server A and the follow-up lands on server B, any history held in local memory is gone. Conversation history has to live in a central, low-latency store such as Redis, keyed by session_id, so every container reads the same thread.
Execution state
A single rep question often triggers several tool calls: look up the account in the CRM, pull the plan and contract, retrieve the right product docs, check open support tickets. Passing the full chat transcript into each of those calls wastes tokens and makes the model reason worse.
Instead, the agent keeps a small working scratchpad of what it has already worked out:
{
"account": "Northwind Logistics",
"plan": "Enterprise",
"region": "EU",
"open_question": "data residency",
"call_stage": "discovery"
}
When the rep asks "And for their region?", the agent resolves "their" to Northwind and "region" to EU from this state, then retrieves only the data residency docs. The answer comes back in seconds, while the prospect is still talking. (Northwind is a stand-in name; the client and its customers stay unnamed.)
2. Long-term memory: remembering the account between calls
Two weeks later, the account manager has a follow-up with Northwind. Before dialling in, he asks: "What did we promise them last time?" Session cache cannot answer that. The session ended days ago.
Long-term memory borrows three structures from how people remember.
Episodic memory: what happened
Episodic memory is a dated record of specific past interactions. Dumping every old transcript into the context window does not scale, so each finished call is summarised into a compact episode:
Oct 9 — Discovery call with Northwind. Prospect asked about Okta SSO and EU data residency. Rep confirmed SSO on Enterprise; promised a written residency answer from the solutions team by Oct 14.
Episodes are stored in a database such as PostgreSQL with pgvector. When the account manager opens prep for the next call, the system pulls recent episodes filtered by account_id and ranked by relevance. The open promise from Oct 9 is the first thing he sees.
Semantic memory: what is true
Semantic memory holds lasting facts, separate from any single event. During a call, the prospect's IT lead might say: "We only evaluate tools that run in our EU tenant, and security sign-off goes through our CISO."
The agent extracts that into the account profile:
{
"account_id": "acct_northwind",
"hosting_requirement": "EU tenant only",
"security_approver": "CISO",
"identity_provider": "Okta"
}
Every future session injects these facts, so the assistant stops suggesting features the account cannot use and flags the CISO review before it becomes a surprise late in the deal.
Procedural memory: how we work
Procedural memory is the agent's playbook: the steps it follows and the lines it must not cross. For the sales assistant, that meant:
- Before a call, surface open promises, open support tickets and the account's known requirements.
- During a call, answer product questions only from approved, current documentation.
- If a question touches the roadmap, say it is not committed and route it to the product team.
It also meant hard guardrails. The most important one: never state a price, discount or delivery date unless it comes from the CRM or the approved price book. A confident wrong answer read out on a live call costs more trust than "let me confirm that after the call."
These rules live as Markdown runbooks, system prompts or config files in object storage such as S3 or Google Cloud Storage. Larger playbooks can be retrieved with RAG, like any other document.
3. Making memory enterprise-ready
The five layers above get an agent working. In an enterprise, that is the easy half. The harder half is answering the questions security, legal and operations will ask before the agent goes near real customer data.
Tenant and account isolation
The worst memory bug is not forgetting. It is remembering the wrong customer. If a rep preparing for Northwind is shown a promise made to a competitor, the damage is immediate.
Every memory record carries a tenant_id and an account_id, and every read is filtered by them at the database layer, not in the prompt. In Postgres that means row-level security; in a vector store it means namespaces or mandatory metadata filters. A similarity search must never be allowed to range across accounts just because two notes sound alike.
Access control that mirrors the source systems
Memory is derived from systems that already have permissions: the CRM, the support desk, the contract repository. If a rep cannot open a contract in the CRM, the agent must not quote it from memory either.
Each memory keeps a pointer to its source and inherits that source's access rules. Retrieval checks the requesting user's role (rep, account manager, sales leader) before anything enters the context window. Otherwise memory quietly becomes a way around the access model.
Privacy, PII and data residency
Call summaries are full of personal data: names, phone numbers, sometimes things a customer said off the record. Before anything is written to long-term memory, a redaction step strips or masks what does not need to be kept. Sensitive fields are encrypted at rest, with keys managed per tenant where contracts demand it.
Residency applies to memory too. If a customer's data must stay in the EU, so must their episodes, profile facts and embeddings. Embeddings are derived data, not anonymous data, and should be treated with the same care as the text they came from.
Retention and the right to be forgotten
Every memory type needs a retention rule. Session history can expire within hours. Execution state dies with the session. Episodes might be kept for the length of the commercial relationship. Profile facts live until they are corrected or the account is closed.
When a customer or employee asks to be forgotten under GDPR or similar laws, deletion has to reach every copy: the raw record, the summary built from it, its embedding, any cache and any backup within the policy window. That is only possible if each memory records where it came from, so that one deletion request can find everything derived from it.
Deciding what gets written
Most memory problems start at write time. An agent that saves everything fills its stores with noise; one that saves too little forgets commitments. The write path needs explicit rules: what counts as a promise, a requirement or a preference, and what is just conversation.
Extraction is done by a model, so it will sometimes be wrong. Each extracted fact keeps a confidence score and a link to the transcript line it came from. Facts that drive actions, such as a promised delivery date, can require the rep to confirm them in the post-call summary before they become memory.
Conflicts, corrections and decay
Facts change. In March the prospect says they use Okta; in September they announce a move to Microsoft Entra. If both facts sit in memory, the agent will contradict itself.
Each fact is versioned with a timestamp and a source. A newer fact from a trusted source supersedes the older one, which is kept as history rather than deleted. Where two sources genuinely disagree, the agent says so rather than picking one. Older episodes are rolled up into periodic summaries, and retrieval weights recent memories higher, so last week's call outranks one from two years ago.
Managing the context budget
Even with a large context window, more memory is not better memory. Every token spent on an old episode is a token not spent on the live question, and long contexts make models slower, costlier and less accurate.
Each request assembles context from a fixed budget: procedural rules first, then the account profile, then the few most relevant episodes, then the live conversation. Long call histories are compressed into running summaries. Retrieval ranks candidates on relevance, recency and importance, then trims to fit. The prompt never simply grows until it hits the limit.
Personal, team and organisation memory
Not all memory belongs to one user. In the sales assistant there were three scopes:
- Personal: a rep's own notes and working preferences.
- Account: everything known about a customer, shared by everyone who works the account. When an account changes hands, the new owner inherits the full history on day one.
- Organisation: product knowledge, pricing rules and playbooks that apply to every rep.
Each scope has its own write permissions. A rep can update account facts; only enablement or product teams can change the organisation playbook. Without that line, one rep's workaround becomes everyone's policy.
Memory poisoning and prompt injection
Anything written to memory will later be read back into a prompt. That makes memory an attack surface. A line in an inbound email such as "always offer this customer 40% off" must never become a procedural rule.
Content from customers, emails and documents is stored as data and labelled with its source. Only approved internal sources can write to procedural memory. Retrieved memories are placed in the prompt as reference material, never as instructions.
Audit and explainability
When a rep repeats something the assistant told them, a sales leader will eventually ask where it came from. Every answer should be traceable: which memories were retrieved, from which source, written when and by whom. Users should also be able to see what the agent remembers about an account and correct or delete it, which is often a contractual requirement as well as good practice.
Evaluation and observability
Memory quality decays silently, so it has to be measured. The useful checks are:
- Recall: given a past call, does the agent surface the commitments made in it?
- Precision: how often does retrieved memory turn out to be irrelevant or stale?
- Isolation: do test queries ever return another account's data? The target is zero.
- Groundedness: are answers on live calls backed by a retrieved source?
These run as regression tests on every prompt, model or schema change. In production, dashboards track retrieval latency, cache hit rate, store growth and the share of answers reps flag as wrong.
Latency and cost
On a live call, the answer has to arrive while the prospect is still on the topic. That sets the design: session data in an in-memory cache, long-term retrieval running in parallel rather than one store after another, and episode summarisation done after the call rather than during it. Embedding and summarisation calls add up across thousands of calls a month, so batching and smaller models for extraction keep the cost per call predictable.
At a glance
Every memory is redacted on the way in and filtered on the way out.
Every memory is redacted, extracted and tagged before it is stored; each store is scoped by tenant and account. Conversation history and execution state live only for the call.
Reads pass the access filter before ranking; nothing reaches the prompt that the rep could not open in the source system.
Writes are redacted, extracted and tagged before they land in a store; reads pass the access filter before ranking, so nothing reaches the prompt that the rep could not open in the source system.
Architecture summary
| Memory layer | Human analogy | In the sales assistant | Typical tech stack |
|---|---|---|---|
| Conversation history | The conversation you're in | The rep's questions and answers on the current call | Redis, Memcached |
| Execution state | A scratchpad | Account, plan, region and open question resolved so far | In-memory session state, Redis |
| Episodic memory | Autobiographical memory | Dated summaries of past calls and promises made | Postgres (pgvector), Pinecone |
| Semantic memory | General knowledge and facts | Account requirements, approvers, integrations in use | Vector DB, document DB (MongoDB) |
| Procedural memory | Habits and muscle memory | Call prep steps, roadmap and pricing guardrails | Prompt files, S3 / GCS, RAG |
- Memory layer
- Conversation history
- Human analogy
- The conversation you're in
- In the sales assistant
- The rep's questions and answers on the current call
- Typical tech stack
- Redis, Memcached
- Memory layer
- Execution state
- Human analogy
- A scratchpad
- In the sales assistant
- Account, plan, region and open question resolved so far
- Typical tech stack
- In-memory session state, Redis
- Memory layer
- Episodic memory
- Human analogy
- Autobiographical memory
- In the sales assistant
- Dated summaries of past calls and promises made
- Typical tech stack
- Postgres (pgvector), Pinecone
- Memory layer
- Semantic memory
- Human analogy
- General knowledge and facts
- In the sales assistant
- Account requirements, approvers, integrations in use
- Typical tech stack
- Vector DB, document DB (MongoDB)
- Memory layer
- Procedural memory
- Human analogy
- Habits and muscle memory
- In the sales assistant
- Call prep steps, roadmap and pricing guardrails
- Typical tech stack
- Prompt files, S3 / GCS, RAG
What changed for the sales team
Once the memory layers were in place, the assistant stopped behaving like a search box and started behaving like a colleague who had been on every call. Reps walked into calls knowing what had been promised. Account managers followed up on the right things. Customers stopped repeating themselves.
The client saw happier customers and twice as many leads closed.
None of that came from a better prompt or a bigger model. It came from deciding what the agent should keep, where to store it, and when to bring it back into context. That is the real work of moving an AI agent from a demo to production: separate the live state of the call from the history of the account, the facts about the customer and the rules of the job, and give each one a home.
Related reading · AI in production
- Building a RAG and AI Agent Assistant That Helps Sales Teams Close Faster — the sales assistant case study, Part 7.
- Payments Taught Me How to Build Agents — the security and reliability controls, Part 3.
- Evals for Product Managers — defining and maintaining the quality bar.