github mastra-ai/mastra @mastra/core@1.29.0
April 28, 2026

latest releases: mastracode@0.16.2, mastra@1.7.2, create-mastra@1.7.2...
11 hours ago

Highlights

Azure Blob Storage workspace + blob store (@mastra/azure)

New @mastra/azure adds an Azure Blob Storage WorkspaceFilesystem provider (@mastra/azure/blob) and an AzureBlobStore content-addressable store for skill versioning, with support for connection string, account key, SAS token, DefaultAzureCredential, anonymous auth, prefix namespacing, and read-only mode.

Stream “until idle” to include background task results in the same turn

agent.streamUntilIdle() (plus POST /api/agents/:agentId/stream-until-idle) keeps SSE streaming open until all background tasks finish, then automatically re-invokes the agent so task results are incorporated without needing a second user message; client-js and React useChat now use this flow.

Resume suspended agent streams over HTTP (resume-stream)

Mastra Server adds POST /agents/:agentId/resume-stream and @mastra/client-js adds agent.resumeStream() so apps can resume a previously suspended run with custom data (e.g., approvals/choices) via the client SDK.

Forked subagents for isolated execution on a cloned thread

A new forked flag for HarnessSubagent (and the built-in subagent tool input) runs subagents on a cloned parent thread to preserve prompt-cache prefix while isolating writes; forks inherit parent tools/instructions, flush pending message saves before cloning, and are hidden from Harness.listThreads() by default unless explicitly included.

Cloudflare Workers / V8-isolate support for MCP JSON schema validation

@mastra/mcp adds a jsonSchemaValidator pass-through for MCPClient and MCPServer, enabling validators like CfWorkerJsonSchemaValidator so tools with outputSchema work in environments where Ajv’s new Function(...) compilation is blocked.

Breaking Changes

  • None noted in this changelog.

Changelog

@mastra/core@1.29.0

