Memory
Entity memory, user profile, and session context in the Contacts agent.
The Contacts agent is a mini CRM that remembers people, the facts you tell it about them, who knows whom, and what's happening between them.
Three memory stores, each scoped to a different shape of state:
1from kern.learn import (2 LearningMachine, LearningMode,3 UserProfileConfig, EntityMemoryConfig, SessionContextConfig,4)56contacts = Agent(7 id="contacts",8 name="Contacts",9 model=MODEL,10 db=agent_db,11 learning=LearningMachine(12 user_profile=UserProfileConfig(mode=LearningMode.ALWAYS),13 entity_memory=EntityMemoryConfig(14 mode=LearningMode.AGENTIC,15 enable_create_entity=True,16 enable_add_fact=True,17 enable_add_relationship=True,18 enable_add_event=True,19 ),20 session_context=SessionContextConfig(21 mode=LearningMode.ALWAYS,22 enable_planning=True,23 ),24 ),25 enable_agentic_memory=True,26)Three stores, three shapes
| Store | Cardinality | Mode | Example |
|---|---|---|---|
| User profile | One record per user | ALWAYS (auto-extracted) | "Prefers async communication, based in PT, role: PM" |
| Entity memory | Graph of entities + facts + relationships + events | AGENTIC (agent writes) | Sarah Chen → role: VP Eng → company: Acme → "joined 2024-Q4" |
| Session context | Per session | ALWAYS | "User is planning a Q1 offsite, talking through agenda" |
LearningMode.ALWAYS runs an extractor on every turn. LearningMode.AGENTIC gives the agent tools to write when it judges something worth keeping.
Entity memory in detail
The Contacts agent gets four entity-memory tools when configured as above:
| Tool | What it does |
|---|---|
create_entity(name, type) | Adds a new entity (Person, Company, Project, ...) |
add_fact(entity, fact) | Attaches a fact to an entity |
add_relationship(entity_a, entity_b, type) | Links two entities |
add_event(entity, event, when) | Records a time-bound event |
Example chat that builds up the graph:
1User: Sarah Chen joined Acme as VP Engineering last month.2Contacts: → create_entity("Sarah Chen", "Person")3 → add_fact("Sarah Chen", "VP Engineering at Acme")4 → add_relationship("Sarah Chen", "Acme", "employed_by")5 → add_event("Sarah Chen", "joined Acme as VP Eng", "2026-03-15")Next session, "what do I know about Sarah?" returns the full picture without the user re-telling.
User profile
User profile is one record per user_id, updated in place. Whatever the agent learns about you (your role, your preferences, your working style) goes here.
1User: I prefer concise responses, no preamble.2Contacts: → user_profile updated: { communication_style: "concise, direct" }Future responses across any session, any agent that shares the same db, get terser automatically.
Session context
Session context is plan-shaped. "What's this conversation actually about? What does the user want by the end?" The agent uses it to keep multi-turn plans coherent.
1Session goal: Plan Q1 offsite agenda2Open items: pick venue, set theme, draft schedule3Decisions so far: 3 days, 25 people, focus on roadmap alignmentUseful for long, exploratory sessions where the user pivots and the agent needs to stay anchored.
Vanilla agentic memory vs LearningMachine
For most agents, enable_agentic_memory=True is enough: a single bucket of facts that the agent writes to via tools.
LearningMachine is right when the shape of memory matters:
- A relationship graph (Contacts) needs entities and edges, not flat strings.
- A self-improving SQL agent (Dash) needs to separate "validated queries" from "error patterns I've fixed".
When in doubt, start with enable_agentic_memory=True and move to LearningMachine once flat memory feels too lossy.
See it in action
1@Contacts Sarah Chen joined Acme as VP Eng last month2@Contacts what do I know about Sarah?3@Contacts who at Acme have I been talking to?4@Contacts I'm meeting Sarah tomorrow about the platform roadmap5@Contacts later: what was the meeting with Sarah about?Each turn updates the entity graph. The agent uses the graph on every retrieval.
Source: agents/contacts/agent.py, Learning Machine docs