Skip to content

Memory & Sessions ​

ArchadiAgent separates three layers of state:

  1. Agent configuration — the Agent object itself (instructions, tools, model). Immutable, shared across every run.
  2. Current run state — held only for the duration of one Runner.run() call (the in-flight messages array, the active agent during handoffs, the trace). Never persisted.
  3. Persistent session state — the conversation transcript, via a SessionStore, keyed by sessionId, surviving across runs/process restarts.

Sessions (raw transcript) ​

ts
import { FileSessionStore, InMemorySessionStore } from "archadi-agent";

const sessionStore = new FileSessionStore(".archadi/sessions.json"); // zero-dependency, durable
// or: new InMemorySessionStore()                                    // fast, lost on restart

const agent = Agent.builder().name("Assistant").instructions("...").model(target).sessionStore(sessionStore).build();

await runner.run(agent, "my name is Aditya", { sessionId: "user-42" });
await runner.run(agent, "what's my name?", { sessionId: "user-42" }); // remembers, same session

Implement the SessionStore interface yourself to back it with Redis, SQLite, Postgres, etc:

ts
interface SessionStore {
  getHistory(sessionId: string): Promise<ChatMessage[]>;
  appendMessages(sessionId: string, messages: ChatMessage[]): Promise<void>;
  clear(sessionId: string): Promise<void>;
  listSessions(): Promise<string[]>;
}

Long-term memory (semantic, cross-session) ​

A SessionStore replays the entire transcript every run — fine for one conversation, wasteful across months of usage. LongTermMemory instead extracts and retrieves only what's relevant to the current message, using mem0:

ts
import { Mem0Memory } from "archadi-agent";

const memory = new Mem0Memory({ apiKey: process.env.MEM0_API_KEY! }); // hosted
// or: new Mem0Memory({ mode: "local", localConfig: { /* vector store config */ } })

const agent = Agent.builder().name("Assistant").instructions("...").model(target).longTermMemory(memory).build();

await runner.run(agent, "I prefer TypeScript over Python", { userId: "aditya" });
// ... weeks later, a different session ...
await runner.run(agent, "what language should I use for this script?", { userId: "aditya" });
// -> the Runner recalls relevant facts and injects them into the system prompt automatically

mem0ai is an optional peer dependency — install it only if you use Mem0Memory:

bash
npm install mem0ai

No mem0 account yet? SimpleLongTermMemory is a zero-setup, in-process fallback with the same interface — the CLI's --memory flag uses it by default.

How the Runner uses both together ​

Each run() call:

  1. Loads the session transcript (sessionStore.getHistory) and prepends it to the prompt.
  2. Recalls relevant long-term facts (longTermMemory.recall) and injects them into the system message.
  3. After a successful run, appends the new turn to the session store and long-term memory (longTermMemory.remember).

SQLite storage ​

For production durability without running a separate database server, use the built-in SQLite adapter:

bash
npm install better-sqlite3
ts
import { SqliteSessionStore } from "archadi-agent";

const sessionStore = new SqliteSessionStore("./data/sessions.db");

const agent = Agent.builder()
  .name("Assistant")
  .instructions("...")
  .model(target)
  .sessionStore(sessionStore)
  .build();

The SQLite store auto-creates the database file and table on first use, uses WAL mode for performance, and wraps batch writes in transactions. Call sessionStore.close() during graceful shutdown.

Custom storage adapters ​

Implement the SessionStore interface to back sessions with Redis, Postgres, DynamoDB, or anything else:

ts
class RedisSessionStore implements SessionStore {
  async getHistory(sessionId: string): Promise<ChatMessage[]> { /* ... */ }
  async appendMessages(sessionId: string, messages: ChatMessage[]): Promise<void> { /* ... */ }
  async clear(sessionId: string): Promise<void> { /* ... */ }
  async listSessions(): Promise<string[]> { /* ... */ }
}