Memory
Give your persona memory: external history management or advanced MemoryAdapter.
Memory
Memory lets a persona remember past interactions and use those memories to inform future responses.
Two modes
1. Simple mode: External history (recommended)
For most applications, manage conversation history yourself. The chat() method returns updatedHistory which you store and pass back:
import { Molroo } from '@molroo-io/sdk';
import { createOpenAI } from '@ai-sdk/openai';
const molroo = new Molroo({ apiKey: 'mk_live_...' });
const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY! });
const sera = await molroo.createPersona(
{ identity: { name: 'Sera' }, personality: { O: 0.7, C: 0.6, E: 0.8, A: 0.9, N: 0.3, H: 0.8 } },
{ llm: openai('gpt-4o-mini') },
);
// Manage history externally
let history: Message[] = [];
const result1 = await sera.chat('Hi, my name is Alice!', { history });
history = result1.updatedHistory;
const result2 = await sera.chat('What was my name again?', { history });
history = result2.updatedHistory;
// -> The persona knows "Alice" from the conversation historyYou are responsible for persisting history between sessions (e.g., in a database, localStorage, or session store).
Memory is fully optional. Without it, the persona still works -- it just won't recall past conversations beyond what you pass in history.
2. Advanced mode: MemoryAdapter
For advanced features like semantic search, emotion-aware storage, and reflections, implement the MemoryAdapter interface:
import type { MemoryAdapter } from '@molroo-io/sdk';
class MyMemoryAdapter implements MemoryAdapter {
async saveEpisode(episode) { /* save to your DB */ }
async recall(query) { /* query your DB */ }
// Optional methods for richer features:
async semanticRecall(query, options?) { /* vector search */ }
async saveReflection(reflection) { /* save reflection */ }
async getReflections(sourceEntity?) { /* get reflections */ }
}
const sera = await molroo.createPersona('Barista Sera', {
llm: openai('gpt-4o-mini'),
memory: new MyMemoryAdapter(),
});When a MemoryAdapter is configured, the SDK automatically recalls relevant episodes before each chat() call and injects them into the LLM prompt.
How it works
persona.chat('Remember our picnic?', { history })
|
+-- 1. Episodic recall (from MemoryAdapter, if configured)
+-- 2. Semantic recall (if semanticRecall is implemented)
+-- 3. Reflection recall (if getReflections is implemented)
|
v
Memory block injected into system prompt
|
v
LLM generates response with memory + history context
|
v
New episode saved automatically (if MemoryAdapter configured)
Returns PersonaChatResult with updatedHistoryEach chat() call:
- Before the LLM call -- recalls episodic + semantic + reflections in parallel (if MemoryAdapter is configured), injects into prompt along with the provided
history - After the API response -- saves the new episode (fire-and-forget), generates reflections if triggered
- Returns
updatedHistory-- always returned regardless of MemoryAdapter
Reflections
Reflections are natural-language self-observations the persona generates when significant emotional shifts occur. They are stored via the MemoryAdapter and recalled as context.
Example reflections:
- "I need to be more empathetic when others share difficult experiences"
- "I've been more confident in conversations lately"
Reflections are generated automatically by the SDK when the API response includes a reflectionPrompt -- requires a MemoryAdapter with saveReflection and getReflections implemented.
Event memory
Beyond chat, molroo can process game events, simulation actions, and other non-chat stimuli as emotional experiences that become memories.
Use event() to send a non-chat event with a required appraisal vector:
// A goblin attacks the persona
await persona.event('attack', 'goblin attacks with sword', {
from: 'goblin',
appraisal: {
goal_relevance: 0.8,
goal_congruence: -0.9,
expectedness: 0.3,
controllability: 0.4,
agency: -0.6,
norm_compatibility: -0.5,
internal_standards: 0,
adjustment_potential: 0.3,
urgency: 0.9,
},
});
// Later, during chat, the persona recalls the event (if MemoryAdapter is configured)
let history: Message[] = [];
const result = await persona.chat('How are you feeling?', { history });
history = result.updatedHistory;event() requires an appraisal vector because emotion impact is the core value -- without appraisal, the event wouldn't affect the persona's feelings.