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

# Memory

> Store and recall long-term memories scoped by user or tenant using Weaviate, pgvector, or custom backends

Memory lets agents **remember facts and preferences across separate runs** — scoped per user, tenant, or custom tags — without relying on conversation history alone.

At the start of each run, the SDK performs a semantic search against the memory store using the incoming prompt as a query. Matching memories are **injected as a labeled "Relevant Memories" message** ahead of conversation history (the system prompt itself is left untouched) — so the model can reference past facts without the caller having to pass them explicitly. When both memory and [retrieval](/features/retrieval) prefetch are active, memory is placed first, RAG context second, keeping the request's stable prefix (system prompt, tools) unaffected by either. The agent also stores new memories during or after the run depending on the store mode.

Use it when users return across sessions, when preferences should persist beyond a single conversation, or when you need tenant- or project-scoped memory separate from chat history.

## Enable

Pass [`WithMemory`](/getting-started/configuration) with a [`memory.Config`](https://pkg.go.dev/github.com/agenticenv/agent-sdk-go/pkg/memory#Config):

```go theme={null}
import (
    "github.com/agenticenv/agent-sdk-go/pkg/agent"
    "github.com/agenticenv/agent-sdk-go/pkg/memory"
    wmem "github.com/agenticenv/agent-sdk-go/pkg/memory/weaviate"
)

store, _ := wmem.NewMemory(
    wmem.WithHost("localhost:8080"),
    wmem.WithClassName("AgentMemory"),
)

a, err := agent.NewAgent(
    agent.WithMemory(memory.DefaultConfig(store)),
    agent.WithLLMClient(llmClient),
)
defer a.Close()

// Attach scope on the context for each run
ctx := memory.WithContextUserID(context.Background(), "user-123")
agentRun, _ := a.Run(ctx, "Remember I prefer concise answers.", nil)
result, _ := agentRun.Get(ctx)
```

## Backends

| Backend | Package | Notes |
| - | - | - |
| Weaviate | `pkg/memory/weaviate` | Vector search — Docker-friendly for dev |
| pgvector | `pkg/memory/pgvector` | Postgres + pgvector — requires an embed function |
| Custom | Implement `interfaces.Memory` | Pass to `memory.DefaultConfig(yourStore)` |

**Infrastructure setup (local dev):**

```bash theme={null}
# Weaviate
docker run --rm -p 8080:8080 -p 50051:50051 cr.weaviate.io/semitechnologies/weaviate:latest

# pgvector (Postgres with pgvector extension)
docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=pass pgvector/pgvector:pg16
```

Both Weaviate and pgvector are external shared stores — the same backend works for single-process and remote-worker deployments. Both processes must reach the same host or cluster.

## Scope

Memories are isolated by scope. Attach context values on every run that should share memories:

```go theme={null}
ctx := memory.WithContextUserID(ctx, userID)
ctx = memory.WithContextTenantID(ctx, tenantID) // optional
agentRun, err := a.Run(ctx, prompt, nil)
result, err := agentRun.Get(ctx)
```

By default, memories are also isolated per agent name. Override resolvers or add custom tags on `memCfg.ScopeConfig`:

```go theme={null}
memCfg.ScopeConfig = memory.ScopeConfig{
    UserIDResolver: func(ctx context.Context) string { return myApp.UserID(ctx) },
    ExtraKeys:      []string{"project_id"},
    TagResolvers: map[string]memory.ScopeResolver{
        "project_id": func(ctx context.Context) string { return myApp.ProjectID(ctx) },
    },
}
```

## Store modes

| Mode | Behavior |
| - | - |
| **On-demand** (default) | The SDK exposes a `save_memory` tool. The LLM calls it during the run when it decides something is worth remembering |
| **Always** | At run end, the SDK runs an extraction step (LLM call or your `Extract` function) and saves the results automatically |

```go theme={null}
memCfg := memory.DefaultConfig(store)
memCfg.Store.Mode = memory.StoreModeOnDemand  // default
// memCfg.Store.Mode = memory.StoreModeAlways
```

Use **on-demand** when the model should decide what to persist. Use **always** when every run should be saved without relying on tool calls — useful for pipelines and batch agents where you want comprehensive memory without explicit tool calls.

## Memory kinds

Memories are tagged with a `Kind` that controls TTL defaults and filtering:

| Kind | Meaning | Default TTL |
| - | - | - |
| `fact` | Objective fact about the user or domain | No expiry |
| `preference` | User preference or style setting | No expiry |
| `instruction` | Standing instruction for the agent | No expiry |
| `note` | Short-term note from a recent session | 48 hours |
| `decision` | Decision made during a run | 7 days |

Set `memCfg.Recall.Kinds` to filter which kinds are recalled for a given agent.

<Warning>
  With `StoreModeAlways` and no custom `Extract`, the worker needs `WithLLMClient` when using remote workers — the SDK runs an LLM call at run-end to extract memories. Set `memCfg.Store.Extract` to a custom function if you want to avoid this extra LLM call.
</Warning>

## Recall config

```go theme={null}
memCfg.Recall = memory.RecallConfig{
    Enabled:  true,    // default true; set false for store-only
    Limit:    20,      // default 10
    MinScore: 0.4,     // default 0.35
    Kinds:    []interfaces.MemoryKind{memory.KindPreference, memory.KindFact},
}
```

## TTL and dedup

Override default TTLs with `memCfg.TTLPolicy`:

```go theme={null}
memCfg.TTLPolicy = memory.TTLPolicy{
    memory.KindPreference: 0,              // no expiry
    memory.KindNote:       7 * 24 * time.Hour,
}
```

`memCfg.Store.DedupMinScore` (default **0.85**) controls whether a near-duplicate memory is updated or appended. Lower to dedup more aggressively; raise to keep distinct entries.

## Remote workers

Pass the **same** `memory.Config` to both `NewAgent` and `NewAgentWorker`. Both processes must reach the same backend host. See [Distributed Execution](/advanced/distributed-execution) for the full split-process setup.

## Custom backend

Implement [`interfaces.Memory`](https://pkg.go.dev/github.com/agenticenv/agent-sdk-go/pkg/interfaces#Memory):

```go theme={null}
type Memory interface {
    Store(ctx context.Context, scope MemoryScope, record MemoryRecord, opts ...StoreMemoryOption) (string, error)
    Load(ctx context.Context, scope MemoryScope, query string, opts ...LoadMemoryOption) ([]MemoryEntry, error)
    Clear(ctx context.Context, scope MemoryScope) error
}
```

* `Store` persists in scope and returns an ID. Support `WithMemoryID` for upserts.
* `Load` returns scoped results ordered by relevance; honor limit and min-score options.
* `Clear` deletes all memories in a scope.

Pass to `memory.DefaultConfig(yourStore)` and use with `agent.WithMemory`.

## Example

<CardGroup cols={2}>
  <Card title="Memory" icon="play" href="/examples/memory" horizontal>
    Weaviate and pgvector store/recall demos
  </Card>
</CardGroup>

## Related

<CardGroup cols={2}>
  <Card title="Conversation" icon="messages" href="/features/conversation" horizontal>
    Session history within a single chat
  </Card>

  <Card title="Retrieval" icon="book-open" href="/features/retrieval" horizontal>
    RAG from external document stores
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.