Minor Changes

  • Added prepareRun and filterRun utilities for scorer input preparation, allowing scorers to filter and transform agent messages before scoring. Scorers can now declare a prepareRun hook or use the filterRun builder to select specific message part types and tool names before scoring runs. (#15642)

    Added getCurrentTraceId() to Harness, which captures the observability trace ID from agent stream responses. This allows callers to correlate feedback and other annotations to the correct trace.

  • Added progressThrottleMs to background task configuration so high-frequency progress output can be coalesced before it reaches pubsub and stream consumers. (#15829)

    const mastra = new Mastra({
      backgroundTasks: {
        enabled: true,
        progressThrottleMs: 500,
      },
    });
  • Added forked subagents: a new forked flag on HarnessSubagent definitions and the built-in subagent tool input. When set, the subagent runs on a clone of the parent thread using the parent agent's instructions and tools, preserving prompt-cache prefix while isolating writes from the main conversation. (#15695)

Patch Changes

  • Stop logging client-disconnect aborts as Error in LLM execution at error level. The catch block in agentic-execution/llm-execution-step.ts now checks for isAbortError(error) first and exits via a debug-level log + the existing onAbort flow before the upstream-error / generic-error branches run. Closes #15844. (#15847)

  • Fixed Studio observability tabs so runtime-injected observability unlocks them. (#15821)

  • Update provider registry and model documentation with latest models and providers (b510d36)

  • Added a stream error retry processor with OpenAI Responses stream error matching. (#15760)

  • Enable ProviderHistoryCompat error processor by default in mastracode (#15730)

  • Fixed AgentChannels.consumeAgentStream silently dropping tripwire chunks, which left channel users (Slack, Discord) with no response when a strategy: "block" processor fired. The chunk is now handled: when retry is false/unset the block reason is posted to the channel (prefixed with the processorId when present); when retry is true the chunk is skipped so the agent's retried output can flow through normally. (#15692)

  • Fixed toModelOutput lookup for dynamically loaded tools via ToolSearchProcessor (#15452)

  • Replace wildcard ./* export with an explicit allowlist of 48 valid subpath exports. The wildcard combined with tsc emitting individual .d.ts files created phantom subpaths (e.g. @mastra/core/auth/ee/defaults) that compiled in TypeScript but crashed at runtime with MODULE_NOT_FOUND. The allowlist approach only exposes subpaths that have actual runtime JS, preventing phantom imports entirely. (#15794)

  • fix(tools): preserve args for programmatic tool calls when merging synthetic tool-call (#15227)

    Fixes an issue where programmatic tool calls (PTC) received empty {} arguments during streaming.

    When a synthetic tool-call was created with empty args, the real tool-call event (containing actual args) was ignored. This change ensures that args from the real tool-call are merged into the synthetic one when missing.

  • Fixed agents forcing temperature: 0 when the user did not explicitly set it. Previously, every agent.stream() / agent.generate() call silently injected temperature: 0 into model settings, which broke models that restrict acceptable temperature values (for example Moonshot Kimi K2.5, which only accepts temperature=1 and rejects any other value with 400 Bad Request). The model provider's own default is now used when the user does not configure a temperature. Users who explicitly set temperature (including temperature: 0 for deterministic output) are unaffected. Fixes #15240. (#15611)

  • Fix forked subagent fork threads starting with empty history. The parent stream's message saves are debounced through SaveQueueManager, so a forked subagent that calls memory.cloneThread mid-stream used to clone from an empty store and lose the parent's user + assistant turn. The tool now drains the parent save queue via a new flushMessages callback on AgentToolExecutionContext before cloning, so forks actually carry the prior conversation. (#15695)

  • The internal <subagent-meta /> tag is no longer appended to subagent tool result content. The tag was previously visible to the parent model in the tool result, which could cause it to be echoed back as literal markup in the parent's assistant text on subsequent turns. Live UIs continue to receive model / duration / tool-call information via the structured subagent_* events; history UIs read the persisted tool_call.args.modelId. parseSubagentMeta is retained so already-persisted threads carrying the legacy tag continue to render cleanly (and the tag is stripped before display in all cases). (#15695)

  • Forked subagents now inherit the parent agent's toolsets (so harness-injected tools like ask_user, submit_plan, and user-configured harness tools remain available inside a fork). The subagent tool entry is kept in the inherited toolset with its id, description, and schemas unchanged so the LLM request prefix stays byte-identical to the parent's and the prompt cache continues to hit; recursive forking is blocked at the runtime layer by replacing only the tool's execute with a stub that returns a "tool unavailable inside a forked subagent" message. Forked runs allow follow-up steps so the model can recover and answer directly if it accidentally calls that stub. Fork threads are tagged with metadata.forkedSubagent: true and metadata.parentThreadId, and Harness.listThreads() hides them by default so they don't surface in user-facing thread pickers; pass includeForkedSubagents: true to opt back in for admin/debug tooling. (#15695)

    Mastra Code now renders forked subagent footers as subagent fork <parent model id>, including persisted history reloaded after the live event metadata is gone.

  • Added missing A2A vNext error variants for protocol 0.3 handling. (#15720)

  • Users now get a clear error when using Observational Memory with agent network. (#15808)

  • Improved skills discovery performance by parallelizing filesystem I/O operations. Discovery of multiple skills, subdirectory scanning, reference file reads, and staleness checks now run concurrently instead of sequentially. Also fixed a bug in CompositeVersionedSkillSource where the root directory stat always returned the current time, causing unnecessary re-discovery on every refresh cycle. (#14360)

  • Fixed tool strict: true being silently dropped when routing through V2 (AI SDK v5) OpenAI providers. V2 providers use a global strictJsonSchema provider option instead of per-tool strict, so Mastra now propagates the intent automatically — when any tool on a call has strict: true, providerOptions.openai.strictJsonSchema is set to true before the request is sent. Explicit user-supplied strictJsonSchema values are respected and never overridden. (#15450)

  • Fixed execute_command timeout handling for models that send numeric values as strings. (#15765)

  • Fixed resourceId not being forwarded to createRun() in the agentic loop, which caused persistWorkflowSnapshot to receive resourceId: undefined. (#15742)

  • Fixed agent loops so truncated model responses stop instead of retrying pending tool calls until max steps. (#15788)

  • Fixed dataset.startExperiment for workflow targets to match runEvals. Previously, scorers running inside a persisted experiment could not access per-step input or output, requestContext configured on the experiment was not forwarded into the workflow run, and direct agent calls inside workflow steps could start detached traces instead of nesting under the workflow step span. Step-level data is now exposed to scorers via run.targetMetadata.stepResults and run.targetMetadata.stepExecutionPath, the workflow's root span ID is available as run.targetSpanId, requestContext propagates into every step, and ambient workflow step tracing is used when creating nested spans. Fixes #15613. (#15792)

  • Fixed requireApproval being silently ignored for tools loaded dynamically via ToolSearchProcessor. The approval gate now fires a tool-call-approval event and pauses execution before running, matching the behaviour of tools registered directly on the agent. (#15782)

  • Fixed AI SDK v5 message rehydration so suspended and approval tool state data parts are restored from persisted message metadata after reload. (#14246)

  • Fixed the TypeScript type for requireApproval on tools so it accepts a function in addition to a boolean. The runtime already supported per-call approval functions (added in #15346), but the type still required boolean, forcing an as any cast. You can now pass a sync or async predicate without a cast — the predicate receives the validated tool input and an optional { requestContext, workspace } second argument. Fixes #15647. (#15783)

  • Added ProviderHistoryCompat error processor that automatically sanitizes tool-call IDs when switching between LLM providers. When a provider rejects tool IDs from another provider's history (e.g. Anthropic enforces ^[a-zA-Z0-9_-]+$), the processor rewrites invalid characters and retries the request. (#15730)

  • Add agent.streamUntilIdle() and default sub-agents to run as background tasks. (#15686)

    streamUntilIdle

    A new agent streaming method that keeps the stream open until all background tasks dispatched during the turn complete. When a task finishes, the agent is re-invoked automatically so the result is processed in the same call — no second user turn required.

    // Before — stream closes once the LLM returns. Background task
    // results are only processed on the next user message.
    const result = await agent.stream('Research quantum computing', { memory });
    for await (const chunk of result.fullStream) {
      /* ... */
    }
    
    // After — stream stays open through the background task completion
    // and the follow-up agent turn; the final answer arrives in the same call.
    const result = await agent.streamUntilIdle('Research quantum computing', { memory });
    for await (const chunk of result.fullStream) {
      /* ... */
    }

@mastra/auth-studio@1.2.2

Patch Changes

  • Authentication now refreshes expired server-side sessions transparently, so recoverable token expiry no longer causes unexpected user sign-outs. Only truly expired sessions (e.g. refresh token dead) return a 401. (#15819)

    Server adapters now forward refreshed session cookies consistently, and auth-studio logs session validation and refresh failures to improve diagnostics.

@mastra/azure@0.2.0

Minor Changes

  • Add @mastra/azure, exporting an Azure Blob Storage WorkspaceFilesystem provider via @mastra/azure/blob with support for connection string, account key, SAS token, DefaultAzureCredential, and anonymous auth, plus prefix namespacing and read-only mode. (#15217)

  • Added AzureBlobStore, a content-addressable blob store backed by Azure Blob Storage for skill versioning. Available alongside the existing AzureBlobFilesystem from @mastra/azure/blob. (#15853)

    import { AzureBlobStore } from '@mastra/azure/blob';
    
    const blobs = new AzureBlobStore({
      container: 'my-skill-blobs',
      connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
    });

    Supports the same authentication methods as AzureBlobFilesystem: connection string, account key, SAS token, DefaultAzureCredential, and anonymous access. A matching azureBlobStoreProvider descriptor is also exported for MastraEditor.

Patch Changes

@mastra/client-js@1.15.0

Minor Changes

  • Added support for resuming suspended agent streams over HTTP with custom data. This adds the POST /agents/:agentId/resume-stream server endpoint and the client SDK agent.resumeStream() method, so apps can continue a suspended agent run through the Mastra client. (#14579)

    Usage example (client SDK):

    const agent = mastraClient.getAgent('my-agent');
    
    // Resume a suspended agent stream with custom data
    const response = await agent.resumeStream(
      { approved: true, selectedOption: 'plan-b' },
      { runId: 'previous-run-id', toolCallId: 'tool-123' },
    );
    
    await response.processDataStream({
      onChunk: chunk => console.log(chunk),
    });
  • Improved the Mastra A2A client to feel closer to the official A2A SDK without introducing a breaking change. (#15720)

    • Added official-style A2A methods such as getAgentCard(), sendMessageStream(), getExtendedAgentCard(), and getTaskPushNotificationConfig().
    • Added typed A2A stream consumption for sendMessageStream() and resubscribeTask().
    • Kept older methods available as deprecated compatibility methods, including getCard() and sendStreamingMessage().

Patch Changes

  • Fixed Studio observability tabs so runtime-injected observability unlocks them. (#15821)

  • Add streamUntilIdle to the agent client, mirroring the new server route. The client keeps the SSE connection open through background task completion and the agent's follow-up turn, and preserves the /stream-until-idle endpoint across client-tool continuations. (#15686)

    const stream = await client.getAgent('my-agent').streamUntilIdle({
      messages: 'Research quantum computing',
    });
    for await (const chunk of stream) {
      /* ... */
    }

@mastra/deployer@1.29.0

Patch Changes

  • Fixed slow or stuck mastra dev startup in large monorepos when workspace packages share internal dependencies. (#12963)

    What changed

    • Mastra now avoids repeating the same dependency analysis work during dev startup when multiple workspace packages depend on the same internal package.
    • This reduces repeated startup work in large monorepos and helps the dev server reach a ready state more reliably.

    Fixes #12843.

@mastra/express@1.3.13

Patch Changes

  • Authentication now refreshes expired server-side sessions transparently, so recoverable token expiry no longer causes unexpected user sign-outs. Only truly expired sessions (e.g. refresh token dead) return a 401. (#15819)

    Server adapters now forward refreshed session cookies consistently, and auth-studio logs session validation and refresh failures to improve diagnostics.

@mastra/fastify@1.3.13

Patch Changes

  • Authentication now refreshes expired server-side sessions transparently, so recoverable token expiry no longer causes unexpected user sign-outs. Only truly expired sessions (e.g. refresh token dead) return a 401. (#15819)

    Server adapters now forward refreshed session cookies consistently, and auth-studio logs session validation and refresh failures to improve diagnostics.

@mastra/hono@1.4.8

Patch Changes

  • Authentication now refreshes expired server-side sessions transparently, so recoverable token expiry no longer causes unexpected user sign-outs. Only truly expired sessions (e.g. refresh token dead) return a 401. (#15819)

    Server adapters now forward refreshed session cookies consistently, and auth-studio logs session validation and refresh failures to improve diagnostics.

  • Refactored Hono adapter's registerCustomApiRoutes() to use the shared buildCustomRouteHandler() from the base class instead of duplicating route/handler resolution logic. Added forwardCustomRouteRequest() to the base class for adapters that already have a raw Request object (avoiding unnecessary request reconstruction). (#15793)

@mastra/koa@1.4.13

Patch Changes

  • Authentication now refreshes expired server-side sessions transparently, so recoverable token expiry no longer causes unexpected user sign-outs. Only truly expired sessions (e.g. refresh token dead) return a 401. (#15819)

    Server adapters now forward refreshed session cookies consistently, and auth-studio logs session validation and refresh failures to improve diagnostics.

@mastra/mcp@1.6.0

Minor Changes

  • Added jsonSchemaValidator pass-through option on MCPClient server entries and MCPServer. Forward this option from @modelcontextprotocol/sdk to opt into a non-default validator. Pass CfWorkerJsonSchemaValidator from @modelcontextprotocol/sdk/validation/cfworker to make tools with outputSchema work in Cloudflare Workers / V8 isolates, where the default Ajv validator's new Function(...) compile path is blocked. (#15866)

    import { MCPClient, MCPServer } from '@mastra/mcp';
    import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/cfworker';
    
    const mcp = new MCPClient({
      servers: {
        upstream: {
          url: new URL('https://example/mcp'),
          jsonSchemaValidator: new CfWorkerJsonSchemaValidator(),
        },
      },
    });
    
    const server = new MCPServer({
      name: 'My Server',
      version: '1.0.0',
      tools: { ... },
      jsonSchemaValidator: new CfWorkerJsonSchemaValidator(),
    });

    Closes #15862.

Patch Changes

@mastra/memory@1.17.2

Patch Changes

  • Fixed the recall tool so message browsing uses the current thread by default and explains when it does. (#15807)

@mastra/observability@1.10.1

Patch Changes

  • Fixed requestContext filtering in span creation to prevent large objects from being serialized into trace data. (#15642)

@mastra/playground-ui@24.0.0

Minor Changes

  • Added shared ThemeProvider, useTheme, and ThemeToggle to unify theme management. (#15838)

    Added

    • ThemeProvider applies the resolved theme class to <html> and persists the choice under the shared mastra-theme localStorage key, with a one-time migration from previously stored preferences.
    • useTheme() works without a <ThemeProvider> ancestor: it returns a read-only fallback that tracks the OS color scheme and exposes a no-op setTheme, so theme-aware leaf components (e.g. CodeDiff, CodeEditor) keep working when embedded standalone.
    • ThemeToggle renders a system/light/dark pill and supports both controlled and uncontrolled usage.

Patch Changes

  • Migrated color tokens to oklch() for perceptually uniform, wide-gamut (P3) ready colors. Light theme neutrals and surfaces no longer have a blue tint (slate → true gray). Dark theme is visually unchanged. (#15713)

  • Added shared Logs components and hooks under @mastra/playground-ui. Consumers can now reuse the Logs page building blocks together with the data hooks and the URL-state / filter-persistence helpers instead of duplicating them per app. (#15723)

  • Added shared metrics components and hooks under @mastra/playground-ui. Consumers can now reuse the metrics dashboard building blocks (KPI, Latency, Scores, Token Usage, Trace Volume, Model Usage Cost cards), their data hooks, and the MetricsProvider / DateRangeSelector primitives instead of duplicating them per app. (#15705)

    New peer dependency: @tanstack/react-query ^5.90.21. Add it alongside your existing playground-ui install.

  • Added shared Traces components and hooks under @mastra/playground-ui. Consumers can now reuse the Traces page building blocks together with the data hooks and the URL-state / filter-persistence helpers instead of duplicating them per app. (#15714)

  • Fixed the logs date filter button height to match other filter controls. (#15801)

@mastra/posthog@1.0.19

Patch Changes

  • Updated posthog-node from v4 to v5 to pick up the latest fixes and LLM analytics improvements. Resolves #15858. (#15867)

@mastra/react@0.2.30

Patch Changes

  • The useChat hook stream now calls the new agent.streamUntilIdle method and the background-task chunks are processed in toUIMessage. (#15686)

@mastra/redis@1.0.2

Patch Changes

  • Fixed Redis package releases to include built files. (#15763)

@mastra/s3@0.5.0

Minor Changes

  • Added AWS credential provider chain support to S3Filesystem and S3BlobStore. You can now pass a credentials option with a credential provider function (e.g. fromNodeProviderChain()) for auto-refreshing credentials on ECS, Lambda, SSO, or AssumeRole deployments. When all credential options are omitted, the AWS SDK default credential provider chain is used automatically instead of falling back to anonymous access. Static accessKeyId/secretAccessKey credentials continue to work as before. (#15437)

    New credentials option

    import { S3Filesystem } from '@mastra/s3';
    import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
    
    // Auto-refreshing credentials (ECS task role, SSO, etc.)
    const fs = new S3Filesystem({
      bucket: 'my-bucket',
      region: 'us-east-1',
      credentials: fromNodeProviderChain(),
    });

    SDK default credential chain (no credentials needed)

    // Credentials discovered from environment automatically
    const fs = new S3Filesystem({
      bucket: 'my-bucket',
      region: 'us-east-1',
    });

    Fixes #14289

Patch Changes

@mastra/server@1.29.0

Minor Changes

  • Added support for resuming suspended agent streams over HTTP with custom data. This adds the POST /agents/:agentId/resume-stream server endpoint and the client SDK agent.resumeStream() method, so apps can continue a suspended agent run through the Mastra client. (#14579)

    Usage example (client SDK):

    const agent = mastraClient.getAgent('my-agent');
    
    // Resume a suspended agent stream with custom data
    const response = await agent.resumeStream(
      { approved: true, selectedOption: 'plan-b' },
      { runId: 'previous-run-id', toolCallId: 'tool-123' },
    );
    
    await response.processDataStream({
      onChunk: chunk => console.log(chunk),
    });

Patch Changes

  • Fixed Studio observability tabs so runtime-injected observability unlocks them. (#15821)

  • Authentication now refreshes expired server-side sessions transparently, so recoverable token expiry no longer causes unexpected user sign-outs. Only truly expired sessions (e.g. refresh token dead) return a 401. (#15819)

    Server adapters now forward refreshed session cookies consistently, and auth-studio logs session validation and refresh failures to improve diagnostics.

  • Updated the A2A server to match the v0.3 protocol shapes and methods. (#15720)

  • Refactored Hono adapter's registerCustomApiRoutes() to use the shared buildCustomRouteHandler() from the base class instead of duplicating route/handler resolution logic. Added forwardCustomRouteRequest() to the base class for adapters that already have a raw Request object (avoiding unnecessary request reconstruction). (#15793)

  • Custom API routes now validate that their paths don't collide with the built-in route prefix. If a custom route path starts with the server's apiPrefix (default /api), a descriptive error is thrown at startup. This prevents custom routes from shadowing built-in Mastra routes (e.g. /api/agents, /api/tools). (#15743)

  • Add POST /api/agents/:agentId/stream-until-idle SSE route that mirrors agent.streamUntilIdle(). The route keeps the SSE stream open through background task completion and the agent's follow-up turn, so clients receive the final answer in a single request. (#15686)

Other updated packages

The following packages were updated with dependency changes only:

Don't miss a new mastra release

NewReleases is sending notifications on new releases.