Skip to main content
Mastra v1 is coming in January 2026. Get ahead by starting new projects with the beta or upgrade your existing project today.

Working Memory with Schema

Use Zod schema to define the structure of information stored in working memory. Schema provides type safety and validation for the data that agents extract and persist across conversations.

It works with both streamed responses using .stream() and generated responses using .generate(), and requires a storage provider such as PostgreSQL, LibSQL, or Redis to persist data between sessions.

This example shows how to manage a todo list using a working memory schema.

PrerequisitesDirect link to Prerequisites

This example uses the openai model. Make sure to add OPENAI_API_KEY to your .env file.

.env
OPENAI_API_KEY=<your-api-key>

And install the following package:

npm install @mastra/libsql

Adding memory to an agentDirect link to Adding memory to an agent

To add LibSQL memory to an agent, use the Memory class and pass a storage instance using LibSQLStore. The url can point to a remote location or local file.

Working memory with schemaDirect link to working-memory-with-schema-1

Enable working memory by setting workingMemory.enabled to true. This allows the agent to remember structured information between interactions.

Providing a schema defines the shape in which the agent should remember information. In this example, it separates tasks into active and completed lists.

Threads group related messages into conversations. When generateTitle is enabled, each thread is automatically given a descriptive name based on its content.

src/mastra/agents/example-working-memory-schema-agent.ts
import { Memory } from "@mastra/memory";
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";
import { LibSQLStore } from "@mastra/libsql";
import { z } from "zod";

export const workingMemorySchemaAgent = new Agent({
name: "working-memory-schema-agent",
instructions: `
You are a todo list AI agent.
Always show the current list when starting a conversation.
For each task, include: title with index number, due date, description, status, and estimated time.
Use emojis for each field.
Support subtasks with bullet points.
Ask for time estimates to help with timeboxing.
`,
model: openai("gpt-4o"),
memory: new Memory({
storage: new LibSQLStore({
url: "file:working-memory-schema.db",
}),
options: {
workingMemory: {
enabled: true,
schema: z.object({
items: z.array(
z.object({
title: z.string(),
due: z.string().optional(),
description: z.string(),
status: z.enum(["active", "completed"]).default("active"),
estimatedTime: z.string().optional(),
}),
),
}),
},
threads: {
generateTitle: true,
},
},
}),
});

Usage examplesDirect link to Usage examples

This example shows how to interact with an agent that uses a working memory schema to manage structured information. The agent updates and persists the todo list across multiple interactions within the same thread.

Streaming a response using .stream()Direct link to streaming-a-response-using-stream

This example sends a message to the agent with a new task. The response is streamed and includes the updated todo list.

src/test-working-memory-schema-agent.ts
import "dotenv/config";

import { mastra } from "./mastra";

const threadId = "123";
const resourceId = "user-456";

const agent = mastra.getAgent("workingMemorySchemaAgent");

const stream = await agent.stream(
"Add a task: Build a new feature for our app. It should take about 2 hours and needs to be done by next Friday.",
{
memory: {
thread: threadId,
resource: resourceId,
},
},
);

for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}

Generating a response using .generate()Direct link to generating-a-response-using-generate

This example sends a message to the agent with a new task. The response is returned as a single message and includes the updated todo list.

src/test-working-memory-schema-agent.ts
import "dotenv/config";

import { mastra } from "./mastra";

const threadId = "123";
const resourceId = "user-456";

const agent = mastra.getAgent("workingMemorySchemaAgent");

const response = await agent.generate(
"Add a task: Build a new feature for our app. It should take about 2 hours and needs to be done by next Friday.",
{
memory: {
thread: threadId,
resource: resourceId,
},
},
);

console.log(response.text);

Example outputDirect link to Example output

The output demonstrates how the agent formats and returns the updated todo list using the structure defined by the zod schema.

# Todo List
## Active Items
1. 🛠️ **Task:** Build a new feature for our app
- 📅 **Due:** Next Friday
- 📝 **Description:** Develop and integrate a new feature into the existing application.
- ⏳ **Status:** Not Started
- ⏲️ **Estimated Time:** 2 hours

## Completed Items
- None yet

Example storage objectDirect link to Example storage object

Working memory stores data in .json format, which would look similar to the below:

{
// ...
"toolInvocations": [
{
// ...
"args": {
"memory": {
"items": [
{
"title": "Build a new feature for our app",
"due": "Next Friday",
"description": "",
"status": "active",
"estimatedTime": "2 hours"
}
]
}
}
}
]
}