How to architect systems that give AI applications persistent, cross-platform memory — covering local-first storage, sync engines, offline support, and the future of AI knowledge graphs.
Founder & Lead Engineer at Toffee
Human experts do not start from scratch each day. A senior engineer brings years of accumulated decisions, patterns, and domain knowledge to every task. But AI systems — despite being powerful reasoning engines — begin every session with a blank slate.
Cross-AI memory systems aim to solve this by creating a persistent knowledge layer that sits between the user and the AI models they use. This layer captures, stores, retrieves, and injects relevant context across sessions and platforms, giving AI interactions the continuity that they currently lack.
Building such a system involves solving problems across several domains: browser engineering for capture, distributed systems for synchronization, information retrieval for relevance ranking, and security for protecting sensitive knowledge.
A cross-AI memory system consists of four architectural layers:
The capture layer intercepts AI conversations as they happen. In a browser-based implementation, this is a Manifest V3 extension with platform-specific content scripts that extract structured data from the DOM. The capture layer is responsible for:
Raw conversations are processed into compressed, structured knowledge bundles. This layer runs either locally (for privacy) or server-side (for higher-quality compression using frontier models). It performs entity extraction, decision mapping, preference detection, and semantic synthesis.
Compressed bundles are stored in a local-first database (IndexedDB via Dexie). Local-first means the database is the source of truth — cloud sync is optional and additive. This ensures the system works offline and maintains user privacy by default.
When a user starts a new AI session, relevant context bundles are identified, formatted for the target model, and injected as system context. This layer must handle the diversity of target platforms and their unique context formatting requirements.
Local-first architecture means the application functions fully without a network connection. All data is stored on the user's device first, with cloud sync as an optional, additive feature. This architecture provides several advantages for AI memory systems:
IndexedDB is the browser's built-in NoSQL database with virtually unlimited storage capacity. Using Dexie as a typed wrapper provides a developer-friendly API:
import Dexie, { Table } from 'dexie';
interface ContextBundle {
id: string;
platform: string;
title: string;
summary: string;
tags: string[];
compressedContext: string;
originalTokens: number;
compressedTokens: number;
createdAt: Date;
updatedAt: Date;
syncStatus: 'local' | 'synced' | 'pending';
}
class MemoryDB extends Dexie {
bundles!: Table<ContextBundle>;
constructor() {
super('ToffeeMemory');
this.version(1).stores({
bundles: 'id, platform, *tags, createdAt, syncStatus',
});
}
}
export const memoryDb = new MemoryDB();
The *tags index syntax creates a multi-entry index, allowing efficient queries like "find all bundles tagged with 'react' or 'typescript'." This is essential for relevance-based context retrieval.
For users who want cross-device access to their AI memory, a synchronization engine bridges the local database with cloud storage. The key design principles are:
The sync engine does not require immediate consistency. Changes made on one device are queued and synchronized when a connection is available. Conflicts are resolved using a last-write-wins strategy (appropriate for single-user data where concurrent edits are rare).
interface SyncOperation {
id: string;
type: 'create' | 'update' | 'delete';
bundleId: string;
payload?: ContextBundle;
createdAt: Date;
retryCount: number;
status: 'pending' | 'in-progress' | 'failed';
}
async function processSyncQueue(): Promise<void> {
const pending = await syncDb.operations
.where('status').equals('pending')
.sortBy('createdAt');
const chunks = chunkArray(pending, 5); // Process 5 at a time
for (const chunk of chunks) {
const results = await Promise.allSettled(
chunk.map(op => executeSyncOperation(op))
);
for (let i = 0; i < results.length; i++) {
if (results[i].status === 'rejected') {
const op = chunk[i];
if (op.retryCount < 5) {
await syncDb.operations.update(op.id, {
retryCount: op.retryCount + 1,
status: 'pending',
});
} else {
await syncDb.operations.update(op.id, { status: 'failed' });
}
} else {
await syncDb.operations.delete(chunk[i].id);
}
}
}
}
The sync engine processes operations in batches of 5 to avoid overwhelming the network or triggering rate limits. Failed operations are retried up to 5 times before being marked as permanently failed. Promise.allSettled ensures that one failed operation does not block others in the same batch.
Synced bundles should be encrypted before leaving the device. Using the Web Crypto API, bundles are encrypted with a key derived from the user's credentials. The server stores only ciphertext — even a database breach reveals nothing about the user's AI conversations.
When a user starts a new AI conversation, the memory system must determine which stored bundles are relevant. This is an information retrieval problem with several approaches:
The simplest approach: match entities and tags in stored bundles against the current conversation topic. Fast but imprecise — it misses semantic relationships.
More sophisticated: compute vector embeddings of bundle summaries and the current prompt, then find bundles with the highest cosine similarity. This captures semantic relationships that keyword matching misses. For example, a bundle about "database migration" would be retrieved when the user asks about "schema changes" even though the keywords do not overlap.
Combine relevance scores with recency: recent bundles about the same topic are more likely to be useful than older ones. The scoring function might look like:
function relevanceScore(bundle: ContextBundle, query: string): number {
const semanticScore = cosineSimilarity(embed(bundle.summary), embed(query));
const recencyDecay = Math.exp(-daysSince(bundle.updatedAt) / 30);
return semanticScore * 0.7 + recencyDecay * 0.3;
}
This weights semantic relevance at 70% and recency at 30%, with recency decaying exponentially over a 30-day half-life. Bundles more than 90 days old contribute almost no recency score, while a highly relevant bundle from yesterday would score very high on both axes.
Current context transfer systems operate on individual conversation bundles — discrete units of knowledge extracted from single conversations. The next evolution is connecting these bundles into a unified knowledge graph where entities, decisions, and preferences from different conversations are linked.
Imagine the following scenario: You have three separate conversations about a project — one about the database schema, one about the API design, and one about the frontend architecture. In the current model, these are three separate bundles. In a knowledge graph model, the entities (tables, endpoints, components) are linked across conversations, creating a unified project context that is richer than any individual conversation.
Building this requires:
GET /api/users reads from the users table and provides data to the UserList React componentThis is significantly harder than per-conversation compression, but it represents the direction that AI memory systems are moving. The organizations that solve cross-conversation knowledge linking will provide a dramatically more powerful context experience than those limited to individual conversation bundles.
AI context portability is still in its early days. The infrastructure being built today — local-first storage, secure sync, semantic compression, cross-platform adapters — forms the foundation for a future where AI interactions are continuous, persistent, and truly intelligent about the user's accumulated knowledge.
Local-first means the application stores all data on the user's device as the source of truth. Cloud sync is optional and additive — the application functions fully offline. This architecture prioritizes privacy, performance, and reliability.
Bundles are encrypted on the device using keys derived from the user's credentials before being sent to the cloud. The server stores only encrypted ciphertext. Even a server breach reveals nothing about the content of AI conversations.
A context bundle is a compressed snapshot of a single AI conversation. A knowledge graph connects entities across multiple conversations, creating a unified understanding of a project or domain. Knowledge graphs enable richer context retrieval but are significantly harder to build.
Learn how AI context transfer works, why language models lose memory between sessions, and how protocols like Toffee compress and port conversation context across ChatGPT, Claude, and Gemini without data loss.
A deep technical exploration of semantic compression — the process of reducing AI conversation transcripts by 60-80% while preserving entities, decisions, preferences, and structural relationships.
Practical techniques for reducing token usage in AI applications — from prompt engineering and context pruning to semantic deduplication and budget-aware injection strategies.