Working Memory with Template
Use template to define the structure of information stored in working memory. Template helps agents extract and persist consistent, structured data 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 template.
Prerequisites
This example uses the openai model. Make sure to add OPENAI_API_KEY to your .env file.
OPENAI_API_KEY=<your-api-key>
And install the following package:
npm install @mastra/libsql
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 template
Enable working memory by setting workingMemory.enabled to true. This allows the agent to remember structured information between interactions.
Providing a template helps define the structure of what should be remembered. In this example, the template organizes tasks into active and completed items using Markdown formatting.
Threads group related messages into conversations. When generateTitle is enabled, each thread is automatically given a descriptive name based on its content.
import { Memory } from "@mastra/memory";
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";
import { LibSQLStore } from "@mastra/libsql";
export const workingMemoryTemplateAgent = new Agent({
name: "working-memory-template-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-template.db",
}),
options: {
workingMemory: {
enabled: true,
template: `
# Todo List
## Active Items
- Task 1: Example task
- Due: Feb 7 2028
- Description: This is an example task
- Status: Not Started
- Estimated Time: 2 hours
## Completed Items
- None yet`,
},
threads: {
generateTitle: true,
},
},
}),
});
Usage examples
This example shows how to interact with an agent that uses a working memory template to manage structured information. The agent updates and persists the todo list across multiple interactions within the same thread.
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.
import "dotenv/config";
import { mastra } from "./mastra";
const threadId = "123";
const resourceId = "user-456";
const agent = mastra.getAgent("workingMemoryTemplateAgent");
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()
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.
import "dotenv/config";
import { mastra } from "./mastra";
const threadId = "123";
const resourceId = "user-456";
const agent = mastra.getAgent("workingMemoryTemplateAgent");
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 output
The output demonstrates how the agent formats and returns the updated todo list using the structure defined in the working memory template.
# 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 object
Working memory stores data in .json format, which would look similar to the below:
{
// ...
"toolInvocations": [
{
// ...
"args": {
"memory": "# Todo List\n## Active Items\n- Task 1: Build a new feature for our app\n - Due: Next Friday\n - Description: Build a new feature for our app\n - Status: Not Started\n - Estimated Time: 2 hours\n\n## Completed Items\n- None yet"
}
}
]
}