Skip to main content

Memory Stores

Each memory subsystem is a separate store that handles one type of information. This page is the at-a-glance index. For a full “what it is, when to use it, and how to configure it” guide, follow the dedicated page for each store.
StoreRemembers…Dedicated guide
Sessionsthe current conversationSessions & History
Summariesrecaps of older conversationSummaries
User Factsfree-form facts about the personUser Facts
User Profilestructured profile (name, role, tz)User Profile
Entitiescompanies / people / projectsEntity Memory
Decisionswhat the agent decided & whyDecision Log
Learningsreusable insights (semantic)Learned Knowledge
Correctionsstructured human fixes to agent outputCorrection Capture
Graphrelationships you can traverseGraph Memory
Proceduresreusable tool workflowsProcedural Memory
The sections below summarize each store inline.

Summaries

Long-term conversation memory. When session history overflows, the overflow messages are summarized by an LLM and stored.
memory: {
  storage,
  summaries: {
    maxCount: 10,     // max summaries per session (default: 10)
    maxTokens: 2000,  // token budget for context injection (default: 2000)
  },
}

User Facts

Extracts and stores discrete facts about users: preferences, background, interests.
memory: {
  storage,
  userFacts: {
    maxFacts: 100,    // max facts per user (default: 100)
  },
}
Example extracted facts:
  • “Prefers dark mode”
  • “Lives in Mumbai”
  • “Works on logistics software”
The memory system automatically extracts facts from conversations:
// Conversation:
// User: "I'm based in Mumbai and usually work late, so schedule meetings after 6 PM IST."

// Extracted facts:
// - "Based in Mumbai"
// - "Prefers meetings after 6 PM IST"
// - "Works late hours"

// The agent sees in its next run:
// "User Facts:
//  - Based in Mumbai
//  - Prefers meetings after 6 PM IST
//  - Works late hours"
User facts are deduplicated automatically — if the user says “I’m in Mumbai” twice, only one fact is stored.

User Profile

Structured user data — name, role, company, timezone, language, custom fields.
memory: {
  storage,
  userProfile: {
    customFields: ["department", "subscription_tier"],
  },
}
Injected as structured context:
About this user:
- Name: Akash Sengar
- Role: Product Manager
- Company: Xhipment
- Timezone: Asia/Kolkata

Entity Memory

Tracks companies, people, projects, and products mentioned in conversations. Every entity is scoped to the user that created it — two users never see each other’s entities, even if they reference the same external company.
memory: {
  storage,
  entities: {
    namespace: "global",  // tenant-level partition (default: "global"). userId
                          // scoping is automatic on top of this.
  },
}
Provides tools: search_entities, create_entity. Both auto-inject the current ctx.userId, so the agent can never accidentally read or write another user’s entities. Entities are automatically extracted from conversations:
// Conversation:
// User: "We need to update the Xhipment dashboard. Talk to Raj from the frontend team."

// Extracted entities (stored under userId from ctx):
// - Xhipment (type: "product", attributes: { category: "dashboard" })
// - Raj (type: "person", attributes: { team: "frontend" })

// search_entities({ query: "frontend" })
// → [{ name: "Raj", type: "person", attributes: { team: "frontend" } }]

Direct access requires a userId

When you bypass the auto-exposed tools and call the store directly, you must pass the userId:
const entities = agent.memory!.getEntityMemory()!;

await entities.upsertEntity("user-123", {
  name: "Acme Corp",
  entityType: "company",
});

const list = await entities.listEntities("user-123");
const ctx = await entities.getContextString("user-123", "latest input");
The same pattern applies to GraphMemory and ProcedureMemory. Calling listEntities() without a userId is a TypeScript error — there is no “global” read path.

Decision Log

Audit trail of agent decisions — what was decided, why, and what happened.
memory: {
  storage,
  decisions: {
    maxContextDecisions: 5,  // recent decisions in context (default: 5)
  },
}
Provides tools: log_decision, record_outcome, search_decisions. Decisions are logged with context for audit trails:
// The agent automatically logs decisions using the log_decision tool:
// log_decision({
//   decision: "Approved refund of $45.99 for order #12345",
//   reasoning: "Order was delayed by 7 days, exceeding the 5-day SLA",
//   context: "Customer reported non-delivery on Dec 22",
// })

// Later, search past decisions:
// search_decisions({ query: "refund policy" })
// → [{ decision: "Approved refund of $45.99...", reasoning: "..." }]

// Record outcomes to track decision quality:
// record_outcome({
//   decisionId: "dec-abc123",
//   outcome: "success",
//   notes: "Customer confirmed receipt of refund",
// })

Learned Knowledge

Vector-backed insights from conversations. Requires a VectorStore.
import { QdrantVectorStore, OpenAIEmbedding } from "@agentium/core";

memory: {
  storage,
  learnings: {
    vectorStore: new QdrantVectorStore({
      url: "http://localhost:6333",
      embedding: new OpenAIEmbedding(),
    }),
    collection: "agentium_learnings",  // default
    topK: 3,                          // results injected into context
  },
  tenantId: "acme-corp",              // required for scope: "tenant" reads
}
Auto-injects relevant learnings into context AND exposes save_learning / search_learnings tools.

Scope hierarchy (v2.3+)

