Highlights
Google Cloud Spanner Storage Adapter (@mastra/spanner@1.0.0)
New first-party storage backend for Google Cloud Spanner (GoogleSQL) covering most Mastra storage domains (memory, workflows, schedules, observability, etc.), including persisting tracing spans for Studio and supporting the local Spanner emulator.
Agent Channels Streaming UX + Tool Rendering Controls (Core + Slack)
Major upgrades to channel adapters: opt-in streaming text deltas, adaptive typing indicators, and a new toolDisplay system (cards/text/timeline/grouped/hidden/function) to control how tool execution renders (including plan/timeline widgets and stable toolCallId correlation).
Client-Side Tool Observability End-to-End (@mastra/client-js + @mastra/observability)
Client-executed tools now show up in server traces via CLIENT_TOOL_CALL spans, with a shared observe helper for child spans/logs inside execute; observability exporters can ingest and forward this client telemetry (including duration metrics labeled toolType: 'client').
Agent Builder Routes Now Auto-Registered in Server Adapters
/agent-builder/* endpoints are now served automatically by any @mastra/server-based adapter (Express/Fastify/Hono/Koa/etc.) without manual wiring, while preserving lazy-loading to keep worker bundles small; new EE permissions gate access.
New Workspace Filesystem Provider via FilesSDK (@mastra/files-sdk@0.2.0)
Adds a unified WorkspaceFilesystem implementation backed by FilesSDK, letting you swap storage providers (S3/R2/GCS/Azure Blob/Vercel Blob/local FS, etc.) by changing the FilesSDK adapter without changing Mastra code.
Breaking Changes
@mastra/slack: removedcards: booleanandformatToolCallfrom Slack provider/channel config; migrate totoolDisplay: 'text'(forcards: false) ortoolDisplayfunction form (forformatToolCall).
Changelog
@mastra/core@1.37.0
Minor Changes
-
Improved agent channels UX: (#16937)
-
Streaming text — opt-in per-adapter
streamingflag (boolean | { updateIntervalMs?: number }) that pushes the agent's text deltas into the platform message progressively via the Chat SDK. -
Adaptive typing indicator — the platform's typing status now reflects what the agent is doing (
is working…at run start,is thinking…during reasoning,is typing…while generating text,is calling {toolName}…while a tool runs,is saving to memory…/is recalling memory…during memory work,is requesting approval for {toolName}…while a tool is suspended), coalesced so the platform API isn't called on every delta. Skipped while a streaming session is open since the widget itself conveys progress. -
toolDisplaymodes — newChannelAdapterConfig.toolDisplaycontrols how tool calls render:'cards'(default) — per-tool running/result cards in rich Block Kit form.'text'— per-tool running/result messages as plain text (replaces the oldcards: falseflag).'timeline'— every tool gets its own task row in a streaming widget with status icons and args.'grouped'— all tools in the run collapse into a single streaming widget; args fold inline into the title and successful results are suppressed for an at-a-glance summary (errors keep their full text).'hidden'— tools run silently; only the typing indicator shows work.- Function form (
ToolDisplayFn) — pass a function(event, ctx) => { kind: 'post', message } | { kind: 'stream', chunk } | undefinedto fully control how every tool event renders.'post'results post a discrete message (closing/reopening the streaming session when needed);'stream'results push atask_update/plan_updateinto the active streaming widget;undefinedskips the event. EveryToolDisplayEventvariant (running/result/error/approval) carries a stabletoolCallIdso user code can correlate events for the same tool invocation (e.g. as theidon a streamedtask_updateso the SDK updates a row in place rather than appending a new one).
'timeline'and'grouped'requirestreaming: trueand fall back to'cards'with a one-time warn if not enabled.'cards'/'text'work under both streaming modes — withstreaming: true, the driver closes the streaming session around each card, posts it, and reopens on the next chunk. Approve/deny prompts always render as a separate Block Kit card regardless of mode, since inline task entries and plain text can't carry interactive buttons.Deprecation (no breaking changes):
ChannelAdapterConfig.cards: booleanandChannelAdapterConfig.formatToolCallare now@deprecatedand surface in IDEs with a strikethrough. Both still work at runtime — they're mutually exclusive withtoolDisplayat the type level. WhentoolDisplayis not set:cards: trueresolves totoolDisplay: 'cards',cards: falseresolves totoolDisplay: 'text', andformatToolCallis shimmed into an equivalentToolDisplayFnthat only fires onresult/errorevents. Migrate at your leisure:cards: false→toolDisplay: 'text', andformatToolCall: ({ toolName, result }) => msg→toolDisplay: event => event.kind === 'result' ? { kind: 'post', message: msg } : undefined. -
typingStatuscustomization — newChannelAdapterConfig.typingStatus(boolean | (chunk, ctx) => string | false, defaulttrue). Set tofalseto suppress all typing indicators (useful when a live streaming widget already conveys progress), or pass a function to set custom copy per chunk. Compose with the exporteddefaultTypingStatushelper to fall back to built-in defaults for chunks you don't handle. -
Signal-aware message boundaries — when a
data-user-messagesignal echoes into the stream mid-reply, any in-flight text is flushed first so the agent's response renders as a new message after the user's signal instead of streaming into the prior reply. -
Stronger stay-silent prompt — the channel input processor's non-DM system message now explicitly calls out anti-patterns (bracketed status notes, "Got it"/"Noted" acknowledgments, apologizing for silence) and points the model at
add_reactionfor silent acknowledgments. Empty responses are framed as a first-class action rather than a fallback. -
Slack DM thread routing — each Slack thread (including top-level DMs) now maps to its own Mastra thread. Previously, replies and tool-approval clicks in a top-level DM could be routed into a sub-thread keyed by the bot's last message, causing follow-ups to thread under that message and tool approvals to fail to find the pending approval.
-
Parallel same-tool approval — fixed a bug where two parallel calls to the same tool with
requireApproval: trueclobbered each other's pending entry, so only the most recent could be approved. -
Tool error rendering — failing tools now emit a closing task update in
'timeline'/'grouped'modes (previously the row stayedin_progressand rendered as ⚠ at session close) and edit their card in'cards'/'hidden'modes. The error text is inlined into the taskdetails(with a ⚠ glyph) while the task itself staysstatus: 'complete'so a single tool failure doesn't flip the overall plan header to an error state. -
Observational-memory lifecycle in streaming widgets —
data-om-buffering-*anddata-om-activationchunks are routed into the active streaming session in'timeline'/'grouped'modes as their own task rows (e.g.Saved to memory (10x)with12.4k → 1.2k tokens), so memory work is visible alongside tool calls. Consecutive observation activations within a session coalesce into a singleRecalled memory (Nx)row with running totals instead of stacking — reflection runs often fire several activations back-to-back. The plan title is set toUpdating memoryon the first OM event so memory-only runs don't show the chat-SDK default ofThinking completed. OM buffering runs async in the background, so any still-in_progressOM task is optimistically markedcompletewhen the streaming session closes — without this, the chat-SDK plan widget would flip the "Saving to memory…" row to an error icon when the stream ends before the buffer flush resolves. In non-plan modes ('cards'/'text'/'hidden'/ToolDisplayFn) OM events are skipped entirely — a phantom Plan widget showing only memory rows would be inconsistent with the mode contract. Approvalplan_update/task_updaterows are also gated by'timeline'/'grouped'for the same reason; non-plan modes now post the approval card directly without flashing a single-row Plan widget that closes immediately after. -
Logger propagation — the Mastra logger is now propagated into
AgentChannelson register so channel-level logs flow through the configured logger. -
Internal refactor (no public API change) —
consumeAgentStreamnow dispatches to one of two focused drivers (streaming vs static) instead of switching ontoolDisplayinside a single 700-line loop. Tool-call correlation moved into aToolTrackerhelper and observational-memory rendering into a dedicatedrenderOmTaskUpdatehelper, both shared between drivers. Invalid combinations now warn and downgrade:streaming: false+'timeline'/'grouped'falls back to'cards'.streaming: true+'cards'/'text'is now valid and uses the streaming driver's close/post/reopen lifecycle.
import { Agent } from '@mastra/core/agent'; import { defaultTypingStatus } from '@mastra/core/channels'; import { createDiscordAdapter } from '@mastra/discord'; const agent = new Agent({ name: 'support-bot', channels: { adapters: { discord: { adapter: createDiscordAdapter(), streaming: true, toolDisplay: 'grouped', // 'cards' | 'text' | 'timeline' | 'grouped' | 'hidden' | ToolDisplayFn typingStatus: false, // suppress typing indicator when the widget already shows progress // Custom typing status per chunk; fall back to defaults for everything else. // typingStatus: (chunk, ctx) => { // if (chunk.type === 'tool-call' && chunk.payload.toolName === 'searchDocs') { // return 'is searching docs…'; // } // return defaultTypingStatus(chunk, ctx); // }, // Custom tool rendering via the function form: skip the running message, // post a single line on result. `undefined` skips rendering that event. // toolDisplay: event => { // if (event.kind !== 'result') return undefined; // return { kind: 'post', message: `🛠 ${event.toolName} → ${event.resultText}` }; // }, }, }, }, });
-
-
Client-side tools now appear in your traces when observability is configured. When an agent calls a tool that executes in the browser via
@mastra/client-js, aCLIENT_TOOL_CALLspan is recorded on the server trace so you can see which client tools were invoked, what arguments they received, and how they relate to the rest of the agent run. (#16425)Tools also gain an
observehelper on their execution context for recording child spans and logs from insideexecute:execute: async ({ userId }, { observe }) => { observe.log('info', 'fetching user', { userId }); return observe.span('fetch user', () => fetch(`/api/users/${userId}`)); };
-
Added signal delivery option attributes API that conditionally merges branch
attributesbased on whether a signal is delivered to an active agent run (ifActive.attributes) or an idle run (ifIdle.attributes). This enables contextual signal delivery — for example, tagging user messages aswhile-activewhen the agent is actively working. (#16923) -
Add per-provider capability files and
automode forobserveAttachments(#16922)- Generate per-provider capability files (e.g.
capabilities/openai.json) alongside the model router registry, sourced from models.dev API - Export
modelSupportsAttachments(modelRouterId)from@mastra/core/llmto check whether a model supports image/file attachments - Extend
observeAttachmentsconfig to accept'auto'in addition toboolean | string[] - When set to
'auto', the observer resolves the model (including function-based models) and checks the capability registry before deciding to forward or drop attachment parts
- Generate per-provider capability files (e.g.
Patch Changes
-
Update provider registry and model documentation with latest models and providers (
cfa2e3a) -
Added sub-agent token usage to
onDelegationCompleteresults, so apps can track per-sub-agent token costs (#15825) -
Fixed thread subscription streams stalling or deadlocking when multiple consumers observe the same active run. Thread streams are now multicast to subscribers so each subscriber receives the run without competing for the underlying stream, and follow-up messages can continue while a subscription is active. (#16946)
-
Connecting or disconnecting an agent through a channel (e.g. Slack) now requires the same write permission as editing the underlying stored agent. The check runs on
POST /channels/:platform/connectandPOST /channels/:platform/:agentId/disconnectwhenever the target agent has a record in the stored-agents store. Callers without write access receive a404 Not found, matching the behavior of the stored-agent edit routes. Agents defined in code (no stored-agents record) are unaffected and continue to honor only the route's existing auth requirement. (#16949)The caller must either own the stored agent, have admin bypass, or hold
agents:edit(or a scopedagents:edit:<agentId>).POST /channels/slack/connect Authorization: Bearer <token-with-agents:edit> Content-Type: application/json { "agentId": "support-bot" }
POST /channels/slack/support-bot/disconnect Authorization: Bearer <token-with-agents:edit>
@mastra/coreis bumped as a patch to ship the regenerated permission definitions that back this check. -
Made provider capabilities loading lazy instead of bulk-syncing on every registry access. Removed subscription setup from harness switchMode() — subscriptions are now lazily ensured at send time. Added 10s TTL cache and invalidation method for listAvailableModels(). (#17008)
-
Preserve
thiswhen resolving permissions for the "View as role" picker inbuildCapabilities. Class-based RBAC providers (e.g.@mastra/auth-workos) read state fromthisinsidegetPermissionsForRole, but the method was being detached to a bare variable before invocation. This caused aTypeError: Cannot read properties of undefined (reading 'options')to be logged on every authenticated request and silently emptied the available roles list. The error was swallowed by a surrounding try/catch so admins saw an empty picker instead of a crash. (#17112) -
Fixed
workflow.parallel()type-checking for steps that declarerequestContextSchema. (#16989)
Steps with matching request context now type-check correctly.
Steps with mismatched request context still fail with a type error.
Fixes #16975. -
Fixed split-brain broker election race in UnixSocketPubSub. When a broker process dies and multiple clients recover concurrently, an exclusive lock file now serializes the election so exactly one process becomes the new broker. (#16955)
-
Fixed a crash that could occur when background execution is enabled for tools with Zod v3 input schemas. (#16915)
Tools with Zod v3, Zod v4, and JSON Schema input definitions now work consistently with background execution.
-
Fixed processor workflow steps so
sendSignalis available when processors inject Agent signals, and updated Observational Memory temporal gap markers to use Agent signals. (#16927) -
Fixed an issue where thread subscriptions could appear idle after a run finished. Subsequent runs now stream promptly, and post-finish signals correctly start from an idle state. (#16928)
-
Fixed agent responses being ordered before the user message that triggered them in long conversations. This prevents duplicate tool calls in the next step. This regression started in 1.35.0. Fixes #16893. (#16913)
-
Fixed agent crash when
backgroundTasks.enabled: trueis combined with a tool whoseinputSchemauses Zod's.refine()or.superRefine(). On Zod v4, such agents threwCannot overwrite keys on object schemas containing refinementson repeated invocations and became unusable. Tools with refined input schemas now work with background tasks. (#16966) -
UnixSocketPubSub: skip serialization when broker has 0 remote clients, lazily build ServerFrame only when a subscribed client exists, and automatically elect a new broker with resubscription when the active broker disconnects. (#16939)
-
Fixed v1 agent tools to preserve legacy tool result output while still allowing usage data in delegation hooks. (#17070)
-
Fixed thread stream subscriptions so streamed agent responses are saved to memory while still supporting multiple subscribers. (#16982)
-
Gate stored-workspace handlers by author. Previously any authenticated caller within a tenant could list, read, update, or delete another user's workspace. (#16974)
Behavior changes
POST /stored/workspaces— server stampsauthorIdfrom the authenticated caller; any body-providedauthorIdis ignored.GET /stored/workspaces/:id,PATCH /stored/workspaces/:id,DELETE /stored/workspaces/:id— return404 Not foundunless the caller is the owner, an admin (*), or holdsstored-workspaces:<action>[:<id>].GET /stored/workspaces— filters to the caller's own rows plus legacy unowned records; admins still see every row.- Legacy workspaces created before this change (no
authorId) remain accessible to any authenticated caller for backwards compatibility.
Example
// Client POST body — authorId is ignored if sent await fetch('/stored/workspaces', { method: 'POST', body: JSON.stringify({ name: 'My workspace', authorId: 'someone-else' }), }); // Stored row — authorId is stamped from the authenticated caller // { // id: 'my-workspace', // name: 'My workspace', // authorId: 'user_abc123', // from requestContext, NOT from body // ... // }
Migration
- Existing rows with
authorId === null/undefinedremain readable/writable by any authenticated caller — no action required for backwards compatibility. - To lock down legacy rows, backfill
authorIddirectly in theworkspacestable with the original creator's id. - For service accounts or tooling that need cross-user access, grant
stored-workspaces:*(or per-idstored-workspaces:<action>:<id>) instead of relying on the legacy unowned bypass. - Admins (callers with
*) continue to see and mutate every row regardless ofauthorId.
The
@mastra/corepatch regeneratespermissions.generated.tsto include theauthandinfrastructureresources that already had routes onmain. -
Agent Builder action routes (
/agent-builder/*) are now registered automatically through the standard server route pipeline. Any adapter built on@mastra/server(Hono, Express, Fastify, Koa, etc.) serves the 15/agent-builder/*endpoints without consumers wiring them manually. (#17085)Example
import { MastraClient } from '@mastra/client-js'; const client = new MastraClient({ baseUrl: 'http://localhost:4111' }); // `/agent-builder/*` routes are now reachable out-of-the-box const actions = await client.getAgentBuilderActions(); const action = client.getAgentBuilderAction('generate-agent'); const { runId } = await action.createRun(); const result = await action.startAsync({ inputData: { prompt: 'Build me an agent' } }, runId);
Why
Previously,
AGENT_BUILDER_ROUTESwas a type-only entry in the route registry to keep@mastra/agent-builderout of Cloudflare worker bundles. Consumers had to register the routes themselves to expose Agent Builder functionality. Lazy-loading of@mastra/agent-builderis preserved — handlers still resolve the workflow module on first request via dynamicimport(), so Cloudflare bundles are unaffected.New EE permissions
The following permissions are added to the EE registry. RBAC consumers with strict allowlists must grant these to retain access to builder action routes:
agent-builder:readagent-builder:writeagent-builder:execute
Two legacy stream routes (
STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE,OBSERVE_STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE) are now registered through the standard pipeline as well. -
Fixed a race that could cause an immediate auto-resume of a suspended tool call to fail on some storage backends. Resume now succeeds reliably whether the underlying storage is fast or slow. (#17015)
Fixes #16158.
-
Fixed a race in Harness
sendMessagewhere a phantomagent_end: 'complete'event could fire before any chunks arrived. Subscribers, such as apps running on Cloudflare Workers or Durable Objects, will no longer miss text deltas, messages, or tool events when an agent run completes. (#17024)The cause was
AgentThreadStreamRuntime.subscribeToThread'sactiveRunId()returningnullduring the gap betweensendSignalreserving a runId andregisterRunpopulating the stream record, which madewaitForCurrentThreadStreamIdle()exit immediately andsendMessageemit a syntheticagent_end. The subscriber now treats both a reserved-but-not-yet-registered local run and an active remote run as live, matchingsendSignal's own behavior. -
Suppressed noisy gateway fetch errors when models.dev is unreachable. The registry no longer retries or logs errors on network failure since all model data is already bundled at publish time. (#16984)
@mastra/acp@0.2.0
Minor Changes
-
Added programmatic model selection for ACP agents using the
modeloption. (#17010)You can now set the model directly when creating
AcpAgentorcreateACPTool, instead of relying on environment variables.const codeAgent = new AcpAgent({ id: 'code-agent', description: 'ACP-compatible coding agent', command: 'claude', args: ['--acp'], model: 'claude-sonnet-4-20250514', });
Discover available models with
getAvailableModels()and change the model at runtime withsetModel(). Invalid model IDs throw a descriptive error listing valid options.
Patch Changes
- Removed zod as a required peer dependency. Internal schemas now use plain JSON Schema objects instead of zod runtime. (#16726)
@mastra/client-js@1.21.0
Minor Changes
-
Client-side tool tracing is now built in. When server-side observability is configured, the SDK automatically measures execution duration and ships it back to the server. To add child spans and structured logs from inside your tool's
execute(input, context)function, use theobservehelper on the execution context: (#16425)execute: async ({ userId }, { observe }) => { observe.log('info', 'fetching user', { userId }); return observe.span('fetch user', () => fetch(`/api/users/${userId}`)); };
The
createTool()helper now callsexecute(input, context)so client tools receive the same execution context shape as core tools.
Patch Changes
-
Fixed client-side tools getting stuck in
input-availablestate in React'suseChatmessages. After a client tool finished executing, the React UI never observed a terminaltool-result(ortool-error) chunk for it, so the matchingdynamic-toolpart stayed atstate: 'input-available'indefinitely. The client now emits a synthetic Mastra-shaped terminal chunk into the streamed response right after the client tool resolves or rejects, so the React reducer correctly flips the part tooutput-available(oroutput-error) and renders the tool result. (#16916)Also fixed the client stream parser so final
tool-callchunks are not treated as partial streaming tool calls while preparing client-tool continuation messages. -
Port the
yj/magnificent-marquessfrontend stack ontorain-purpose. (#17105)@mastra/client-js: newToolProviderresource and agetModelPolicyaccessor on the root client. Route types regenerated for the new endpoints.@internal/playground: Agent Builder routes (agents, skills, infrastructure, favorite, library) wired into the router,RoutePermissionGuardandRoleImpersonationProviderapplied to the app shell, new login layout, role-impersonation banner,useRestoreFocushook,StudioIndexRedirecthome, and supporting tweaks across agents, browser view, LLM, and CMS surfaces.
Existing client-tools-on-signals work and the unrouted Agent Builder view/edit pages are preserved.
-
Made optional memory response fields optional in server schemas and generated client types. (#17070)
-
Add
StoredSkill.favorite()andStoredSkill.unfavorite()methods, mirroring the existingStoredAgentfavorite API. Both are idempotent and callPUT/DELETE /api/stored/skills/:id/favorite. (#17101) -
Agent Builder action routes (
/agent-builder/*) are now registered automatically through the standard server route pipeline. Any adapter built on@mastra/server(Hono, Express, Fastify, Koa, etc.) serves the 15/agent-builder/*endpoints without consumers wiring them manually. (#17085)Example
import { MastraClient } from '@mastra/client-js'; const client = new MastraClient({ baseUrl: 'http://localhost:4111' }); // `/agent-builder/*` routes are now reachable out-of-the-box const actions = await client.getAgentBuilderActions(); const action = client.getAgentBuilderAction('generate-agent'); const { runId } = await action.createRun(); const result = await action.startAsync({ inputData: { prompt: 'Build me an agent' } }, runId);
Why
Previously,
AGENT_BUILDER_ROUTESwas a type-only entry in the route registry to keep@mastra/agent-builderout of Cloudflare worker bundles. Consumers had to register the routes themselves to expose Agent Builder functionality. Lazy-loading of@mastra/agent-builderis preserved — handlers still resolve the workflow module on first request via dynamicimport(), so Cloudflare bundles are unaffected.New EE permissions
The following permissions are added to the EE registry. RBAC consumers with strict allowlists must grant these to retain access to builder action routes:
agent-builder:readagent-builder:writeagent-builder:execute
Two legacy stream routes (
STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE,OBSERVE_STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE) are now registered through the standard pipeline as well. -
Improved agent thread subscription resilience by keeping server streams active during idle periods and allowing the JavaScript client to reconnect when subscription streams close or resubscribe requests fail. (#17045)
Enable automatic reconnection with
subscription.processDataStream({ onChunk: chunk => console.log(chunk), reconnect: true }). -
Fixed
clientToolsbeing silently dropped — and never executed — on thread-backed chats. When a chat had athreadId, the ReactuseChathook routed messages through the new agent signals path but did not pass theclientToolsmap into the signal startup flow, so client-side tools were unavailable when the model requested them. (#16540)The signals path now carries
clientToolsand other per-send stream options onsendSignal. When the subscribed stream finishes withtool-calls, the client executes matching local tools with observability support, emits tool result chunks, and posts a continuation with the assistant tool-call messages plus tool-result messages so the run resumes on the same thread with the same per-send options.
@mastra/convex@1.2.0
Minor Changes
-
Convex can now persist channel installations and provider configuration. (#16718)
import { ConvexStore } from '@mastra/convex'; const storage = new ConvexStore({ id: 'app-storage', deploymentUrl: process.env.CONVEX_URL!, adminAuthToken: process.env.CONVEX_ADMIN_KEY!, }); const channels = await storage.getStore('channels'); await channels?.saveInstallation({ id: 'slack-agent-1', platform: 'slack', agentId: 'agent-1', status: 'active', webhookId: 'webhook-1', data: { teamId: 'T123', botUserId: 'U123' }, createdAt: new Date(), updatedAt: new Date(), });
-
Workflow schedules can now be stored in Convex. (#16710)
import { ConvexStore } from '@mastra/convex'; const storage = new ConvexStore({ id: 'app-storage', deploymentUrl: process.env.CONVEX_URL!, adminAuthToken: process.env.CONVEX_ADMIN_KEY!, }); const schedules = await storage.getStore('schedules'); await schedules?.createSchedule({ id: 'daily-summary', target: { type: 'workflow', workflowId: 'summary-workflow' }, cron: '0 9 * * *', status: 'active', nextFireAt: Date.now(), createdAt: Date.now(), updatedAt: Date.now(), });
Patch Changes
- Improved Convex background task reliability with safer lifecycle updates, faster filtering, and smoother upgrades from older storage rows. (#16724)
@mastra/deployer@1.37.0
Patch Changes
- Removed zod as a required peer dependency. Internal schemas now use plain JSON Schema objects instead of zod runtime. (#16726)
@mastra/editor@0.10.0
Minor Changes
-
Ship
EditorAgentBuilderand Agent Builder runtime through the@mastra/editor/eesubpath. (#16948)- Adds
EditorAgentBuilderclass and supporting types under@mastra/editor/ee(dormant unlessMastraEditorConfig.builderis configured). - Wires builder resolution on
MastraEditor:hasEnabledBuilderConfig(),resolveBuilder(),ensureBuilderWorkspaces(), andreconcileBuilderWorkspaces(). - Adds builder defaults plumbing in the agent namespace (
applyBuilderDefaults,BUILDER_BASELINE_DEFAULTSenablingobservationalMemory: trueby default for Builder-created agents). - Adds a defense-in-depth license guard inside
MastraEditor.resolveBuilder()that mirrors the server-startup check inMastraServer.validateAgentBuilderLicense(). Dev environments bypass viaisEEEnabled(); production without a validMASTRA_EE_LICENSEthrows[mastra/auth-ee] Agent Builder is configured but no valid EE license was found. - Bumps the
@mastra/corepeer dependency to>=1.34.0-0 <2.0.0-0to cover the@mastra/core/agent-builder/eeand@mastra/core/auth/eesubpaths consumed by the builder runtime.
Opt-in usage:
import { Mastra } from '@mastra/core'; import { MastraEditor } from '@mastra/editor'; const editor = new MastraEditor({ builder: { enabled: true, configuration: { agent: { models: { default: { provider: 'openai', modelId: 'gpt-4o-mini' } }, }, }, }, }); new Mastra({ storage, editor }); // Later, on demand: const builder = await editor.resolveBuilder(); // `builder` is undefined when the builder is not configured/enabled. // In production it requires a valid MASTRA_EE_LICENSE; dev environments bypass.
This is plumbing — no UI consumer ships in this release.
- Adds
Patch Changes
- Removed zod as a required peer dependency. Internal schemas now use plain JSON Schema objects instead of zod runtime. (#16726)
@mastra/evals@1.2.3
Patch Changes
- Removed zod as a required peer dependency. Internal schemas now use plain JSON Schema objects instead of zod runtime. (#16726)
@mastra/express@1.3.24
Patch Changes
-
Developers can now cancel long-running custom API route work when clients disconnect. Node-based adapters pass abort signals into custom route handlers, clean up response streams correctly, and still surface upstream response body errors. (#16335)
registerApiRoute('/stream', { method: 'GET', handler: async c => { const stream = await agent.stream(prompt, { abortSignal: c.req.raw.signal, }); return stream.toTextStreamResponse(); }, });
-
Improved agent thread subscription resilience by keeping server streams active during idle periods and allowing the JavaScript client to reconnect when subscription streams close or resubscribe requests fail. (#17045)
Enable automatic reconnection with
subscription.processDataStream({ onChunk: chunk => console.log(chunk), reconnect: true }).
@mastra/fastembed@1.1.1
Patch Changes
- Removed zod as a required peer dependency. Internal schemas now use plain JSON Schema objects instead of zod runtime. (#16726)
@mastra/fastify@1.3.24
Patch Changes
-
Developers can now cancel long-running custom API route work when clients disconnect. Node-based adapters pass abort signals into custom route handlers, clean up response streams correctly, and still surface upstream response body errors. (#16335)
registerApiRoute('/stream', { method: 'GET', handler: async c => { const stream = await agent.stream(prompt, { abortSignal: c.req.raw.signal, }); return stream.toTextStreamResponse(); }, });
@mastra/files-sdk@0.2.0
Minor Changes
-
Added @mastra/files-sdk workspace filesystem provider — a unified storage adapter backed by FilesSDK. Supports any FilesSDK adapter (S3, R2, GCS, Azure Blob, Vercel Blob, local filesystem, and more) through a single
FilesSDKFilesystemclass that implements theWorkspaceFilesysteminterface. (#17027)Usage
import { Files } from 'files-sdk'; import { s3 } from 'files-sdk/s3'; import { FilesSDKFilesystem } from '@mastra/files-sdk'; const files = new Files({ adapter: s3({ bucket: 'my-bucket', region: 'us-east-1' }) }); const filesystem = new FilesSDKFilesystem({ files });
Swap adapters without changing code — just replace
s3()withr2(),gcs(),azure(),fs(), etc.
Patch Changes
@mastra/hono@1.4.19
Patch Changes
-
Developers can now cancel long-running custom API route work when clients disconnect. Node-based adapters pass abort signals into custom route handlers, clean up response streams correctly, and still surface upstream response body errors. (#16335)
registerApiRoute('/stream', { method: 'GET', handler: async c => { const stream = await agent.stream(prompt, { abortSignal: c.req.raw.signal, }); return stream.toTextStreamResponse(); }, });
-
Improved agent thread subscription resilience by keeping server streams active during idle periods and allowing the JavaScript client to reconnect when subscription streams close or resubscribe requests fail. (#17045)
Enable automatic reconnection with
subscription.processDataStream({ onChunk: chunk => console.log(chunk), reconnect: true }). -
Fixed SSE streams so browser clients can connect to long-lived subscriptions before the first stream event is available. (#16540)
@mastra/koa@1.5.7
Patch Changes
-
Developers can now cancel long-running custom API route work when clients disconnect. Node-based adapters pass abort signals into custom route handlers, clean up response streams correctly, and still surface upstream response body errors. (#16335)
registerApiRoute('/stream', { method: 'GET', handler: async c => { const stream = await agent.stream(prompt, { abortSignal: c.req.raw.signal, }); return stream.toTextStreamResponse(); }, });
-
Improved agent thread subscription resilience by keeping server streams active during idle periods and allowing the JavaScript client to reconnect when subscription streams close or resubscribe requests fail. (#17045)
Enable automatic reconnection with
subscription.processDataStream({ onChunk: chunk => console.log(chunk), reconnect: true }).
@mastra/mcp@1.8.1
Patch Changes
- Removed zod as a required peer dependency. Internal schemas now use plain JSON Schema objects instead of zod runtime. (#16726)
@mastra/memory@1.20.0
Minor Changes
- Add per-provider capability files and
automode forobserveAttachments(#16922)- Generate per-provider capability files (e.g.
capabilities/openai.json) alongside the model router registry, sourced from models.dev API - Export
modelSupportsAttachments(modelRouterId)from@mastra/core/llmto check whether a model supports image/file attachments - Extend
observeAttachmentsconfig to accept'auto'in addition toboolean | string[] - When set to
'auto', the observer resolves the model (including function-based models) and checks the capability registry before deciding to forward or drop attachment parts
- Generate per-provider capability files (e.g.
Patch Changes
-
Fixed observational memory so in-progress messages are not removed during observation cleanup. (#16913)
-
Removed zod as a required peer dependency. Internal schemas now use plain JSON Schema objects instead of zod runtime. (#16726)
-
Fixed processor workflow steps so
sendSignalis available when processors inject Agent signals, and updated Observational Memory temporal gap markers to use Agent signals. (#16927)
@mastra/observability@1.14.0
Minor Changes
- Support ingesting client-side tool telemetry. Spans, logs, and duration metrics captured by the client SDK during tool execution are forwarded through the observability bus to your existing exporters. Client tool durations are reported via the existing
mastra_tool_duration_msmetric with atoolType: 'client'label to distinguish them from server-side tool durations. (#16425)
Patch Changes
- Paused observability uploads after invalid credentials so exporters stop repeatedly sending unauthorized requests. (#16743)
@mastra/playground-ui@30.0.0
Minor Changes
-
Added a Drawer component — a panel that slides in from any edge of the screen with swipe-to-dismiss gestures. (#16958)
The Drawer can be anchored to any of the four screen edges and supports snap points, nested stacking, controlled state, non-modal mode, swipe-to-open areas, and detached triggers.
import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose, Button, } from '@mastra/playground-ui'; <Drawer side="right"> <DrawerTrigger asChild> <Button>Open</Button> </DrawerTrigger> <DrawerContent> <DrawerHeader> <DrawerTitle>Library</DrawerTitle> <DrawerDescription>A panel that slides in from the right edge.</DrawerDescription> </DrawerHeader> <DrawerFooter> <DrawerClose asChild> <Button variant="outline">Close</Button> </DrawerClose> </DrawerFooter> </DrawerContent> </Drawer>;
-
Added a reusable
HoverCardcomponent (HoverCard,HoverCardTrigger,HoverCardContent) built on Base UI. You can now use these exported components to add hover card interactions anywhere in your UI. (#16919)import { HoverCard, HoverCardTrigger, HoverCardContent } from '@mastra/playground-ui'; <HoverCard> <HoverCardTrigger>Weather Agent</HoverCardTrigger> <HoverCardContent>Answers questions about current conditions and forecasts.</HoverCardContent> </HoverCard>;
Patch Changes
-
Migrated the Switch component to Base UI for smoother animations and consistent behavior. No API changes —
checked,defaultChecked,onCheckedChange, anddisabledwork exactly as before. (#16891) -
Improved the Select component by migrating it to Base UI for more reliable positioning and accessibility. The public API (
Select,SelectTrigger,SelectContent,SelectItem,SelectValue,SelectGroup) is unchanged, so no consumer updates are needed. (#16918) -
Added
DataList.RowStatic, a non-interactive row primitive. It renders a row that looks identical to other list rows but does not respond to clicks and shows no hover/focus state — use it alongsideDataList.RowButton/DataList.RowLinkwhen only some rows are clickable (e.g. error or placeholder entries in an otherwise navigable list). (#16970){ rows.map(row => row.href ? ( <DataList.RowLink key={row.id} to={row.href} LinkComponent={Link}> {row.cells} </DataList.RowLink> ) : ( <DataList.RowStatic key={row.id}>{row.cells}</DataList.RowStatic> ), ); }
-
Added
DataListprimitives and props for building selection-aware, condensed list rows that match the Traces/Logs visual style. (#16820)New cells on
DataList:IdCell— compact mono cell that truncates long IDs to 8 chars.MonoCell— compact mono + truncate text cell (for input previews, JSON summaries, etc.).DateCell— compact date cell rendering "Today" or "MMM dd".TimeCell— compact mono time cell renderingHH:mm:ss.SSSwith the millisecond portion tinted.SelectCell— labelled checkbox cell with a shift-key range-select handler.TopSelectCell— header version withindeterminatesupport for "select all".TopCells— non-interactive header sibling ofRowButton, for hosting top cells beside a leading select cell.
New props on
DataList.RowButtonandDataList.RowLink:flushLeft— drops the default left margin when wrapped beside a leading cell.colStart— places the row starting at a column line (e.g.colStart={2}to leave column 1 for a leading cell).featured— applies the highlighted background to mark the active row.
New props on existing wrappers:
asonDataList.CellandDataList.TopCell— render the cell as any HTML element (e.g.<label>so the whole cell is clickable).hasLeadingCellonDataList.Top— drops default gap and left padding so a leading cell sits flush, mirroring howRow+RowButtoncompose.
Example — selection row with a checkbox in column 1 and an interactive button spanning the rest:
<DataList.Row> <DataList.SelectCell checked={isSelected} onToggle={shiftKey => toggle(id, shiftKey)} /> <DataList.RowButton flushLeft colStart={2} featured={isFeatured} onClick={onRowClick}> <DataList.IdCell id={item.id} /> <DataList.MonoCell>{item.input}</DataList.MonoCell> </DataList.RowButton> </DataList.Row>
Internally the Traces and Logs list views now use the shared primitives — no behavior change for those consumers.
-
Added support for trailing cells in
DataListrows.DataList.RowButtonandDataList.RowLinknow acceptcolEndandflushRight(mirrors of the existingcolStart/flushLeft), so a row can sit beside a non-interactive trailing cell (e.g. an actions column) and stay aligned with the header. Rows wrapped inDataList.Rownow render a full-width separator that extends through the leading and trailing cells.DataList.MonoCellalso gained an optionalheightprop so non-compact lists can use it without forcing compact padding. (#16888)Usage
<DataList.Row> <DataList.RowButton flushLeft flushRight colEnd={-2} onClick={onClick}> {/* main row content */} </DataList.RowButton> <DataList.Cell> {/* trailing actions, e.g. icon buttons */} </DataList.Cell> </DataList.Row> <DataList.MonoCell height="default">long mono text…</DataList.MonoCell>
-
Migrated the Label component off Radix UI. It now renders a native
<label>element with the same props and styling —htmlFor,className, and children behave exactly as before. (#16892) -
Fixed Studio Settings page (and other default-height
PageLayoutpages) clipping their content with no scrollbar on viewports shorter than the form. Users on short laptop screens (under ~991px tall) could not reach the Save button under the Mastra Connection headers form, making it impossible to apply changes. Default-heightPageLayoutpages now grow with their content and scroll through the studio chrome wrapper;height="full"pages (Logs, Traces, Metrics, etc.) are unchanged. (#16999) -
Restyled scrollbars across the studio UI to match the design system — thin, themed thumb on a transparent track — replacing the default OS scrollbars that clashed with dark and light surfaces. (#16918)
-
Exported ContextMenu from the package entry so it can be imported alongside other Base UI primitives. (#17062)
-
Design-system additions to support theming: (#17059)
Avatarnow accepts optionalcolorandtextColorprops for per-instance tinting, and falls back to the initial when the image fails to load.Searchbaraccepts an optionalclassNameto let consumers tune layout without forking.TabListaccepts astyleprop and the active-tab indicator now reads from the--tab-indicator-colorCSS variable, letting parents theme the indicator (e.g. per-agent accent color).stringToColornow accepts anynumberfor thelightnessargument and defaults to90instead of75for a lighter fallback chip.- Global
bodyrule enablesfont-smoothing/-webkit-font-smoothingfor crisper UI text.
-
Removed
EntryListand its sub-components (EntryList.Header,EntryList.Entries,EntryList.Entry,EntryList.EntryText,EntryList.Pagination,EntryList.NoMatch,EntryListSkeleton, etc.) from the public API. All in-repo list views have migrated toDataList, which is the recommended replacement. (#16910)Migration:
// Before import { EntryList, EntryListSkeleton } from '@mastra/playground-ui'; <EntryList> <EntryList.Trim> <EntryList.Header columns={columns} /> <EntryList.Entries> {items.map(item => ( <EntryList.Entry key={item.id} columns={columns} entry={item} onClick={…}> {columns.map(col => <EntryList.EntryText key={col.name}>{item[col.name]}</EntryList.EntryText>)} </EntryList.Entry> ))} </EntryList.Entries> </EntryList.Trim> <EntryList.Pagination …/> </EntryList> // After import { DataList } from '@mastra/playground-ui'; <DataList columns={gridColumns}> <DataList.Top> {columns.map(col => <DataList.TopCell key={col.name}>{col.label}</DataList.TopCell>)} </DataList.Top> {items.map(item => ( <DataList.RowButton key={item.id} onClick={…}> {columns.map(col => <DataList.Cell key={col.name}>{item[col.name]}</DataList.Cell>)} </DataList.RowButton> ))} <DataList.Pagination …/> </DataList>
-
Improved the Checkbox component by migrating it to Base UI. The public API is unchanged —
checked(including the'indeterminate'value),defaultChecked,onCheckedChange, anddisabledall behave as before. (#16905) -
Fixed MetricsDataTable sticky header and column backgrounds to use surface3 token, matching DashboardCard surface (#16828)
-
Improved the RadioGroup component by migrating it to Base UI. The public API (
RadioGroup,RadioGroupItem,value,onValueChange,disabled) is unchanged. Also fixes the radio indicator sizing/centering — the control now stays square and the inner dot is properly centered. (#16904)
@mastra/posthog@1.0.26
Patch Changes
- Fixed negative PostHog cost calculations when cache tokens are present. (#16876)
@mastra/react@0.4.1
Patch Changes
-
Added support for reasoning-start and reasoning-end stream chunks so reasoning blocks are opened and closed with provider metadata preserved. (#17061)
-
Fixed
clientToolsbeing silently dropped — and never executed — on thread-backed chats. When a chat had athreadId, the ReactuseChathook routed messages through the new agent signals path but did not pass theclientToolsmap into the signal startup flow, so client-side tools were unavailable when the model requested them. (#16540)The signals path now carries
clientToolsand other per-send stream options onsendSignal. When the subscribed stream finishes withtool-calls, the client executes matching local tools with observability support, emits tool result chunks, and posts a continuation with the assistant tool-call messages plus tool-result messages so the run resumes on the same thread with the same per-send options.
@mastra/sentry@1.1.0
Minor Changes
-
Added the
gen_ai.conversation.idspan attribute to the Sentry exporter, sourced frommetadata.threadId. Spans from the same chat thread now group together in Sentry's Conversations view (part of AI Agent Monitoring). (#16925)const agent = mastra.getAgent('chat'); // Pass threadId as before — the Sentry exporter now emits it as gen_ai.conversation.id await agent.generate('Hello', { memory: { thread: 'thread-123', resource: 'user-1' }, });
Patch Changes
@mastra/server@1.37.0
Minor Changes
-
Connecting or disconnecting an agent through a channel (e.g. Slack) now requires the same write permission as editing the underlying stored agent. The check runs on
POST /channels/:platform/connectandPOST /channels/:platform/:agentId/disconnectwhenever the target agent has a record in the stored-agents store. Callers without write access receive a404 Not found, matching the behavior of the stored-agent edit routes. Agents defined in code (no stored-agents record) are unaffected and continue to honor only the route's existing auth requirement. (#16949)The caller must either own the stored agent, have admin bypass, or hold
agents:edit(or a scopedagents:edit:<agentId>).POST /channels/slack/connect Authorization: Bearer <token-with-agents:edit> Content-Type: application/json { "agentId": "support-bot" }
POST /channels/slack/support-bot/disconnect Authorization: Bearer <token-with-agents:edit>
@mastra/coreis bumped as a patch to ship the regenerated permission definitions that back this check. -
Gate stored-workspace handlers by author. Previously any authenticated caller within a tenant could list, read, update, or delete another user's workspace. (#16974)
Behavior changes
POST /stored/workspaces— server stampsauthorIdfrom the authenticated caller; any body-providedauthorIdis ignored.GET /stored/workspaces/:id,PATCH /stored/workspaces/:id,DELETE /stored/workspaces/:id— return404 Not foundunless the caller is the owner, an admin (*), or holdsstored-workspaces:<action>[:<id>].GET /stored/workspaces— filters to the caller's own rows plus legacy unowned records; admins still see every row.- Legacy workspaces created before this change (no
authorId) remain accessible to any authenticated caller for backwards compatibility.
Example
// Client POST body — authorId is ignored if sent await fetch('/stored/workspaces', { method: 'POST', body: JSON.stringify({ name: 'My workspace', authorId: 'someone-else' }), }); // Stored row — authorId is stamped from the authenticated caller // { // id: 'my-workspace', // name: 'My workspace', // authorId: 'user_abc123', // from requestContext, NOT from body // ... // }
Migration
- Existing rows with
authorId === null/undefinedremain readable/writable by any authenticated caller — no action required for backwards compatibility. - To lock down legacy rows, backfill
authorIddirectly in theworkspacestable with the original creator's id. - For service accounts or tooling that need cross-user access, grant
stored-workspaces:*(or per-idstored-workspaces:<action>:<id>) instead of relying on the legacy unowned bypass. - Admins (callers with
*) continue to see and mutate every row regardless ofauthorId.
The
@mastra/corepatch regeneratespermissions.generated.tsto include theauthandinfrastructureresources that already had routes onmain. -
Agent Builder action routes (
/agent-builder/*) are now registered automatically through the standard server route pipeline. Any adapter built on@mastra/server(Hono, Express, Fastify, Koa, etc.) serves the 15/agent-builder/*endpoints without consumers wiring them manually. (#17085)Example
import { MastraClient } from '@mastra/client-js'; const client = new MastraClient({ baseUrl: 'http://localhost:4111' }); // `/agent-builder/*` routes are now reachable out-of-the-box const actions = await client.getAgentBuilderActions(); const action = client.getAgentBuilderAction('generate-agent'); const { runId } = await action.createRun(); const result = await action.startAsync({ inputData: { prompt: 'Build me an agent' } }, runId);
Why
Previously,
AGENT_BUILDER_ROUTESwas a type-only entry in the route registry to keep@mastra/agent-builderout of Cloudflare worker bundles. Consumers had to register the routes themselves to expose Agent Builder functionality. Lazy-loading of@mastra/agent-builderis preserved — handlers still resolve the workflow module on first request via dynamicimport(), so Cloudflare bundles are unaffected.New EE permissions
The following permissions are added to the EE registry. RBAC consumers with strict allowlists must grant these to retain access to builder action routes:
agent-builder:readagent-builder:writeagent-builder:execute
Two legacy stream routes (
STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE,OBSERVE_STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE) are now registered through the standard pipeline as well.
Patch Changes
-
Developers can now cancel long-running custom API route work when clients disconnect. Node-based adapters pass abort signals into custom route handlers, clean up response streams correctly, and still surface upstream response body errors. (#16335)
registerApiRoute('/stream', { method: 'GET', handler: async c => { const stream = await agent.stream(prompt, { abortSignal: c.req.raw.signal, }); return stream.toTextStreamResponse(); }, });
-
Made optional memory response fields optional in server schemas and generated client types. (#17070)
-
Improved agent thread subscription resilience by keeping server streams active during idle periods and allowing the JavaScript client to reconnect when subscription streams close or resubscribe requests fail. (#17045)
Enable automatic reconnection with
subscription.processDataStream({ onChunk: chunk => console.log(chunk), reconnect: true }).
@mastra/slack@1.3.0
Minor Changes
-
Improved Slack channel UX: (#16937)
- Flat adapter config —
SlackProvidernow accepts per-adapter options (formatError,streaming,typingStatus,toolDisplay) directly at the top level instead of nesting underadapterConfig. TheadapterConfigfield still works as a deprecated fallback. - Breaking change — the
cards: booleanandformatToolCallfields have been removed fromSlackProviderConfig/SlackAdapterChannelConfig. Migratecards: false→toolDisplay: 'text', andformatToolCall: (info) => msg→toolDisplay: (event) => event.kind === 'result' ? { kind: 'post', message: msg } : undefined. - Opinionated defaults —
SlackProvidernow defaultsstreaming: trueandtoolDisplay: 'grouped'since the grouped "Thinking Steps" widget renders well in Slack's AI Assistant UI. Whenstreaming: falseis explicitly set,toolDisplayfalls back to'cards'since'grouped'requires streaming. Override either per-config to restore other modes. - AI Assistant manifest —
assistant:writeis now part ofDEFAULT_BOT_SCOPESand the generated manifest declares the matchingassistant_viewfeature, so newly generated app manifests support the AI Assistant surface and thread context in DMs. - Slack DM tool-approval routing — clicks on tool-approval cards in Slack DMs now resume the correct Mastra thread.
import { SlackProvider } from '@mastra/slack'; const slack = new SlackProvider({ // Top-level options (preferred): streaming: true, toolDisplay: 'grouped', // or 'cards' | 'text' | 'timeline' | 'hidden' | ToolDisplayFn });
- Flat adapter config —
Patch Changes
@mastra/spanner@1.0.0
Major Changes
-
Added a Google Cloud Spanner storage adapter (
@mastra/spanner) targeting the GoogleSQL dialect. The adapter implements thememory,workflows,scores,backgroundTasks,agents,mcpClients,mcpServers,skills,blobs,promptBlocks,scorerDefinitions,schedules, andobservabilitystorage domains and works with both managed Cloud Spanner instances and the local Spanner emulator. Theschedulesdomain plugs into Mastra's built-inWorkflowSchedulerfor cron-driven workflow triggers, and theobservabilitydomain persists AI tracing spans inmastra_ai_spansto power the Studio traces UI (JSON containment filters compile to per-keyJSON_VALUEequality andEXISTSoverJSON_QUERY_ARRAYsince Spanner has no@>operator). (#15955)import { SpannerStore } from '@mastra/spanner'; const storage = new SpannerStore({ id: 'spanner-storage', projectId: process.env.SPANNER_PROJECT_ID!, instanceId: process.env.SPANNER_INSTANCE_ID!, databaseId: process.env.SPANNER_DATABASE_ID!, });
Patch Changes
@mastra/voice-murf@0.12.1
Patch Changes
- Replaced ky HTTP client with native fetch and built-in retry logic, removing the external dependency (#16960)
Other updated packages
The following packages were updated with dependency changes only:
- @mastra/agent-builder@1.0.38
- @mastra/arize@1.1.2
- @mastra/arthur@0.2.12
- @mastra/braintrust@1.1.2
- @mastra/datadog@1.2.2
- @mastra/deployer-cloud@1.37.0
- @mastra/deployer-cloudflare@1.1.38
- @mastra/deployer-netlify@1.1.14
- @mastra/deployer-vercel@1.1.32
- @mastra/laminar@1.1.2
- @mastra/langfuse@1.3.2
- @mastra/langsmith@1.2.2
- @mastra/longmemeval@1.0.43
- @mastra/mcp-docs-server@1.1.40
- @mastra/nestjs@0.1.8
- @mastra/opencode@0.0.40
- @mastra/otel-bridge@1.1.2
- @mastra/otel-exporter@1.1.2
- @mastra/temporal@0.1.7