> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory

> Give agents persistent memory across sessions with pluggable backends

Memory lets agents remember past conversations, user preferences, and context across sessions.

<Note>
  A subset of `Memory` is now callable directly over MCP — see [MCP Memory Tools](/docs/features/mcp-memory-tools).
</Note>

<Note>
  Replaces the deprecated `auto_save="name"` kwarg — see [Legacy Agent Parameters](/docs/features/agent-legacy-params).
</Note>

## Grow memory autonomously

With `self_improve="background"` **and** `memory=True`, the same guarded post-turn review that autonomously grows skills can also autonomously persist durable facts and preferences via `store_memory` — off the hot path, with zero cost to reply latency and zero context pollution during the live turn. See [Self-Improving Agents](/docs/features/self-improve).

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    name="Assistant",
    instructions="You are a helpful personal assistant.",
    memory=True,  # memory is isolated per instance — pass user_id="…" to share/persist across runs
)

agent.start("My name is Alice and I prefer concise answers.")
```

The user shares preferences in chat; the agent recalls them in later sessions via the configured memory backend.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Memory Flow"
        Input[💬 User Input] --> Store[💾 Memory Store]
        Store --> Recall[🔍 Recall Context]
        Recall --> Response[✅ Contextual Response]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Input input
    class Store,Recall process
    class Response output
```

<Warning>
  **Breaking change: `backend` no longer accepts `redis`/`postgres`/`valkey`.**

  `MemoryConfig(backend="redis")`, `backend="postgres"`, and `backend="valkey"` now raise a `ValueError` instead of silently substituting a local file store. Earlier releases *accepted* these values but stored data locally — so any code that "worked" was already not reaching Redis/Postgres.

  Valid backends: `file`, `sqlite`, `chroma`, `mem0`, `mongodb`, `dakera`, `in_memory`.

  **Two supported ways to use Redis / Postgres:**

  1. **Recommended — pass a live `db()` store:**

     ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
     from praisonaiagents import Agent, MemoryConfig, db

     agent = Agent(
         name="Assistant",
         instructions="You are a helpful assistant.",
         memory=MemoryConfig(db=db(state_url="redis://localhost:6379/0")),
     )
     ```

     `from praisonaiagents import db` binds the callable factory directly. The namespaced `from praisonaiagents.db import db` form still works.

  2. **Advanced — register a custom adapter:**
     ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
     from praisonaiagents.memory.adapters import register_memory_adapter

     register_memory_adapter("redis", MyRedisAdapter)
     agent = Agent(memory=MemoryConfig(backend="redis"))  # now accepted
     ```

  See [Redis persistence](/docs/features/persistence-redis) for the full `db(state_url=...)` guide.
</Warning>

## Quick Start

<Steps>
  <Step title="Level 1 — Bool (simplest)">
    Turn on memory with a single flag — the agent remembers across turns using the default file backend.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        name="Assistant",
        instructions="You are a helpful assistant.",
        memory=True,  # memory is isolated per instance — pass user_id="…" to share/persist across runs
    )
    agent.start("Remember that I work in software engineering.")
    ```

    <Tip>
      `memory=True` and `memory="file"` are truly zero-dependency — the agent skips importing the heavier `Memory` module on this path, so `Agent(memory=True)` starts as fast as an agent with no memory. Heavier backends (`sqlite`, `chroma`, `mem0`, `mongodb`, `dakera`, or `learn=True`) load their dependencies lazily and raise a friendly `ImportError` if the `praisonaiagents[memory]` extra isn't installed.

      If a memory provider's backend package **is** installed but initialisation fails (for example a SaaS backend like `mem0` needs credentials or network), the agent now falls back to `FileMemory` with a warning instead of raising. This mirrors the existing "missing dependencies → `FileMemory`" contract, so `Agent(...)` construction never hard-crashes on a misconfigured backend.
    </Tip>
  </Step>

  <Step title="Level 2 — String (pick a backend)">
    Pass a backend name to choose where memories are stored.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        name="Assistant",
        instructions="You are a helpful assistant.",
        memory="sqlite",
    )
    agent.start("Remember that I prefer concise answers.")
    ```
  </Step>

  <Step title="Level 3 — Config class (full control)">
    Use `MemoryConfig` to scope memory per user and auto-extract facts.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MemoryConfig

    agent = Agent(
        name="Assistant",
        instructions="You are a helpful assistant.",
        memory=MemoryConfig(
            backend="sqlite",
            user_id="alice",
            auto_memory=True,
        ),
    )
    agent.start("What do you know about my preferences?")
    ```
  </Step>

  <Step title="Level 4 — Config with continuous learning">
    Add `LearnConfig` to build a long-term persona alongside session memory.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MemoryConfig, LearnConfig

    agent = Agent(
        name="Assistant",
        instructions="You are a helpful assistant.",
        memory=MemoryConfig(
            backend="sqlite",
            user_id="alice",
            learn=LearnConfig(persona=True, insights=True, mode="agentic"),
        ),
    )
    agent.start("I always want answers formatted as bullet points.")
    ```
  </Step>
