Give an app agent memory
Let a support agent remember each customer's preferences, recall them into the next model call as data, keep tool-supplied facts quarantined, and forget a person with a signed receipt.
Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.
Stability The promise an interface ships with.
- Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
- Beta Usable in production; may change before it becomes stable.
- Experimental May change or go away; needs an explicit opt-in in main.yaml.
Your support agent will remember what each customer tells it, such as how they like to be contacted, and use it in the next reply. Memories stay inside the customer's tenant, reach the model only as data, and are forgotten for real when the customer asks, with a receipt to show for it. It takes about 20 minutes.
You need
- A MainSDK app with
aiset up and an agent underagents(see Give an agent a budget). - Sign-in, so each request has a person and a tenant.
1. Declare memory and the agent's grant
memory:
driver: db # local in development works too
embed: { model: openai/text-embedding-3-small, feature: memory-embed }
ttl: { event: 90d }
from-tools: quarantine
agents:
support-bot:
budget: { spend: $5/day, calls: 500/day }
memory: { read: own, write: true, forget: approve, recalls: 500/day, writes: 100/day }read: own means the agent sees only what it wrote. forget: approve means a forget by the agent waits for a person.
2. Remember what the customer says
import { memory } from "mainsdk/experimental/memory";
export async function rememberPreference(text: string) {
return memory.remember(text, { kind: "preference" }); // about the person the agent acts for, in their tenant
}Call it when the customer states a preference, for example from a support.remember action the agent can call.
3. Recall into the next reply, as data
import { ai } from "mainsdk";
import { memory } from "mainsdk/experimental/memory";
export async function reply(user: { id: string }, message: string) {
const ctx = await memory.context({ query: message, budget: 800 });
const out = await ai.generate({
model: "anthropic/claude-sonnet-4-5",
messages: [
{ role: "user", content: ctx.text }, // one escaped <memory> block, never system text
{ role: "user", content: message },
],
feature: "support-chat",
agent: "support-bot",
user,
});
return out.text;
}If the store is down, ctx.text is an empty block and ctx.degraded is true; the reply still goes out.
4. Let a person confirm what a tool supplied
Facts the agent picked up from a tool or a web page are quarantined to their session. Show them to the customer and confirm the ones they agree with.
import { auth } from "mainsdk";
import { memory } from "mainsdk/experimental/memory";
export async function POST(req: Request) {
await auth.require(req);
const { id } = (await req.json()) as { id: string };
return Response.json(await memory.revise(id, { trust: "confirmed" }, { reason: "customer confirmed" }));
}5. Forget on request
import { auth } from "mainsdk";
import { memory } from "mainsdk/experimental/memory";
export async function POST(req: Request) {
const session = await auth.require(req);
const receipt = await memory.forget({ about: session.user }, { reason: "customer request" });
return Response.json({ receipt }); // signed by your project key; ids only, no content
}Verify
$ pnpm mainsdk check
memory: driver db, erase hard, regions eu, us
agents.support-bot.memory: read own, write, forget approve
0 findingsIn a test, remember a preference as one tenant and recall as another: the second gets nothing. Forget, then read the receipt: its signature verifies with your project's public key.
If it fails
| You see | Do this |
|---|---|
MAIN-MEM-0005 | The agent has no grant. Add memory under agents.<name> |
MAIN-MEM-0001 | No person in context. Call inside a signed-in request, or pass about |
MAIN-MEM-0003 | The text looked like instructions. Store what the person said, not what a tool returned |
MAIN-MEM-0022 | You passed recalled text as system. Put it in a user message |
MAIN-MEM-0023 | A driver in main.yaml is named memory. Rename it local |
For agents
Give support-bot memory with MainSDK: add memory (driver db) and agents.support-bot.memory
(read own, write true, forget approve) to main.yaml. Store preferences with memory.remember,
pass memory.context() text as a user message (never system), confirm tool-supplied memories
with memory.revise(id, { trust: "confirmed" }) from a person, and add a forget route that
returns the memory.forget receipt. Run pnpm mainsdk check until it reports 0 findings.Next
Was this page helpful?