Lots of great stuff landed this week, especially if you’ve been pushing Mastra into longer conversations or juggling files across multiple storage backends.
Release: @mastra/core@1.3.0
Let's dive in:
Observational Memory Async Buffering (default-on) + New Streaming Events
Observational memory now does more work ahead of time, so your agent stays fast even as threads get long. Async buffering is enabled by default, which means observations and reflections can be pre-computed in the background while the conversation is still comfortably within the context window. When the window fills up, Mastra can activate buffered results instantly instead of blocking on an extra LLM call.
That’s a big deal for chat UIs and production workloads where a sudden “please wait” pause after 30 or 50 turns is a real UX killer. It also gives you cleaner telemetry for understanding what your memory system is doing over time.
Default behavior and configuration
Async buffering ships with sensible defaults:
observation.bufferTokens: 0.2(buffer every 20% ofmessageTokens)observation.bufferActivation: 0.8(activate when the window hits 80%, and retain 20% on activation)reflection.bufferActivation: 0.5(start background reflection halfway to the observation threshold)
If you want to opt out (for example, to simplify behavior in certain environments), you can disable buffering explicitly:
1import { Memory } from "@mastra/memory";
2
3const memory = new Memory({
4 options: {
5 observationalMemory: {
6 model: "google/gemini-2.5-flash",
7 observation: {
8 bufferTokens: false,
9 },
10 },
11 },
12});There are also a couple of important config rules to be aware of:
- If you pass an object config for
observationalMemory, themodelis now required. UseobservationalMemory: trueif you just want the defaults. shareTokenBudget: truecurrently requiresbufferTokens: false(temporary limitation), so you will need to disable buffering if you rely on shared token budgeting.
1// Default model + default buffering behavior
2const agentConfig = {
3 observationalMemory: true,
4};
5
6// Explicit model
7const agentConfig2 = {
8 observationalMemory: {
9 model: "google/gemini-2.5-flash",
10 },
11};
12
13// shareTokenBudget currently requires buffering to be disabled
14const agentConfig3 = {
15 observationalMemory: {
16 model: "google/gemini-2.5-flash",
17 shareTokenBudget: true,
18 observation: { bufferTokens: false },
19 },
20};New structured streaming events for UIs and telemetry
Streaming updates are now more structured and easier to build on:
data-om-statusreplacesdata-om-progresswith a status object that includes active window usage, buffered observation/reflection state, and projected activation impact.- New buffering markers make background work visible to your UI:
data-om-buffering-startdata-om-buffering-enddata-om-buffering-failed
If you’re rendering progress bars, you’ll also appreciate a fix that prevented observational memory progress bars from resetting to zero after agent responses finished. (PR #12934)
Workspace Mounts (CompositeFilesystem)
Workspaces can now mount multiple filesystem providers (S3, GCS, local disk, and more) into a single unified directory tree using CompositeFilesystem. Instead of wiring different tools to different storage backends, you can give your agent one consistent filesystem view and let the mount table decide what provider serves what path.
This is especially useful when your agent workflow naturally spans multiple systems, for example:
- training data living in S3 at
/data - model artifacts in GCS at
/models - scratch space on local disk at
/tmp
Your tools and agents can operate on predictable paths without needing to care whether the backing store is S3, GCS, or something else.
Mounting multiple backends into one workspace
1import { Workspace, CompositeFilesystem } from "@mastra/core/workspace";
2
3// Mount multiple filesystems under one tree
4const composite = new CompositeFilesystem({
5 mounts: {
6 "/data": s3Filesystem,
7 "/models": gcsFilesystem,
8 },
9});
10
11const workspace = new Workspace({
12 filesystem: composite,
13 sandbox: e2bSandbox,
14});Alongside mounts, there’s a lot of “make it safe in production” work:
- New descriptive error types for sandbox and mount failures (for example
SandboxTimeoutError,MountError) - Safer concurrent lifecycle handling in
MastraFilesystemandMastraSandbox - Directory listings can now include mount status and error info, so UIs can show whether each mount is healthy
- Tree formatting now sorts case-insensitively to better match native
treeoutput
Other Notable Updates
- Workspace registry + tool workspace access: Manage multiple workspaces at runtime with
addWorkspace(),getWorkspaceById(), andlistWorkspaces(), and access the active workspace in tools viacontext.workspace(PR #12607) - Native Groq AI SDK integration: Groq models now use
@ai-sdk/groqinstead of OpenAI-compatible fallback mode (PR #12741) - Workflow steps support metadata: Steps can now include serializable
metadatathat survives serialization and shows up in the workflow graph (PR #12861) - Logger propagation fixes:
mastra.setLogger()now updates memory and workflow loggers, and workflow step errors are propagated correctly to the configured logger (PR #12905, PR #12889, PR #12834) - Tool input validation is more forgiving: If a model returns stringified JSON for array/object params, Mastra now detects and parses it before Zod validation (PR #12771)
- Thread persistence fix for stream-legacy: Threads are now saved immediately when created to avoid race conditions where messages failed to persist (PR #12774)
- Nested agent tool approval events surfaced correctly: Parent streams now receive approval and suspend events from sub-agents for proper suspend/resume flows (PR #12732)
- Third-party AI SDK providers unblocked: Models with unknown
specificationVersionvalues are auto-wrapped when possible, and error messages are clearer when not (PR #12856)
That's all for @mastra/core@1.3.0!
Happy building! 🚀