</Steps>

***

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Memory

    User->>Agent: Message
    Agent->>Memory: Store conversation turn
    Agent->>Memory: Retrieve relevant context
    Memory-->>Agent: Past context
    Agent-->>User: Context-aware response
```

| Phase       | What happens                                          |
| ----------- | ----------------------------------------------------- |
| 1. Store    | Each conversation turn is saved to the memory backend |
| 2. Retrieve | Relevant past context is recalled before responding   |
| 3. Respond  | Agent answers with full historical context available  |

<Note>
  Retrieved memory reaches the system prompt under normal logging (WARNING/INFO). You no longer need `verbose=5` / DEBUG logging or an explicit `include_in_output=True` for `Agent(memory=True)` to take effect during a chat — see [Memory Troubleshooting](/docs/features/memory-troubleshooting).
</Note>

<Tip>
  Turn on `prefetch=True` on `MemoryConfig` to have relevant long-term memories injected into the system prompt at the start of every turn — no explicit `recall()` call required.
</Tip>

***

## Which Backend to Choose?

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What's your setup?}
    Q -->|Prototype / single server| F[file backend\ndefault, zero deps]
    Q -->|Single server, persistent| S[sqlite backend]
    Q -->|Vector search / RAG| C2[chroma backend]
    Q -->|Multi-agent shared memory| M[mem0 or mongodb]
    Q -->|Self-hosted decay-weighted memory| D[dakera]
    Q -->|Redis / Postgres| DB[use db\(url=...\)]
    Q -->|Anthropic model with long context| C[claude_memory=True]

    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef backend fill:#6366F1,stroke:#7C90A0,color:#fff

    class Q decision
    class F,S,C2,M,D,DB,C backend
```

***

## Configuration Options

<Card icon="code" href="/docs/sdk/reference/praisonaiagents/modules/feature_configs">
  Full list of options, types, and defaults — `MemoryConfig`
</Card>

The most common options at a glance:

| Option                  | Type                          | Default  | Description                                                                                                                                                       |
| ----------------------- | ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend`               | `str`                         | `"file"` | Storage backend: `file`, `sqlite`, `chroma`, `mem0`, `mongodb`, `dakera`, `in_memory`. Aliases: `chromadb`/`rag` → `chroma`, `none` → `in_memory`.                |
| `user_id`               | `str \| None`                 | `None`   | User identifier for scoped memory. Leaving it `None` now yields a per-instance `agent-<uuid>` id (not a shared `"default"`) — set it to share/persist across runs |
| `auto_memory`           | `bool`                        | `False`  | Auto-extract and store key facts                                                                                                                                  |
| `learn`                 | `bool \| LearnConfig \| None` | `None`   | Enable continuous learning                                                                                                                                        |
| `history`               | `bool`                        | `False`  | Auto-inject session history into context                                                                                                                          |
| `prefetch`              | `bool`                        | `False`  | Opt-in: at turn start, recall long-term memories relevant to the user prompt and inject them into the system context                                              |
| `prefetch_limit`        | `int`                         | `5`      | Max number of memories injected per turn                                                                                                                          |
| `prefetch_token_budget` | `int`                         | `512`    | Estimated-token cap for the injected memory block (truncated with `…` if exceeded)                                                                                |

<Note>
  Turn on `prefetch=True` on `MemoryConfig` to have relevant long-term memories injected into the system prompt at the start of every turn — no explicit `recall()` call required. See [Memory Prefetch](/docs/features/memory-prefetch) for the full guide.
</Note>

***

## Combining `backend` and `config`

Pass a `config=` dict alongside `backend=` to hand provider-specific settings to the store — the outer `backend=` still decides which store is built.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonaiagents.config.feature_configs import MemoryConfig

agent = Agent(
    name="Assistant",
    instructions="Remember facts across turns.",
    memory=MemoryConfig(
        backend="sqlite",
        user_id="alice",
        config={"short_db": "./mem/short.db"},
    ),
)
agent.start("My favourite colour is teal.")
```

