Short answer: Split user-scoped customer facts from project-wide playbooks; use ticket properties as soft walls inside a hard authenticated customer id boundary.
Customer support agents must know who the customer is, what they already tried, and which policies apply—without mixing accounts. Ticket history alone is not enough: preferences, escalations, and shared resolution patterns need different isolation rules. Weaviate Engram supplies user-scoped personalization, project-wide continual learning, property scopes for ticket or conversation boundaries, and bounded topics for singular profiles or summaries. Treat authenticated customer id as the hard wall and ticket ids as filters inside it—never invent the customer id from free text. Keep chain-of-thought scratchpads out of durable customer memory. Search both layers every turn; write asynchronously so latency is never an excuse to skip memory. Prove isolation with automated cross-customer probes.
Customer support agents live or die by memory. The agent must know who the customer is, what they already tried, and which policies apply, without ever mixing one account into another. Ticket history alone is not enough. Preferences, prior escalations, and shared resolution patterns sit in different layers, and each layer needs a different isolation rule. Weaviate Engram gives support products that architecture directly: user-scoped personalization for customer facts, project-wide continual learning for playbooks, property scopes for ticket or conversation boundaries, and bounded topics when a profile or summary must stay singular. This chapter explains why support memory fails when it is one flat store, how Engram groups separate customer privacy from team skill, how ticket scopes keep threads tidy without losing cross-ticket recall, how to search both layers on every turn, and how hard isolation at the storage layer beats filters you hope the application remembers.
The design goal is simple to say and hard to fake. Every customer should feel remembered. No customer should ever see another customer’s life.
Why does a single memory pile break support workflows?
Support traffic looks conversational, so teams often dump every transcript into one vector index. That feels convenient on day one. It becomes dangerous quickly. A refund preference from customer A can surface for customer B when the wording is similar. A temporary scratchpad note about an internal workaround can become durable “fact.” A playbook lesson that should help every agent gets trapped inside one user’s thread, or worse, a private preference gets promoted into global policy.
Those failures are not exotic. Cross-tenant bleed in agent memory is a known production risk when isolation is only an application filter. Semantic search will happily rank another customer’s memory if nothing in the storage layer forbids it. Support also mixes time scales. The open ticket needs a running summary. The account needs durable preferences. The operations team needs lessons that improve tomorrow’s refunds. One pile cannot hold all three jobs safely.
So the architecture question arrives next. How do you give the agent rich recall without making isolation a checklist item developers must remember on every call?
How should Engram groups split customer memory from agent skill?
Engram’s docs use customer support as the canonical multi-group example for a reason. A support agent usually needs two use cases with different magnets and different scopes. A personalization group holds user-scoped topics such as contact preferences, plan tier, and device history. Writes and searches require a user_id, and Weaviate multi-tenancy enforces hard isolation between customers. A continual_learning group holds project-wide topics such as escalation heuristics and FAQ-first refund checks. Those memories are shared across agents and customers because they describe how to do the job, not who the customer is.
That split prevents two opposite mistakes. Without a personalization group, every ticket starts cold and customers repeat themselves. Without a continual-learning group, every good resolution dies when the shift ends. Mixing both into one group with one scope forces a false choice: either leak customer data into shared skill, or starve the playbook of transferable experience. Separate groups keep topic names and pipelines tuned to each job while still living in one Engram project.
Bounded topics tighten the personalization side further. A user-scoped profile topic can stay singular per customer so the agent always has one canonical card to fetch into the system prompt. An optional conversation summary topic scoped by conversation_id or ticket id stays singular per thread and updates in place as messages arrive. Unbounded topics still accumulate discrete facts over time. The support architecture is therefore not “store everything.” It is “store the right shape in the right group.”
Where do ticket and conversation scopes fit without trapping useful recall?
After groups settle the privacy versus skill split, property scopes handle thread locality. A topic can require custom properties such as ticket_id. On write, Engram demands those properties when the topic is configured to need them. On search, including a property narrows results to that ticket. Omitting it searches across all of a customer’s tickets. That soft isolation is intentional. You can keep the open-thread summary tight while still asking, across the account, whether this person already disputed the same warranty claim last spring.
Support products should treat the authenticated customer id as the hard boundary and ticket ids as filters inside that boundary. Never invent the customer id from free text in the prompt. Pass it from the session that already proved identity. Engram will refuse to cross users for user-scoped topics even if the query string would otherwise match. That is the difference between a hope and a guarantee.
Internal scratchpads still need discipline outside Engram. Chain-of-thought notes and tool dumps belong in short-lived working state, not in durable customer memory. Engram topics are magnets. If a topic description asks for customer preferences, the pipeline will pull preferences. If you feed it raw planner noise without a matching topic, you avoid polluting the store. Topic design is part of the architecture, not decoration.
What does a support turn look like when both memory layers are wired correctly?
On each customer message, the agent should retrieve personalization memories for that user_id, retrieve continual-learning playbooks without a user filter, and only then call the model. After the turn, it should add the conversation messages into the personalization path so new facts can extract asynchronously. Playbook lessons can be written separately when a resolution is confirmed, often without user_id, so the skill stays shared.
Here is a concrete warranty desk for a luthier parts brand. The customer is arguing about a cracked bridge on a claimed manufacturing defect. The open ticket lives on one bench. Personal facts stay on the customer. The refund playbook stays project-wide.
import os
from engram import EngramClient
from engram.types import HybridRetrieval
client = EngramClient(api_key=os.environ["ENGRAM_API_KEY"])
customer = "cust_rio_valdez_guitars"
ticket = "luthier-warranty-bench-2"
# Customer-private recall for this account (and optionally this ticket).
profile_hits = client.memories.search(
query="Prior warranty claims, preferred contact channel, instrument model",
user_id=customer,
group="personalization",
retrieval_config=HybridRetrieval(limit=5),
properties={"ticket_id": ticket},
)
# Shared playbooks: no user_id, because skill is project-wide.
playbooks = client.memories.search(
query="Cracked bridge warranty steps before offering a partial refund",
group="continual_learning",
retrieval_config=HybridRetrieval(limit=5),
)
turn = [
{
"role": "user",
"content": (
"This is ticket luthier-warranty-bench-2. My cedar-top parlor "
"arrived with a hairline bridge crack. Email only, please. "
"I already sent photos last Tuesday."
),
},
{
"role": "assistant",
"content": (
"I see the photos on this ticket and your email preference. "
"I will follow the cracked-bridge checklist before discussing "
"repair versus partial refund."
),
},
]
# Fire-and-forget personalization write. Do not block the agent reply path.
run = client.memories.add(
turn,
user_id=customer,
group="personalization",
properties={"ticket_id": ticket},
)
print(run.run_id, run.status)
The two searches return different kinds of truth. Personalization may recall that Rio prefers email and already filed photos. Continual learning may recall that hairline bridge cracks need humidity checks before refund offers. Hybrid retrieval helps both keyword-heavy policy language and fuzzy customer phrasing. The add call returns immediately. Engram’s pipeline extracts, reconciles, and commits in the background so the chat stays responsive.
When you need a single profile card in every system prompt, configure a bounded user profile topic and fetch it rather than hoping search ranks it first. When you need the live ticket synopsis, keep a bounded summary scoped by ticket id and update it as messages arrive. Search remains for open-ended questions. Fetch remains for known singular objects.
What isolation tests should a support memory design refuse to skip?
Architecture without tests is a story. Store a distinctive preference under customer A. Search as customer B with the same query. Assert empty or irrelevant results. Repeat across groups to confirm playbooks still appear without customer leakage. Omit user_id on a user-scoped write in staging and confirm Engram rejects the call rather than inventing a shared bucket. These checks belong in CI because prompt injection and hurried application code both love to “helpfully” drop filters.
Also separate product documentation from Engram memory. Shared policy manuals can live in a normal knowledge index. Engram holds per-customer state and learned agent skill. A personalized support answer often merges both: docs for what is allowed, Engram for what this customer already lived through. That composition keeps the knowledge base publishable and the memory store private.
Support memory architecture is therefore a disciplined use of Engram primitives, not a bigger transcript dump. Use groups to split personalization from continual learning. Use user_id as the hard wall between customers. Use ticket properties as soft walls inside an account. Use bounded topics for profiles and running summaries. Search both layers every turn, and write asynchronously so latency never becomes an excuse to skip memory. Our next chapter, How should you design memory architecture for coding assistants?, turns the same isolation and topic ideas toward developer tools, where personal coding habits and shared repository decisions need an equally careful split.