Memory
Memory in MindedJS allows agents to persist and share data across conversation turns and flow executions. It acts as the agent's working memory, storing context, user information, conversation state, and any other data your agent needs to remember.
What is Memory?
Memory is a structured data store that:
Persists throughout an agent session
Is accessible to all nodes in your flows
Gets automatically merged when updated
Is validated against a schema you define
Can store any JSON-serializable data
Defining Memory Schema
Memory schemas are defined using Zod for type safety and runtime validation.
import { z } from 'zod';
const memorySchema = z.object({
user: z.object({
id: z.string(),
name: z.string(),
preferences: z.object({
language: z.string().default('en'),
timezone: z.string().default('UTC'),
}),
}),
conversation: z.object({
topic: z.string().optional(),
urgency: z.enum(['low', 'medium', 'high']).default('medium'),
}),
order: z
.object({
id: z.string(),
status: z.string(),
total: z.number(),
})
.optional(),
});
type Memory = z.infer<typeof memorySchema>;
Using Memory in Your Agent
1. Configure Memory Schema
import { Agent } from 'mindedjs';
const agent = new Agent({
memorySchema,
config,
tools,
});
2. Initialize Memory
Memory is typically initialized when a trigger event occurs:
import { events } from 'mindedjs';
agent.on(events.TRIGGER_EVENT, async ({ triggerName, triggerBody }) => {
if (triggerName === 'new_order_issue') {
return {
memory: {
user: { id: triggerBody.userId, name: triggerBody.userName },
order: { id: triggerBody.orderId, status: 'pending' },
},
messages: [],
};
}
});
3. Access Memory in Tools
Tools can read from and write to memory:
const updateOrderStatus = {
name: 'updateOrderStatus',
description: 'Updates the order status in memory',
inputSchema: z.object({
newStatus: z.string(),
}),
execute: async ({ input, memory }) => {
// Read from memory
const currentOrder = memory.order;
// Return updated memory (merges with existing)
return {
result: `Order status updated to ${input.newStatus}`,
memory: {
order: {
...currentOrder,
status: input.newStatus,
lastUpdated: new Date().toISOString(),
},
},
};
},
};
Memory Lifecycle
Initialization: Memory starts empty
{}
and gets populated during trigger eventsPersistence: Automatically persisted between conversation turns
Updates: Memory updates are merged when tools return a memory object
Validation: All updates are validated against your schema
// Current memory: { userId: "123", userName: "John" }
// Tool returns: { memory: { userName: "John Doe", email: "[email protected]" } }
// Result: { userId: "123", userName: "John Doe", email: "[email protected]" }
Best Practices
1. Keep It Focused
Only store data relevant to your agent's functionality:
// Good: Focused schema
const memorySchema = z.object({
customerId: z.string(),
currentIssue: z.string(),
resolutionSteps: z.array(z.string()),
});
2. Use Optional Fields and Defaults
const memorySchema = z.object({
userId: z.string(),
orderId: z.string().optional(), // Not all conversations involve orders
conversationState: z.enum(['started', 'in_progress', 'resolved']).default('started'),
attemptCount: z.number().default(0),
});
3. Structure Related Data
Group related fields into objects:
const memorySchema = z.object({
customer: z.object({
id: z.string(),
name: z.string(),
tier: z.enum(['bronze', 'silver', 'gold']),
}),
session: z.object({
startTime: z.string(),
channel: z.enum(['chat', 'email', 'phone']),
}),
});
Common Patterns
User Context Pattern
const memorySchema = z.object({
user: z.object({
id: z.string(),
profile: z.object({
name: z.string(),
email: z.string(),
preferences: z.record(z.unknown()),
}),
}),
});
Conversation State Pattern
const memorySchema = z.object({
conversation: z.object({
phase: z.enum(['greeting', 'information_gathering', 'processing', 'resolution']),
data: z.record(z.unknown()),
}),
});
Memory vs Messages vs History
Memory: Structured data representing current state and context
Messages: Conversation messages (AI, Human, Tool call, System etc.)
History: Flow execution tracking with details about node visits, triggers, and tool calls
// Memory: Current state
{
orderId: "ORD-123",
status: "processing",
customer: { name: "John", tier: "gold" }
}
// Messages: Conversation messages
[
{ role: "human", content: "I need help with my order" },
{ role: "ai", content: "I'd be happy to help!" },
]
All three work together to provide complete context to your agent.
Updating Memory Outside Agent Lifecycle
Sometimes you need to update the agent's memory from outside the normal agent flow - for example, when external events occur or when you need to programmatically modify the session state. MindedJS provides the updateMemory
method for this purpose.
Using updateMemory
The updateMemory
method allows you to update the memory for a specific session:
await agent.updateMemory(sessionId, memoryUpdate);
Parameters
sessionId
(string): The unique identifier of the session whose memory you want to updatememoryUpdate
(Partial): A partial memory object containing only the fields you want to update
Example Usage
// Update a single field
await agent.updateMemory('session-123', {
order: {
status: 'shipped',
trackingNumber: 'TRK-456789'
}
});
// Update multiple fields
await agent.updateMemory('session-123', {
user: {
preferences: {
language: 'es',
timezone: 'America/Mexico_City'
}
},
conversation: {
urgency: 'high'
}
});
Important Notes
Partial Updates: The memory update is merged with existing memory, so you only need to provide the fields you want to change
Validation: Updates are validated against your memory schema - invalid updates will throw an error
Session Must Exist: The session ID must correspond to an active session
Asynchronous: The method returns a Promise, so make sure to await it
Last updated