AI Memory

How the AI remembers things across conversations and how apps contribute context

Imagine telling the AI you prefer TypeScript over JavaScript, that your team deploys to staging every Tuesday, or that “Project Aurora” is the internal name for your Q2 launch. Without memory, you’d repeat yourself every conversation. With memory, the AI just knows.

Memory turns the AI from a stateless tool into a teammate that learns your preferences, understands your project, and builds on past conversations. It works at two levels: personal memories that follow you around, and workspace knowledge shared across your team.

Remembering things

When you say something like “remember that I prefer dark mode” or “keep in mind our staging server is api-staging.example.com”, the AI stores that as a memory. It categorizes it automatically — preference, fact, or context — and loads it into every future conversation.

The AI doesn’t announce what it remembers. If you ask about deployment and the AI knows your staging URL, it references it naturally. If a memory contradicts something you’re saying right now, the current conversation wins.

The AI recognizes phrases like “remember that…” or “keep in mind…” and stores them automatically. Beyond that, the Memory app exposes four actions that the AI can invoke as app actions during conversation:

  • remember — store a new memory from text you provide
  • recall — search your memories (“recall anything about deployment”)
  • list — see everything you’ve stored
  • forget — remove a specific memory (“forget the thing about dark mode”)
  • add — summarize recent messages into a memory

These are full app actions implemented in the Memory app (src/apps/memory/app.tsx), not just UI operations. The AI discovers and calls them the same way it calls any installed app’s actions.

How context gets loaded

Before every conversation, the AI loads relevant context in the background. Your personal memories and workspace-wide knowledge are fetched in parallel, each with a 500ms timeout — if the database is slow, the AI starts without context rather than making you wait.

The system loads up to 20 entries per category. Your memories are sorted by recency. Workspace knowledge is sorted by weight (importance) first, then recency. Each entry is capped at 200 characters in the prompt — enough for a fact or preference, with longer content available through search on demand.

This context appears in the AI’s prompt as “memories about you” and “workspace knowledge” sections. The AI is instructed to use these naturally and trust the current conversation over stored memories if they conflict.

AI visibility

When apps store data, the aiVisibility field controls how the AI can access it.

context — loaded into every conversation automatically. The AI sees this before you say anything. Use for preferences, key facts, and critical reference data that should always be top of mind.

await tools.data.public.set('api-limit', 'rate limit is 1000 req/min', {
aiVisibility: 'context',
scope: 'server',
weight: 4,
})

searchable — the default. Not loaded upfront, but the AI finds it when searching. Most app data belongs here: synced records, issues, customers, documentation. The AI discovers it on demand when someone asks a relevant question.

await tools.data.public.set('customer:acme', JSON.stringify(customer), {
title: 'Acme Corp',
kind: 'customer',
// aiVisibility defaults to 'searchable'
})

hidden — invisible to the AI. Won’t appear in context or search results. Hidden entries are actively removed from the search index. Use for internal app state, sync cursors, or bookkeeping data that has no value in conversation.

await tools.data.public.set('sync:cursor', lastId, {
aiVisibility: 'hidden',
})

Note that tools.data.private already keeps data invisible to the AI and other users. Setting aiVisibility: 'hidden' on public data is for entries that should appear in the workspace data view but stay out of AI conversations.

Scope

The scope field controls whose conversations include the data.

user — belongs to one person. The AI only loads user-scoped context in that person’s conversations. Your memories are private to you — the AI won’t reference your preferences when talking to someone else.

server — shared across the workspace. This is the default. Everyone’s conversations include server-scoped context. Team knowledge, project glossaries, and shared conventions go here.

channel — tied to a specific channel. Useful for channel-specific guidelines or project-focused reference data that only matters in one conversation space. Note: channel-scoped data is available through search but is not automatically loaded into the AI’s context the way user and server scoped data is.

Apps contributing context

Any app can enrich the AI’s knowledge through the aiVisibility and scope fields on stored data. A practical pattern: store your most important records as context so the AI always knows about them, and everything else as searchable for on-demand discovery.

actions: {
sync: {
description: 'Sync accounts from CRM',
async run({ tools }) {
const accounts = await fetchAccounts()
for (const account of accounts) {
await tools.data.public.set(
`account:${account.id}`,
JSON.stringify(account),
{
title: account.name,
kind: 'account',
aiVisibility: account.arr > 100_000 ? 'context' : 'searchable',
scope: 'server',
weight: account.arr > 100_000 ? 5 : 1,
},
)
}
return `synced ${accounts.length} accounts`
},
},
}

The weight field influences ordering for context-level data. Higher-weight items load first when there are many entries competing for those 20 slots. Give critical data a weight of 4-5, nice-to-have context 1-2. Weight has no effect on searchable or hidden data.