Learnings carry an explicit scope so genuinely shared knowledge isn’t trapped in one user’s silo:
ScopeVisible toUse for
"user" (default)the saving user onlypersonal preferences
"agent"every user of that agent / roleworkflow patterns (“Vendor X invoice drift”)
"tenant"every user/agent in the tenantorg-wide policies (“Refunds > $500 need VP”)
"global"everyonebuilt-in defaults
Reads are the union. When alice chatting with the invoice-recon agent at tenant acme searches for learnings, she sees her personal ones plus the agent-shared ones plus the tenant policies plus global defaults — but never another user’s personal scope or another agent’s shared scope. Writes pick one. The LLM (or your code) chooses the scope when saving:
// Agent's save_learning tool exposes the scope parameter:
save_learning({
  title: "Vendor X line-item drift",
  content: "Vendor X invoices consistently show $0.10–$0.50 drift per line.",
  context: "invoice reconciliation",
  scope: "agent",      // share with the whole invoice-recon team
})
If you call the store directly:
await learnings.saveLearning({
  title: "Org refund policy",
  content: "Refunds above $500 require VP approval.",
  context: "support / refunds",
  tags: ["policy"],
  namespace: "default",
  scope: "tenant",
  tenantId: "acme-corp",
});

const results = await learnings.searchLearnings("refund policy", {
  userId: "alice",
  agentName: "support",
  tenantId: "acme-corp",
  topK: 5,
});
Auto-extracted learnings always save as "user" — the framework never auto- promotes an LLM-extracted insight to a shared scope.

How Learnings Work

// Setup with vector store
const agent = new Agent({
  name: "support-agent",
  model: openai("gpt-4o"),
  memory: {
    storage,
    learnings: {
      vectorStore: new QdrantVectorStore({
        url: "http://localhost:6333",
        embedding: new OpenAIEmbedding(),
      }),
      topK: 3, // Inject top 3 most relevant learnings
    },
  },
});

// During a conversation, the agent discovers a useful pattern.
// Agent uses save_learning tool with scope="agent" so the whole team benefits:
// save_learning({
//   title: "Customs holds account for 80% of 'lost' international shipments",
//   content: "For delayed international shipments, check customs hold status
//             before issuing refunds. 80% of 'lost' packages are stuck in customs.",
//   context: "international shipping refunds",
//   tags: ["shipping", "customs", "refund"],
//   scope: "agent",
// })

// In a FUTURE conversation — DIFFERENT user, SAME agent:
// The vector store finds this learning is relevant
// and injects it into the system prompt:
// "Relevant Learnings:
//  - Customs holds account for 80%... [agent]: For delayed international shipments,
//    check customs hold status before issuing refunds."
The agent now proactively checks customs status before approving refunds — even though it learned this from a completely different conversation, and even when serving a completely different customer. See Multi-User Isolation for the full scope contract.

Correction Capture

Structured records of humans correcting agent output — field-level (originalValuecorrectedValue, reason, entityKey), embedded into a vector store, and retrieved on future relevant runs so the same mistake is not repeated. Requires a VectorStore.
memory: {
  storage,
  corrections: {
    vectorStore: new QdrantVectorStore({
      url: "http://localhost:6333",
      embedding: new OpenAIEmbedding(),
    }),
    collection: "agentium_corrections",  // default
    topK: 3,                             // results injected into context
  },
}
Corrections can be recorded three ways: the POST /agents/:name/corrections HTTP endpoint, agent.memory.recordCorrection(), or the auto-exposed record_correction tool. Corrections default to agent scope — a fix to an agent’s output is workflow knowledge that benefits every user. See Correction Capture for full documentation.

Graph Memory

Knowledge graph with entity-relationship tracking. Unlike flat entity memory, graph memory builds a traversable graph of nodes and edges with temporal metadata.
import { InMemoryGraphStore } from "@agentium/core";

memory: {
  storage,
  graph: {
    store: new InMemoryGraphStore(),
    autoExtract: true,     // extract entities + relationships from conversations
    maxContextNodes: 10,   // max nodes in context string
  },
}
See Graph Memory for full documentation.

Procedure Memory

Records and reuses successful multi-step tool-call workflows.
memory: {
  storage,
  procedures: true,     // or { maxProcedures: 100 }
}
See Procedural Memory for full documentation.

Temporal Awareness

All fact-based stores (User Facts, Entity Memory) now support temporal fields:
  • validFrom — when the fact became valid
  • invalidatedAt — when a newer fact superseded it
The LLM extraction prompts detect contradictions and mark old facts as superseded rather than keeping duplicates. See Temporal Awareness for full documentation.

All Auto-Exposed Tools

When memory stores are enabled, these tools become available to the agent:
StoreToolsDescription
Entity Memorysearch_entities, create_entitySearch and create entity records
Decision Loglog_decision, record_outcome, search_decisionsLog decisions and track outcomes
Learningssave_learning, search_learningsSave and retrieve vector-backed insights
Correctionsrecord_correction, search_correctionsRecord and retrieve structured human corrections
Graph Memoryquery_graph, traverse_entity, add_relationshipQuery and traverse the knowledge graph
Proceduresrecall_procedureFind matching multi-step workflows
These tools are automatically added to the agent’s tool set — no manual registration needed.