# Mastra working memory with tool calls: fixing 'use: tool-call' and messages missing before tool calls

*Disclosure: I'm Mohammed, founder of MemorySync. I drafted this article with AI assistance and reviewed it for accuracy against the official Mastra and MemorySync docs. The install, type checks and a full agent run with a mock model were run (no real LLM call); see the notes at the end of each step.*

If you searched for "Mastra working memory tool-call messages not saved", you probably landed on [mastra-ai/mastra#4221](https://github.com/mastra-ai/mastra/issues/4221): with `workingMemory: { enabled: true, use: 'tool-call' }`, the text an agent wrote before calling a tool never reached the database. Turning working memory off made the messages come back.

That issue was filed against `@mastra/memory` 0.3.x and `@mastra/core` 0.9.x. A maintainer merged a fix in May 2025 and closed it. Today the bigger change is that the `use` option is gone altogether. Below is what that means for an old config, the current setup, and how to confirm nothing goes missing. Mastra behaviour comes from the [Mastra working memory docs](https://mastra.ai/docs/memory/working-memory) and the package type definitions. I'm building MemorySync, a hosted memory layer, and it gets one short section at the end (if you want it with Mastra, see the [MemorySync Mastra guide](https://docs.memorysync.io/guides/mastra?utm_source=hashnode&utm_medium=social&utm_campaign=pivot_oct19&utm_content=mastra-working-memory-tool-call-messages-docs)).

## Step 1: Upgrade, then drop the `use` option

Install current versions (Mastra's packages need Node.js 22.13 or later):

```bash
npm install @mastra/core @mastra/memory @mastra/libsql
```

If your config still looks like the one in the issue, it won't load any more. In `@mastra/core` 1.79.0 the type of `use` is `never`, with the note "The `use` option has been removed. Working memory always uses tool-call mode." TypeScript flags it, and plain JavaScript fails when `Memory` is constructed:

```text
Error: The workingMemory.use option has been removed. Working memory always uses tool-call mode.
```

So the fix is to delete the line. Tool-call mode isn't something you opt into now; it's the only mode.

## Step 2: The current working memory config

This is the docs' working memory setup with a custom template and libSQL storage:

```typescript
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
import { LibSQLStore } from '@mastra/libsql'

const memory = new Memory({
  storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db' }),
  options: {
    lastMessages: 20,
    workingMemory: {
      enabled: true, // no `use` option any more
      template: `# User
- Name:
- Preferred seat:`,
    },
  },
})

export const agent = new Agent({
  id: 'assistant',
  name: 'Assistant',
  instructions: 'You are a helpful assistant.',
  model: 'openai/gpt-6.1-sol', // the model string from Mastra's quickstart; use your own
  memory,
})
```

The agent keeps working memory up to date by calling the `updateWorkingMemory` tool. Working memory is resource-scoped by default, so it follows the user across threads. libSQL is one of the adapters the docs list as supporting resource-scoped working memory, along with PostgreSQL, OracleDB, Upstash and MongoDB.

If your agent doesn't update it when you expect, the docs suggest saying how and when to fill the template in the agent's `instructions`.

## Step 3: Call it with a thread and a resource

```typescript
const res = await agent.generate("I'm Sam and I always pick the aisle seat.", {
  memory: { thread: 'thread-1', resource: 'user-42' },
})
```

`resource` is the stable user ID and `thread` is the conversation. Resource-scoped working memory needs `resource` on every call.

## Step 4: Check what was actually saved

This is the check the issue was really about. After a run, read the thread back and look at working memory:

```typescript
const { messages } = await memory.recall({ threadId: 'thread-1', resourceId: 'user-42' })
console.log(messages.map((m) => m.role))

console.log(await memory.getWorkingMemory({ threadId: 'thread-1', resourceId: 'user-42' }))
```

I ran Steps 2 to 4 on current packages with a mock model (no real LLM). The mock wrote "Noted, Sam. Saving that.", called `updateWorkingMemory` and then wrote "Done.". The stored assistant message kept both text parts, including the text written before the tool call. The `updateWorkingMemory` tool call itself wasn't stored as a message part, and working memory held the updated profile. A new process reading `thread-2` for the same `resource` got the same profile back.

So if you're on current versions and something still looks missing, check two things before filing a bug:

- **Are you looking for the tool call itself?** In my run the working memory tool call didn't appear among the stored message parts; the result went into working memory instead. The docs note one exception: with the experimental `useStateSignals: true` option, the tool is registered as `setWorkingMemory` and its tool-call parts are kept in the history.
- **Is the `resource` the same?** A different `resource`, or `scope: 'thread'`, means a separate working memory.

## Step 5 (optional): Read-only working memory for sub-agents

Routing agents and sub-agents can read working memory without changing it:

```typescript
await agent.generate('What do you know about me?', {
  memory: { thread: 'thread-1', resource: 'user-42', options: { readOnly: true } },
})
```

## Where MemorySync fits

Working memory is a single Markdown block (or a JSON object, if you use a schema) that the model rewrites. If you also want individual facts extracted and recalled per user from a hosted service, MemorySync's [Mastra guide](https://docs.memorysync.io/guides/mastra?utm_source=hashnode&utm_medium=social&utm_campaign=pivot_oct19&utm_content=mastra-working-memory-tool-call-messages) recommends running it next to Mastra's `Memory`: `Memory` for the transcript, MemorySync for what the agent should keep knowing. Its processors use `processInput` rather than a per-step hook, so a multi-step tool loop gets the recalled context once per `generate`/`stream` call. You don't need it to fix the issue above.

## Troubleshooting

- **`The workingMemory.use option has been removed`.** Delete `use` from `workingMemory`. See Step 1.
- **Working memory is empty in a new thread.** Pass the same `resource`, and keep the default `scope: 'resource'`. Check that your storage adapter is on the supported list.
- **The agent never updates working memory.** Add update rules to `instructions`, per the docs.
- **Working memory is updated, but the user's message is missing.** Check that `thread` and `resource` are passed on that call.

## Common questions

**Does Mastra still support `workingMemory.use: 'tool-call'`?**
No. The option has been removed, and working memory always uses tool-call mode. Setting it throws when `Memory` is constructed, so delete the line.

**How does a Mastra agent update working memory?**
Through the `updateWorkingMemory` tool. You can also set it yourself when you create or update a thread (`metadata.workingMemory`), or call `memory.updateWorkingMemory(...)` directly ([Mastra working memory docs](https://mastra.ai/docs/memory/working-memory)).

**Is Mastra working memory shared across threads?**
By default, yes. It's resource-scoped, so every thread with the same `resource` sees it. Set `scope: 'thread'` to isolate it per conversation ([Mastra working memory docs](https://mastra.ai/docs/memory/working-memory)).

**Can I use MemorySync with Mastra's working memory?**
Yes. MemorySync's guide recommends running both: Mastra's `Memory` for conversation history and MemorySync's processors for durable per-user facts ([MemorySync Mastra guide](https://docs.memorysync.io/guides/mastra?utm_source=hashnode&utm_medium=social&utm_campaign=pivot_oct19&utm_content=mastra-working-memory-tool-call-messages)).

## Sources

- GitHub issue mastra-ai/mastra#4221 and its comments (fix merged May 2025)
- Mastra docs: mastra.ai/docs/memory/working-memory
- `@mastra/core` 1.79.0 type definitions (`dist/memory/types.d.ts`: `use?: never`) and runtime error message
- npm: @mastra/core 1.79.0, @mastra/memory 1.39.0, @mastra/libsql 1.27.0 (Node >= 22.13.0)
- MemorySync Mastra guide: docs.memorysync.io/guides/mastra

## Try it

If you want to see a memory survive a full page reload before wiring up an agent, the MemorySync playground runs the save, reload and recall loop in your browser: [memorysync.io/try](https://memorysync.io/try?utm_source=hashnode&utm_medium=social&utm_campaign=pivot_oct19&utm_content=mastra-working-memory-tool-call-messages).
