April 15, 2026
Server auth now supports mapUserToResourceId, automatically mapping an authenticated user to a resource ID so memory/threads are isolated per user without custom middleware, and client attempts to inject reserved context keys (mastra__resourceId, mastra__threadId) are stripped.
Experiments correctly execute the specified agentVersion, and observability gains first-class entityVersionId/parentEntityVersionId/rootEntityVersionId across spans/metrics/scores/logs/feedback (with storage migrations in ClickHouse/DuckDB/Postgres/MongoDB/LibSQL), plus new experiment query filters and experimentId propagation into agent spans and scorer context.
chatRoute(), handleChatStream(), networkRoute(), and handleNetworkStream() now accept agentVersion (and runtime ?versionId= / ?status= overrides) to route traffic to draft/published or specific version IDs (requires the Editor).
You can enable per-tool strict: true in createTool() for providers that support strict tool calling, and processors can now intercept LLM failures via processAPIError (including a built-in PrefillErrorHandler that retries Anthropic “assistant message prefill” errors automatically).
Agent Browser/Stagehand add lightweight auth persistence via storageState/exportStorageState(), support persistent sessions via profile and custom Chrome via executablePath, and improve cleanup (stale lock files/orphaned Chrome processes) for more reliable runs.
@mastra/voice-sarvam@1.0.0 drops deprecated Sarvam models (bulbul:v1, saarika:v1/v2/flash), defaults shift to bulbul:v3 + speaker shubh, and the TTS request payload changes from inputs[] to text.feat(server): Add mapUserToResourceId callback to auth config for automatic resource ID scoping (#13954)
Auth configs now accept a mapUserToResourceId callback that maps the authenticated user to a resource ID after successful authentication. This enables per-user memory and thread isolation without requiring custom middleware or adapter subclassing.
const mastra = new Mastra({
server: {
auth: {
authenticateToken: async token => verifyToken(token),
mapUserToResourceId: user => user.id,
},
},
});
The callback is called in coreAuthMiddleware after the user is authenticated and set on the request context. The returned value is set as MASTRA_RESOURCE_ID_KEY, which takes precedence over client-provided values for security. Works across all server adapters (Hono, Express, Next.js, etc.).
Added processAPIError hook to the Processor interface for intercepting LLM API call failures before they surface as errors. New built-in PrefillErrorHandler automatically recovers from Anthropic "assistant message prefill" errors by appending a <system-reminder>continue</system-reminder> user message and retrying once. (#14435)
Experiments now run the correct agent version (#15317)
When an experiment specifies agentVersion, the experiment pipeline now resolves and executes against that specific version instead of ignoring it. Previously, the version was stored as metadata but the agent always ran with its current default configuration.
entityVersionId is now a first-class observability dimension
New entityVersionId, parentEntityVersionId, and rootEntityVersionId fields are available on all observability records (spans, metrics, scores, feedback, logs). This enables filtering and grouping OLAP queries by version at any level of the span tree. rootEntityVersionId is particularly useful for aggregating all signals within a versioned agent's trace. This replaces the previous resolvedVersionId attribute which was buried in span attributes and unfilterable.
experimentId propagated to agent spans
Agent spans created during experiment execution now carry the experimentId, enabling trace-to-experiment cross-referencing.
Scorer correlation context
Scorers running in the experiment pipeline now receive full targetCorrelationContext (including experimentId), so scores emitted via observability carry experiment context.
New experiment query filters
listExperiments now supports filtering by targetType, targetId, agentVersion, and status. listExperimentResults now supports filtering by traceId and status.
Added profile and executablePath options to browser config for persistent sessions and custom browser support. Automatically cleans up stale Chrome lock files on browser close. (#15194)
Added (#15313)
Added per-tool strict mode for providers that support strict tool calling. You can now set strict: true on createTool() and Mastra will forward it when preparing tool definitions.
const weatherTool = createTool({
id: 'weather',
description: 'Get weather for a city',
strict: true,
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => ({ city }),
});
Update provider registry and model documentation with latest models and providers (582644c)
Fixed mastra_workspace_list_files silently returning no files when agents passed an empty pattern (e.g. pattern: [] or pattern: ''). Empty and whitespace-only patterns are now treated as "no filter" and return the full listing instead of a dirs-only view or a picomatch error. (#15360)
Fixed harness tool approval, decline, and resume handlers hardcoding requireToolApproval: true. They now follow the harness yolo state like sendMessage already does, so resumed tool calls in yolo mode no longer get unexpectedly re-gated on approval.
Update references to "Mastra Cloud" to "Mastra platform" (#15297)
Fixed symlinked skill paths so workspace skills resolve consistently and allowed path checks work through both symlink and real paths. (#15228)
AgentBrowser with default thread scope now initializes correctly. Previously, calling launch() followed by getPage() would throw "Browser not launched" when no explicit thread ID was provided. (#15285)
fix: ensure listVectorStores always returns a string id (#15239)
Improved structuredOutput.model error messages to surface upstream structuring failures, including plain-object errors, instead of a generic internal agent error. (#15226)
Agent instances can now create lightweight clones that preserve all configuration, so version overrides and tools are isolated without mutating the shared runtime agent. (#15314)
Fixed structuredOutput.model custom gateway resolution by registering the internal structuring agent with the parent Mastra instance. (#15230)
Fixed OpenAI reasoning summary streaming so reasoning summary text is preserved when multiple summaries overlap or finish out of order. (#15225)
Upgraded model router providers to AI SDK v3 spec: OpenAI, Anthropic, Google, xAI, Groq, and Mistral now use the latest v6 SDK packages. Providers built on openai-compatible (Cerebras, DeepInfra, DeepSeek, Perplexity, TogetherAI) remain on v2 spec until their base package is updated. All provider packages (both v5 and v6) bumped to their latest stable patch versions. (#15358)
Fixed 'item missing its reasoning part' error for OpenAI reasoning models (gpt-5-mini, gpt-5.2). The v5 SDK couldn't serialize reasoning items for OpenAI's Responses API, so Mastra stripped them from prompts — but this caused errors in multi-turn conversations with memory enabled. With v3 providers, reasoning items are serialized natively and the stripping workaround has been removed.
Fixed gateway model detection to use duck typing instead of instanceof check, preventing potential failures from cross-package module resolution issues. Propagates gatewayId through the AISDKV5LanguageModel wrapper so duck-type detection works even when models are re-wrapped. (#15168)
Fixed Channels not working on Vercel serverless (and other serverless platforms). Webhook handlers now await initialization on cold starts instead of immediately returning 503, and pass the platform's waitUntil to the Chat SDK so agent processing survives after the HTTP response is sent. See #15300. (#15335)
fix(core): Restore AI SDK v6 provider option typings for vector embeddings (#15306)
The vendored AI SDK v6 declaration build now re-exports ProviderOptions after type bundling renames it to ProviderOptions_2. This fixes TS2724 errors in @mastra/core when vector embeddings import AI SDK v6 provider option types.
storageState option and exportStorageState() method for lightweight auth persistence (cookies and localStorage). Also kills orphaned Chrome child processes on close to prevent zombies. (#15194)Added structured output streaming to the AI SDK UI stream. When an agent produces structured output, the final object is now emitted as a data-structured-output data part in the UI message stream, making it available to frontends via AI SDK UI's custom data handling. (#15237)
Added agent versioning support to chat and network route handlers. You can now pass agentVersion to chatRoute(), handleChatStream(), networkRoute(), and handleNetworkStream() to target a specific agent version by ID or status (draft/published). Route handlers also accept ?versionId=<id> or ?status=draft|published query parameters at request time, which take precedence over static configuration. Requires the Editor to be configured. (#15296)
// Static version on route config
chatRoute({
path: '/chat',
agent: 'weatherAgent',
agentVersion: { status: 'published' },
});
// Programmatic version on handler
const stream = await handleChatStream({
mastra,
agentId: 'weatherAgent',
agentVersion: { versionId: 'ver_abc123' },
params,
});
entityVersionId, parentEntityVersionId, and rootEntityVersionId columns to observability storage tables (spans, metrics, scores, feedback, logs) for filtering and grouping traces by entity version. Added ALTER TABLE migrations for existing databases. Added targetType, targetId, agentVersion, and status filters to listExperiments, and traceId and status filters to listExperimentResults. (#15317)entityVersionId, parentEntityVersionId, and rootEntityVersionId columns to observability storage tables (spans, metrics, scores, feedback, logs) for filtering and grouping traces by entity version. Added ALTER TABLE migrations for existing databases. Added targetType, targetId, agentVersion, and status filters to listExperiments, and traceId and status filters to listExperimentResults. (#15317)Fixed "column does not exist" errors when using experiment review features on databases created before the review pipeline was introduced. Startup now automatically migrates older experiment tables to the latest schema. (#15304)
Added entityVersionId, parentEntityVersionId, and rootEntityVersionId columns to observability storage tables (spans, metrics, scores, feedback, logs) for filtering and grouping traces by entity version. Added ALTER TABLE migrations for existing databases. Added targetType, targetId, agentVersion, and status filters to listExperiments, and traceId and status filters to listExperimentResults. (#15317)
requireToolApproval option to MCP server configuration for requiring human approval before tool execution. Supports both boolean (all tools) and function (dynamic per-tool logic). (#15315)gatewayId through the AISDKV5LanguageModel wrapper so duck-type detection works even when models are re-wrapped. (#15168)entityVersionId, parentEntityVersionId, and rootEntityVersionId columns to observability storage tables (spans, metrics, scores, feedback, logs) for filtering and grouping traces by entity version. Added ALTER TABLE migrations for existing databases. Added targetType, targetId, agentVersion, and status filters to listExperiments, and traceId and status filters to listExperimentResults. (#15317)Fixed double-counting of Anthropic cache tokens in usage metrics (#15316)
Cost estimates now use the latest model pricing rates for more accurate calculations (#15362)
Update references to "Mastra Cloud" to "Mastra platform" (#15297)
Reduced observability overhead for MODEL_STEP spans by storing a lightweight message preview of request bodies. (#15249)
This keeps span previews readable and avoids pulling large payloads into exporter input.
Fixed cost lookup for models with date suffixes. Providers like OpenAI often return model names with date suffixes (e.g., gpt-5.4-mini-2026-03-17) that don't exactly match pricing data entries. The lookup now tries multiple variants including stripping date suffixes and converting dots to dashes. (#15349)
Added entityVersionId, parentEntityVersionId, and rootEntityVersionId to span correlation context, enabling version information to propagate to scores, metrics, logs, and feedback emitted during traced execution. (#15317)
Fixed stack traces for errors reported to Sentry. Exceptions now point to the code that threw the error instead of SentryExporter.handleSpanEnded inside the exporter, so issues in Sentry are actually debuggable. (#15343)
This was caused by two issues, both fixed:
@mastra/sentry passed the error message as a string to Sentry.captureException, which made Sentry synthesize a stack trace from the exporter's call site. It now passes an Error instance with the captured stack attached.@mastra/observability stored the wrapping MastraError's stack on the span, hiding the original error's location. When the MastraError has a cause, the cause's stack is now preserved.Fixes #15337.
Fixed vector similarity queries to leverage HNSW and IVFFlat indexes. When querying without filters on an HNSW or IVFFlat-indexed table, ORDER BY and LIMIT are now placed inside the CTE so PostgreSQL can use the index for faster approximate nearest neighbor searches instead of scanning all rows. (#14574)
Fixed batchInsert and batchUpdate in @mastra/pg to run on a single Postgres transaction connection. (#15312)
This prevents pooled BEGIN/COMMIT/ROLLBACK calls from landing on different connections and leaving idle transactions open during batch writes.
Fixed "column does not exist" errors when using experiment review features on databases created before the review pipeline was introduced. Startup now automatically migrates older experiment tables to the latest schema. (#15304)
Fixed vector operations failing when pgvector extension is installed in a custom schema. The search_path is now set before index creation and vector similarity queries, ensuring operator classes (e.g. vector_cosine_ops) and distance operators (e.g. <=>) resolve correctly regardless of where the extension is installed. Previously, only table creation set the search_path, causing CREATE INDEX and query operations to fail with unresolvable operator errors. (#14526)
Added entityVersionId, parentEntityVersionId, and rootEntityVersionId columns to observability storage tables (spans, metrics, scores, feedback, logs) for filtering and grouping traces by entity version. Added ALTER TABLE migrations for existing databases. Added targetType, targetId, agentVersion, and status filters to listExperiments, and traceId and status filters to listExperimentResults. (#15317)
Added PageLayout and PageHeader compound components for consistent page structure across Mastra Studio, plus a NoDataPageLayout helper for 401/403/empty/error states. (#15243)
List components (AgentsList, WorkflowsList, ToolsList, ProcessorsList, McpServersList, PromptsList, LogsList, ObservabilityTracesList) no longer handle errors or empty states internally — handle those at the page level. If you consume these components directly, move error/empty-state rendering to the parent.
Fix dataset detail tab badges to use total item and experiment counts instead of currently loaded rows. (#14994)
Added EntityList.Pagination sub-component for server-side pagination of EntityList views. Mirrors the existing ItemList.Pagination API. (#15353)
Added ValueLink, ValueWithTooltip, and ValueWithCopyBtn variants to DataKeysAndValues component (#15208)
Refresh Studio Evaluation pages with an updated UI and flattened top-level URLs (/scorers, /datasets, /experiments; /evaluation remains as the overview). @mastra/playground-ui removes EvaluationDashboard and all Evaluation*-prefixed list components, constants, and hooks — use the per-domain replacements (e.g. ScorersList) instead. (#15258)
Fixed DataList to only take as much height as its content needs instead of always stretching to fill available space (#15291)
{messages: [...]} and output objects with text are now properly extracted and formatted. (#15203)--- (#14624)
@mastra/schema-compat: patch
Improved provider schema compatibility for structured outputs and tool calls. Fixed validation for optional, nullable, and defaulted fields, and for ISO date strings returned for date fields.
Fixed stack traces for errors reported to Sentry. Exceptions now point to the code that threw the error instead of SentryExporter.handleSpanEnded inside the exporter, so issues in Sentry are actually debuggable. (#15343)
This was caused by two issues, both fixed:
@mastra/sentry passed the error message as a string to Sentry.captureException, which made Sentry synthesize a stack trace from the exporter's call site. It now passes an Error instance with the captured stack attached.@mastra/observability stored the wrapping MastraError's stack on the span, hiding the original error's location. When the MastraError has a cause, the cause's stack is now preserved.Fixes #15337.
feat(server): Add mapUserToResourceId callback to auth config for automatic resource ID scoping (#13954)
Auth configs now accept a mapUserToResourceId callback that maps the authenticated user to a resource ID after successful authentication. This enables per-user memory and thread isolation without requiring custom middleware or adapter subclassing.
const mastra = new Mastra({
server: {
auth: {
authenticateToken: async token => verifyToken(token),
mapUserToResourceId: user => user.id,
},
},
});
The callback is called in coreAuthMiddleware after the user is authenticated and set on the request context. The returned value is set as MASTRA_RESOURCE_ID_KEY, which takes precedence over client-provided values for security. Works across all server adapters (Hono, Express, Next.js, etc.).
fix(server): Strip reserved context keys from client-provided requestContext (#13954)
Clients could inject mastra__resourceId or mastra__threadId via the request body or query params to impersonate other users' memory/thread access. Reserved keys are now filtered out during request context creation in mergeRequestContext, so only server-side code (auth callbacks, middleware) can set them.
exit_type to prevent restore dialogs, kills orphaned Chrome child processes, and uses CDP events for reliable disconnect detection in both shared and thread scope. (#15194)Added support for Sarvam's current TTS and STT models. Previously the package only supported the now-deprecated bulbul:v1 and saarika:v1/v2/flash models, which Sarvam has retired. (#15204)
What's new:
bulbul:v2, bulbul:v3 (default), and bulbul:v3-beta. bulbul:v3 and bulbul:v3-beta support 39 speakers; bulbul:v2 supports 7 speakers.saarika:v2.5 (default) and saaras:v3. saaras:v3 is a multi-mode model that supports transcribe, translate, verbatim, translit, and codemix via a new mode option.temperature, dict_id, output_audio_codec.speech_sample_rate options: 8000, 16000, 22050, 24000, 32000, 44100, 48000.Breaking changes:
bulbul:v1 TTS model and its speakers (meera, pavithra, maitreyi, arvind, amol, amartya, diya, neel, misha, vian, arjun, maya). Sarvam has retired the underlying API.saarika:v1, saarika:v2, and saarika:flash STT models.bulbul:v3 and the default speaker is shubh. Speakers are not interchangeable between bulbul versions — each has its own catalog.text (single string) instead of inputs (array), matching Sarvam's current API.Migration:
Before:
const voice = new SarvamVoice({
speechModel: { model: 'bulbul:v1', language: 'en-IN' },
speaker: 'meera',
listeningModel: { model: 'saarika:v2' },
});
After:
const voice = new SarvamVoice({
speechModel: { model: 'bulbul:v3', language: 'en-IN' },
speaker: 'shubh',
listeningModel: { model: 'saarika:v2.5' },
});
// Or use saaras:v3 for speech translation:
await voice.listen(audio, { model: 'saaras:v3', mode: 'translate' });
Resolves #15188.
The following packages were updated with dependency changes only:
Fetched April 30, 2026
Highlights Azure Blob Storage workspace + blob store ( ) New adds an Azure Blob Storage provider ( ) and an content-addressable store for s…
Highlights Smarter Model Selection for Observational Memory now lets you route observer and reflector calls to different models based on in…