Skip to main content
Memory lets agents remember facts and preferences across separate runs — scoped per user, tenant, or custom tags — without relying on conversation history alone. 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 with a memory.Config:
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")
result, _ := a.Run(ctx, "Remember I prefer concise answers.", nil)

Backends

BackendPackageNotes
Weaviatepkg/memory/weaviateVector search — Docker-friendly for dev
pgvectorpkg/memory/pgvectorPostgres + pgvector — requires an embed function
CustomImplement interfaces.MemoryPass to memory.DefaultConfig(yourStore)
Infrastructure setup (local dev):
# 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:
ctx := memory.WithContextUserID(ctx, userID)
ctx = memory.WithContextTenantID(ctx, tenantID) // optional
a.Run(ctx, prompt, nil)
By default, memories are also isolated per agent name. Override resolvers or add custom tags on memCfg.ScopeConfig:
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

ModeBehavior
On-demand (default)The LLM calls the save_memory tool during the run when it decides to persist something
AlwaysMemories are saved automatically when the run finishes
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.
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.

Recall config

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

Default TTL per memory kind:
KindDefault TTL
decision7 days
note48 hours
factNo expiry
preferenceNo expiry
instructionNo expiry
Override with memCfg.TTLPolicy:
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 Worker Separation for the full split-process setup.

Custom backend

Implement interfaces.Memory:
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

Memory

Weaviate and pgvector store/recall demos

Conversation

Session history within a single chat

Retrieval

RAG from external document stores

Hooks

BeforeMemoryLoad and BeforeMemoryStore hooks

Configuration

WithMemory reference