An explicit `provider` or `backend` key inside `config=` wins; otherwise the outer `backend=` fills in.

| What you wrote                                                | Backend actually used |
| ------------------------------------------------------------- | --------------------- |
| `MemoryConfig(backend="sqlite")`                              | `sqlite`              |
| `MemoryConfig(backend="sqlite", config={"short_db": "…"})`    | `sqlite`              |
| `MemoryConfig(backend="sqlite", config={"provider": "file"})` | `file` (inner wins)   |
| `MemoryConfig(backend="sqlite", config={"backend": "file"})`  | `file` (inner wins)   |
| `MemoryConfig(backend="file")`                                | `file`                |

<Note>
  The `config` dict you pass in is never mutated — a provider key, if injected, is written to an internal copy. Safe to share the same dict across multiple agents.
</Note>

***

## Common Patterns

### Pattern 1 — User-scoped memory

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MemoryConfig

agent = Agent(
    instructions="You are a personal assistant.",
    memory=MemoryConfig(user_id="user_alice", backend="sqlite"),
)
response = agent.start("What have I told you about my work preferences?")
print(response)
```

### Pattern 2 — History injection for conversation continuity

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MemoryConfig

agent = Agent(
    instructions="You are a support agent.",
    memory=MemoryConfig(history=True, history_limit=5),
)
agent.start("Continue from where we left off.")
```

