> ## Documentation Index
> Fetch the complete documentation index at: https://smithers-feat-claude-workflow-mirror.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory

> Cross-run facts, message history, namespaces, and task memory metadata.

Memory persists state **across runs**. Task outputs are per-run; memory is per-namespace and survives every workflow execution.

<Note>API reference: [Memory](/reference/memory) lists every memory export and type, its options, and links to source and tests.</Note>

```mermaid theme={null}
flowchart LR
  W[workflow] --> ST
  AG[agent] --> ST
  U[user] --> ST
  GL[global] --> ST
  ST[(Memory store<br/>one SQLite db)] --> F[Facts · namespaced JSON, optional TTL]
  ST --> H[Message history · ordered threads]
  style ST fill:#def,stroke:#36c
```

## Three layers

```ts theme={null}
import { createMemoryStore } from "smithers-orchestrator/memory";
import { Database } from "bun:sqlite";
import { drizzle } from "drizzle-orm/bun-sqlite";

const sqlite = new Database("smithers.db");
const db = drizzle(sqlite);
const store = createMemoryStore(db);
const ns = { kind: "workflow" as const, id: "code-review" };
```

| Layer           | API                                                                                                                                                          | Use for                                                                 |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| Facts           | `store.setFact(ns, key, value, ttlMs?)` / `store.getFact(ns, key)` / `store.listFacts(ns)`                                                                   | Namespaced JSON facts. Optional TTL. Last-write-wins.                   |
| Message history | `store.createThread(ns, title?)`, `store.listThreads(ns)`, `store.saveMessage(msg)`, `store.listMessages(threadId, limit)`, `store.deleteMessages(threadId)` | Ordered chat threads per agent or user; list/delete to compact history. |
| Maintenance     | `store.deleteExpiredFacts()` plus processors                                                                                                                 | TTL cleanup and history compaction.                                     |

Every method has an Effect-returning twin (`store.listThreadsEffect`, `store.deleteMessagesEffect`, etc.) for use inside an Effect pipeline.

## Namespaces

```ts theme={null}
type MemoryNamespace = { kind: "workflow" | "agent" | "user" | "global"; id: string };
```

Pick the kind to match the lifetime: `workflow` is scoped to a workflow definition; `agent` to an agent identity; `user` to an end user; `global` is shared across everything.

## Task Memory Metadata

```tsx theme={null}
<Task
  id="review"
  output={outputs.review}
  agent={reviewer}
  memory={{
    recall:   { namespace: ns, topK: 3 },               // inject relevant past facts into prompt
    remember: { namespace: ns, key: "last-review" },    // persist this output as a fact
    threadId: `${ctx.input.repo}:reviews`,              // append messages to this thread
  }}
>
  Review the latest PR.
</Task>
```

`memory` is preserved on the task descriptor as metadata for runtimes and integrations that layer memory behavior onto task execution. The direct store APIs above are the current public memory read/write surface.

## Imperative get/set/delete inside a workflow

The `memory={{ recall, remember }}` block above is **declarative metadata**; it is preserved on the task descriptor for runtimes that layer memory onto task execution, not an imperative call. To actually get, set, or delete a fact **while a run is executing**, build a store with `createMemoryStore(db)` and call it from inside a compute `<Task>` (a function task with no `agent`). The compute callback receives `deps` only; there is no injected `store`, so you create one:

```tsx theme={null}
import { createMemoryStore } from "smithers-orchestrator/memory";
import { Database } from "bun:sqlite";
import { drizzle } from "drizzle-orm/bun-sqlite";

const store = createMemoryStore(drizzle(new Database("smithers.db")));
const ns = { kind: "workflow" as const, id: "code-review" };

<Task id="remember-model" output={outputs.done}>
  {async () => {
    await store.setFact(ns, "model", "gpt-4");           // set
    const fact = await store.getFact(ns, "model");        // get (MemoryFact | undefined)
    const all  = await store.listFacts(ns);               // list
    await store.deleteFact(ns, "stale-key");              // delete
    return { done: true };
  }}
</Task>
```

Create the store once at module scope (outside the workflow) and reuse it across tasks rather than re-opening the SQLite handle in every task body. Under Effect, the same operations are available as `store.setFactEffect(ns, key, value, ttlMs?)`, `store.getFactEffect(ns, key)`, etc., or via `MemoryService` (`MemoryServiceApi`), which also exposes the underlying `.store`.

## Processors

Maintenance jobs you run periodically:

```ts theme={null}
import { TtlGarbageCollector, TokenLimiter, Summarizer } from "smithers-orchestrator/memory";

const gc         = TtlGarbageCollector();   // expire facts past their TTL
const limiter    = TokenLimiter(4000);      // keep history under token budget
const summarizer = Summarizer(myAgent);     // compress old messages with an LLM

await gc.process(store);
await limiter.process(store);
await summarizer.process(store);
```

```mermaid theme={null}
flowchart LR
  M[Facts + messages accumulate] --> GC[TtlGarbageCollector<br/>drop expired facts]
  GC --> TL[TokenLimiter<br/>trim history to budget]
  TL --> SM[Summarizer<br/>compress old messages with an LLM]
  SM --> K[Compact, in-budget memory]
  style K fill:#dfe,stroke:#3a3
```

## Inspect from the CLI

```bash theme={null}
bunx smithers-orchestrator memory list workflow:code-review -w workflow.tsx
```

The CLI currently exposes fact listing. Use the store API for writes, deletes, threads, messages, and TTL cleanup.

## Notes

* Memory and task outputs are **distinct stores**. Don't use memory for run-scoped state; it's not transactional with the workflow's frame commits.
* Working-memory writes are unordered. Use message history when sequence matters.
