# User Profile

## Personal Info

- Name:
- Location:
- Timezone:

## Preferences

- Communication Style: [e.g., Formal, Casual]
- Project Goal:
- Key Deadlines:
  - [Deadline 1]: [Date]
  - [Deadline 2]: [Date]

## Session State

- Last Task Discussed:
- Open Questions:
  - [Question 1]
  - [Question 2]
`,
    },
  },
});
```

## Designing Effective Templates

A well-structured template keeps the information easy for the agent to parse and update. Treat the
template as a short form that you want the assistant to keep up to date.

- **Short, focused labels.** Avoid paragraphs or very long headings. Keep labels brief (for example
  `## Personal Info` or `- Name:`) so updates are easy to read and less likely to be truncated.
- **Use consistent casing.** Inconsistent capitalization (`Timezone:` vs `timezone:`) can cause messy
  updates. Stick to Title Case or lower case for headings and bullet labels.
- **Keep placeholder text simple.** Use hints such as `[e.g., Formal]` or `[Date]` to help the LLM
  fill in the correct spots.
- **Abbreviate very long values.** If you only need a short form, include guidance like
  `- Name: [First name or nickname]` or `- Address (short):` rather than the full legal text.
- **Mention update rules in `instructions`.** You can instruct how and when to fill or clear parts of
  the template directly in the agent's `instructions` field.

### Alternative Template Styles

Use a shorter single block if you only need a few items:

```typescript
const basicMemory = new Memory({
  options: {
    workingMemory: {
      enabled: true,
      template: `User Facts:\n- Name:\n- Favorite Color:\n- Current Topic:`,
    },
  },
});
```

You can also store the key facts in a short paragraph format if you prefer a more narrative style:

```typescript
const paragraphMemory = new Memory({
  options: {
    workingMemory: {
      enabled: true,
      template: `Important Details:\n\nKeep a short paragraph capturing the user's important facts (name, main goal, current task).`,
    },
  },
});
```

## Structured Working Memory

Working memory can also be defined using a structured schema instead of a Markdown template. This allows you to specify the exact fields and types that should be tracked, using a [Zod](https://zod.dev/) schema. When using a schema, the agent will see and update working memory as a JSON object matching your schema.

**Important:** You must specify either `template` or `schema`, but not both.

### Example: Schema-Based Working Memory

```typescript
import { z } from "zod";
import { Memory } from "@mastra/memory";

const userProfileSchema = z.object({
  name: z.string().optional(),
  location: z.string().optional(),
  timezone: z.string().optional(),
  preferences: z
    .object({
      communicationStyle: z.string().optional(),
      projectGoal: z.string().optional(),
      deadlines: z.array(z.string()).optional(),
    })
    .optional(),
});

const memory = new Memory({
  options: {
    workingMemory: {
      enabled: true,
      schema: userProfileSchema,
      // template: ... (do not set)
    },
  },
});
```

When a schema is provided, the agent receives the working memory as a JSON object. For example:

```json
{
  "name": "Sam",
  "location": "Berlin",
  "timezone": "CET",
  "preferences": {
    "communicationStyle": "Formal",
    "projectGoal": "Launch MVP",
    "deadlines": ["2025-07-01"]
  }
}
```

## Choosing Between Template and Schema

- Use a **template** (Markdown) if you want the agent to maintain memory as a free-form text block, such as a user profile or scratchpad.
- Use a **schema** if you need structured, type-safe data that can be validated and programmatically accessed as JSON.
- Only one mode can be active at a time: setting both `template` and `schema` is not supported.

## Example: Multi-step Retention

Below is a simplified view of how the `User Profile` template updates across a short user
conversation:

```nohighlight