<Note>
  Default sessions are **workspace-scoped** — the same agent name in a different project is a different session. See [Where sessions live](/docs/docs/memory/features#where-sessions-live) for details and the `PRAISONAI_GLOBAL_SESSIONS` opt-out.
</Note>

### Pattern 3 — Recalled context at turn start

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MemoryConfig

writer = Agent(
    name="writer",
    instructions="Store user facts.",
    memory=MemoryConfig(backend="file", user_id="alice"),
)
writer.memory.remember("User prefers metric units and dark mode.")

reader = Agent(
    name="reader",
    instructions="Answer using recalled context.",
    memory=MemoryConfig(
        backend="file",
        user_id="alice",
        prefetch=True,          # inject long-term memories at turn start
        prefetch_limit=5,
        prefetch_token_budget=512,
    ),
)

reader.start("What are my UI preferences?")
```

The agent sees a `## Recalled memories` block in its system prompt before the first model call — no extra tool call needed.

***

## Quick API — `remember`, `recall`, `forget`

Three verbs give you explicit control over long-term facts — store, look up, and delete.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Quick Memory API"
        R[📝 remember] --> S[💾 Long-term Store]
        S --> C[🔍 recall]
        S --> F[🗑️ forget]
    end

    classDef verb fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef store fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef out fill:#10B981,stroke:#7C90A0,color:#fff

    class R,F verb
    class S store
    class C out
```

An agent with `memory=True` exposes its memory instance directly, so you can store and recall facts on demand.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    name="Note Taker",
    instructions="Save and recall project facts on request.",
    memory=True,
)

# The agent's memory instance is available directly
agent.memory.remember("Sprint 42 ships on Friday")
matches = agent.memory.recall("When does sprint 42 ship?")
```

Use `Memory()` standalone in a plain script — no config, no agent required.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.memory import Memory

mem = Memory()  # no config needed — uses local SQLite
mem.remember("API rate limit is 1000 req/min")
for m in mem.recall("rate limit"):
    print(m["text"])
mem.forget(query="rate limit")
```

### Prompt-ready context — `get_context`

`get_context(query=...)` returns retrieved memory as a single prompt-ready string for a given query — the same string `Agent.get_memory_context()` injects into the system prompt.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(name="Assistant", instructions="Help the user.", memory=True)
agent.memory.remember("User is working on the climate dashboard project.")

ctx = agent.memory.get_context(query="What projects am I working on?")
print(ctx)
```

An empty or whitespace-only `query` intentionally returns `""` — this avoids a `LIKE "%%"` scan that would pull in unrelated (and possibly other users') records.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
agent.memory.get_context(query="")   # -> ""  (nothing leaked)
```

Pass `user_id="…"` (or configure it on `MemoryConfig`) so user-scoped memories stay isolated when a single `Memory` instance is shared across users.

### Parameters

| Method                    | Parameter   | Type           | Default      | Description                                                                                                                                                                                                                                                                                                                                                            |
| ------------------------- | ----------- | -------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Memory()`                | `config`    | `dict \| None` | `None`       | Backend config. Optional — omit for the default local backend.                                                                                                                                                                                                                                                                                                         |
| `Memory()`                | `verbose`   | `int`          | `0`          | Verbosity level.                                                                                                                                                                                                                                                                                                                                                       |
| `remember`                | `content`   | `str`          | *(required)* | Fact to store in long-term memory.                                                                                                                                                                                                                                                                                                                                     |
| `remember`                | `metadata`  | `dict \| None` | `None`       | Keyword-only. Extra metadata stored with the record.                                                                                                                                                                                                                                                                                                                   |
| `remember` *(returns)*    | —           | `str`          | —            | The generated memory id.                                                                                                                                                                                                                                                                                                                                               |
| `recall`                  | `query`     | `str`          | *(required)* | Search string.                                                                                                                                                                                                                                                                                                                                                         |
| `recall`                  | `limit`     | `int`          | `5`          | Keyword-only. Max results returned.                                                                                                                                                                                                                                                                                                                                    |
| `recall` *(returns)*      | —           | `list[dict]`   | —            | Matching records, each with at least a `text` field.                                                                                                                                                                                                                                                                                                                   |
| `forget`                  | `memory_id` | `str \| None`  | `None`       | Keyword-only. Delete by exact id. When no `memory_type` is passed, deletes from **both** tiers — short-term and long-term ids can collide because each tier has its own `AUTOINCREMENT` sequence, and the returned count reflects rows removed from both. Pass `memory_type="short_term"` or `"long_term"` via `delete_memory()` to scope the delete to a single tier. |
| `forget`                  | `query`     | `str \| None`  | `None`       | Keyword-only. Delete long-term records matching this query.                                                                                                                                                                                                                                                                                                            |
| `forget` *(returns)*      | —           | `int`          | —            | Count of records deleted across both tiers when `memory_id` is used without a tier.                                                                                                                                                                                                                                                                                    |
| `get_context`             | `query`     | `str \| None`  | `None`       | Search string. Empty/whitespace returns `""`.                                                                                                                                                                                                                                                                                                                          |
| `get_context`             | `user_id`   | `str \| None`  | `None`       | Keyword arg. Falls back to the configured `user_id`.                                                                                                                                                                                                                                                                                                                   |
| `get_context` *(returns)* | —           | `str`          | —            | Prompt-ready context string (`""` when nothing matches).                                                                                                                                                                                                                                                                                                               |

<Note>
  `remember()` and `recall()` operate on **long-term** memory only, and `forget(query=...)` is scoped to long-term memory to match. `forget()` requires **exactly one** of `memory_id` or `query` — passing neither, both, or an empty query raises `ValueError`.
</Note>

<Warning>
  **Cross-tier id collisions are normal.** The SQLite adapter numbers short-term and long-term rows independently, so the Nth short-term row and the Nth long-term row share an id. `forget(memory_id=id)` now deletes from **both** tiers by design — previously it short-circuited on the first hit and could erase the wrong record while reporting success. If you need tier-scoped deletion, call `agent.memory.delete_memory(memory_id, memory_type="long_term")` (or `"short_term"`).
</Warning>

`agent.memory.get_all_memories()` returns every stored short-term and long-term record (each with a public `type` field of `"short_term"` or `"long_term"`). When a memory adapter is configured, it now correctly delegates to the adapter — earlier releases returned `[]` for every provider.

### Which memory API?

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What do you need?}
    Q -->|Auto-save every turn of a chat| A["Agent(memory=True)"]
    Q -->|Explicitly store & look up facts| B["memory.remember() / recall() / forget()"]
    Q -->|Both| C["Agent(memory=True) then agent.memory.remember(...)"]

    classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef opt fill:#6366F1,stroke:#7C90A0,color:#fff
    class Q q
    class A,B,C opt
```

### Interaction flow

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Memory

    User->>Agent: "Remember our launch date is Nov 15."
    Agent->>Memory: remember("launch date Nov 15")
    Memory-->>Agent: memory_id

    Note over User,Memory: ...days later, new session...

    User->>Agent: "When is our launch?"
    Agent->>Memory: recall("launch date")
    Memory-->>Agent: [{text: "launch date Nov 15", ...}]
    Agent-->>User: "November 15."
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Always set user_id when you want memory to persist or be shared">
    As of PraisonAI PR #3614, `Agent(memory=True)` **without** a `user_id` generates a fresh per-instance identifier (`agent-<uuid>`) and logs a warning. Memory is **isolated per Agent object** by default — safe, but **not** what you want if you re-create the agent between requests and expect it to remember the last conversation.

    Pass `user_id="alice"` (or `"tenant-42"`, `"project-climate"`, etc.) to opt into a shared / persistent store that survives across processes.

    As of PraisonAI [#4203](https://github.com/MervinPraison/PraisonAI/pull/4203), this isolation now covers every backend — `sqlite`, `chroma`, `mongodb`, `mem0`, and `learn` derive per-agent default store paths and collection names from the same `agent-<uuid>` id, so two agents in one process no longer silently share one `short_term.db` / `long_term.db` / `memory_store`. Explicit `user_id`, `short_db`, `long_db`, `rag_db_path`, or `collection_name` still win. See [Per-agent isolation across backends](/docs/features/multi-agent-memory#per-agent-isolation-across-backends).

    ```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    graph TB
        Q{Do you want memory<br/>to survive re-creating<br/>the Agent?} -->|No — one-shot| Iso["✅ Agent(memory=True)<br/>per-instance, auto-isolated"]
        Q -->|Yes — persist / share| Named["✅ Agent(memory={'user_id': '…'})<br/>shared across runs"]

        classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
        classDef iso fill:#6366F1,stroke:#7C90A0,color:#fff
        classDef named fill:#10B981,stroke:#7C90A0,color:#fff
        class Q q
        class Iso iso
        class Named named
    ```
  </Accordion>

  <Accordion title="Use auto_memory for fact extraction">
    Enable `auto_memory=True` to have the agent automatically identify and store important facts from each conversation — names, preferences, decisions — without extra code.
  </Accordion>

  <Accordion title="Combine memory with learning">
    Set `learn=True` inside `MemoryConfig` to enable continuous learning alongside session memory. This gives agents both short-term context (memory) and long-term pattern recognition (learn).
  </Accordion>

  <Accordion title="Backend scaling path">
    Start with `file`, move to `sqlite` when you need durability, then `mongodb` (or `chroma` for vector search) when you deploy multiple agent instances that share memory. For Redis or Postgres, use `memory=MemoryConfig(db=db(state_url="redis://..."))` or `db(database_url="postgresql://...")` — see [Redis persistence](/docs/features/persistence-redis).
  </Accordion>

  <Accordion title="Choose remember/recall for facts, memory=True for conversation history">
    `Agent(memory=True)` auto-captures every conversation turn. `remember()` / `recall()` / `forget()` give you **explicit** control for fact storage — use them for structured knowledge you want to look up later. Both share the same long-term store when the agent's `memory` instance is used.
  </Accordion>
</AccordionGroup>

***

## Async safety

Task-callback memory writes (`store_in_memory` in `Task.execute_callback`) run on a worker thread on the async path. Parallel tasks batched into a single `asyncio.gather(...)` no longer stall the event loop on one slow embedding/DB write.

The built-in in-memory adapter is thread-safe: concurrent async writes from multiple parallel tasks cannot produce duplicate ids or lose entries.

No user-facing change: the async path automatically dispatches the write via `asyncio.to_thread`.

<Note>
  If you write a custom memory adapter that will be used from async task callbacks, make its mutating methods thread-safe — see [Custom Memory Adapters](/docs/features/custom-memory-adapters). The full set of async guarantees lives on the [Async Safety](/docs/features/async-safety) page.
</Note>

***

## Related

<CardGroup cols={2}>
  <Card title="Learn" icon="graduation-cap" href="/docs/features/learn">
    Learn — continuous learning from conversations
  </Card>

  <Card title="Knowledge" icon="book" href="/docs/features/knowledge">
    Knowledge — add documents and URLs as agent knowledge
  </Card>

  <Card title="Memory Flush on Compaction" icon="database-backup" href="/docs/features/pre-compaction-memory-flush">
    Preserve facts before compaction — save durable facts before older messages are dropped
  </Card>

  <Card title="Async Safety" icon="shield-check" href="/docs/features/async-safety">
    Offloaded memory writes and the thread-safe in-memory adapter
  </Card>
</CardGroup>
