github mastra-ai/mastra @mastra/core@1.50.0
July 6, 2026

5 hours ago

Highlights

LiveKit Realtime Voice Agents (@mastra/livekit)

New @mastra/livekit package turns Mastra agents (or per-turn workflows) into realtime voice agents with LiveKit handling the full audio loop (WebRTC, VAD, STT/TTS, turn detection, barge-in) while Mastra drives replies, tools, and memory—plus built-in tracing and a Studio “voice mode”.

File-System Routed Mastra Primitives + Zero-Boilerplate Startup

Mastra can now auto-discover and register storage.ts, observability.ts, server.ts, studio.ts, workflows/*.ts, and agent processors from the src/mastra directory during mastra dev/mastra build; @mastra/deployer can also auto-construct a Mastra instance when src/mastra/index.ts is missing, enabling fully file-based projects with no new Mastra(...) entry file.

Unified Schedules API (Heartbeats → Schedules)

Agent “heartbeats” and workflow schedules are unified under mastra.schedules and /api/schedules (client + server), with deprecated/removed heartbeat routes and methods; persisted legacy rows are normalized (target.type: 'heartbeat''agent') so existing schedules keep firing across supported stores.

Workspace Provider Registry in MastraEditor

MastraEditor now supports a workspace-level provider registry: register a single createWorkspace factory that builds complete Workspace instances (filesystem + sandbox), and let stored agents reference them via { type: 'provider', provider, config } for cleaner hydration and multi-environment workspace setups.

Observability Improvements for Serverless + File-Based Config

Observability can now be file-routed via src/mastra/observability.ts, and ObservabilityEntrypoint adds flush() so mastra.observability.flush() works directly in serverless environments (delegating to all instances, similar to shutdown()).

Breaking Changes

  • Heartbeats were renamed to schedules: mastra.heartbeatsmastra.schedules, config heartbeatschedules, type renames (e.g., HeartbeatAgentSchedule), new agent schedule IDs use agent_, and the default fire signal tag is now <schedule>.
  • Server removed /api/heartbeats/* routes in favor of the unified /api/schedules/* API.
  • Client deprecated *Heartbeat() methods in favor of unified schedule methods (to be removed in a future release).

Changelog

@mastra/core@1.50.0

Minor Changes

  • Added file-system-routed observability singleton. Place an observability.ts file in your mastra directory that default-exports an ObservabilityEntrypoint, and it will be auto-discovered and registered when running mastra dev or mastra build. Code-registered observability takes precedence if both are present. (#18887)

    // src/mastra/observability.ts
    import { Observability, MastraStorageExporter } from '@mastra/observability';
    
    export default new Observability({
      configs: { default: { serviceName: 'mastra', exporters: [new MastraStorageExporter()] } },
    });
  • Added file-system routed storage support. A storage.ts file under the mastra directory is now auto-discovered and registered during mastra dev / mastra build. The default export replaces the InMemoryStore fallback. Code-registered storage (passed to new Mastra({storage})) wins on collision. (#18885)

    // src/mastra/storage.ts
    import { LibSQLStore } from '@mastra/libsql';
    
    export default new LibSQLStore({ url: 'file:local.db' });
  • Added file-system-routed workflows support. Workflows placed in workflows/*.ts under the mastra directory are now auto-discovered and registered during mastra dev / mastra build, matching the existing file-based agents convention. Code-registered workflows win on name collisions. (#18883)

    // src/mastra/workflows/onboarding.ts
    import { createWorkflow } from '@mastra/core/workflows';
    
    export default createWorkflow({ id: 'onboarding' /* ...steps */ });
  • Added workspace-level provider registry to MastraEditor. You can now register WorkspaceProvider factories that build complete Workspace instances as a single unit, instead of composing from separate filesystem and sandbox providers. Stored agents can reference a workspace provider via { type: 'provider', provider: 'my-cloud', config: { ... } } and the editor will call the registered factory during agent hydration. (#18781)

    import { MastraEditor } from '@mastra/editor';
    import { Workspace } from '@mastra/core/workspace';
    
    const editor = new MastraEditor({
      workspaces: {
        'my-cloud': {
          id: 'my-cloud',
          name: 'My Cloud Workspace',
          createWorkspace: config =>
            new Workspace({
              id: 'cloud-ws',
              name: 'Cloud WS',
              filesystem: new MyCloudFilesystem(config),
              sandbox: new MyCloudSandbox(config),
            }),
        },
      },
    });
    
    // Stored agent workspace reference using the provider:
    // { type: 'provider', provider: 'my-cloud', config: { region: 'us-east-1' } }
  • models.dev gateway: honor per-model provider overrides (endpoint, request shape, SDK). (10959d5)

    A provider can now serve individual models over a different base URL / request shape than the provider default — e.g. a model served over the OpenAI Responses API while the provider default is chat-completions. The models.dev gateway now reads each model's provider block (api, shape, npm), so resolveLanguageModel routes shape: "responses" models via the OpenAI Responses API and buildUrl prefers a per-model api when present. Providers without per-model overrides are unaffected.

  • Added file-system routed server config singleton. Place a server.ts file in your mastra directory that default-exports a ServerConfig object, and it will be auto-discovered and registered when running mastra dev or mastra build. Code-registered server config takes precedence if both are present. (#18888)

  • Added file-system-routed agent processors. Place input and output processor files under agents/<name>/processors/input/ and agents/<name>/processors/output/. Each file default-exports a processor, and they are auto-discovered and merged with config-defined processors when running mastra dev or mastra build. Config-defined processors run first, and a dynamic (function) inputProcessors/outputProcessors in config.ts takes precedence over discovered files. (#18890)

    src/mastra/agents/support/
    ├── config.ts
    ├── instructions.md
    └── processors/
        ├── input/
        │   └── moderation.ts
        └── output/
            └── redact-pii.ts
    
    // src/mastra/agents/support/processors/input/moderation.ts
    import { ModerationProcessor } from '@mastra/core/processors';
    
    export default new ModerationProcessor({ model: 'openai/gpt-5-nano' });
  • Renamed heartbeats to schedules. Agent heartbeats and workflow schedules are now one unified Schedules API: mastra.schedules manages both. The name "heartbeat" implied a liveness check; these are cron-based agent schedules, so they are now simply called schedules. (#18874)

    Before

    const hb = await mastra.heartbeats.create({
      agentId: 'chef',
      cron: '0 9 * * *',
      prompt: 'Suggest a dish of the day',
    });
    
    await mastra.heartbeats.pause(hb.id);

    After

    // Schedule an agent (was a heartbeat)
    const schedule = await mastra.schedules.create({
      agentId: 'chef',
      cron: '0 9 * * *',
      prompt: 'Suggest a dish of the day',
    });
    
    // Schedule a workflow with the same API
    await mastra.schedules.create({
      workflowId: 'daily-report',
      cron: '0 6 * * *',
      inputData: { region: 'us' },
    });
    
    await mastra.schedules.pause(schedule.id);

    What changed:

    • mastra.heartbeats is now mastra.schedules and also creates, lists, updates, pauses, resumes, runs, and deletes workflow schedules. Results are discriminated by agentId vs workflowId.
    • The Mastra config option heartbeat: { ... } (lifecycle hooks) is now schedules: { ... }, and hook types were renamed (HeartbeatHooksScheduleHooks, HeartbeatPrepareContextSchedulePrepareContext, and so on).
    • New agent schedule ids use the agent_ prefix instead of hb_. Existing hb_ ids keep working.
    • The default signal tag an agent receives on a fire is now <schedule> instead of <heartbeat>.
    • Types renamed: HeartbeatAgentSchedule, CreateHeartbeatInputCreateAgentScheduleInput, HeartbeatScheduleTargetAgentScheduleTarget (persisted target.type is now 'agent' instead of 'heartbeat').

    Existing schedules stored in your database keep working: rows persisted with the old target.type: 'heartbeat' are read as 'agent' automatically and keep firing.

  • Added file-system routed studio config singleton. Place a studio.ts file in your mastra directory that default-exports a StudioConfig object, and it will be auto-discovered and registered when running mastra dev or mastra build. Code-registered studio config takes precedence if both are present. (#18889)

Patch Changes

  • Fix workflow snapshot bloat on agent HITL tool-approval suspensions (#18647). Agent-run snapshots previously grew with thread length × number of historical suspensions because completed steps retained stale suspendPayloads (each embedding a full serialized message list) and duplicated message arrays across step payloads and outputs. Snapshots could balloon to 5MB+ on long threads and hit storage row-size limits. (#18862)

    Agent-loop snapshots are now pruned to minimal resume artifacts before persist: completed steps drop suspension payloads and heavy message/step data, while suspended steps keep their full resume state intact. Snapshot size now stays flat across sequential approvals — O(thread) instead of O(suspensions × thread).

    This also adds an optional pruneSnapshot workflow option (alongside shouldPersistSnapshot) that transforms a snapshot immediately before it is persisted. User-authored workflows are unaffected and persist full snapshots by default.

  • Add unit test coverage for agent utility functions in packages/core/src/agent/utils.ts. (#18896)

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

  • Fixed cross-pod signal routing to dead runIds in multi-pod deployments without sticky sessions (#18614)

  • Fix DurableAgent persisting messages when memory.options.readOnly is true. The durable finish path saved via the save queue directly, bypassing the MessageHistory processor that enforces readOnly in the non-durable path, so messages were written against the caller's explicit "read but don't save" instruction. The durable path now honors readOnly and skips persistence, matching the non-durable agent. Closes #18771. (#18921)

  • Added flush() to ObservabilityEntrypoint so mastra.observability.flush() works directly in serverless environments. (#18873)

    Previously, flush() only existed on individual ObservabilityInstance objects, requiring users to call mastra.observability.getDefaultInstance()?.flush(). The entrypoint-level flush() delegates to all registered instances, matching the existing shutdown() pattern.

    // Before (broken — getObservability() didn't exist, flush() wasn't on the entrypoint)
    const observability = mastra.getObservability();
    await observability.flush();
    
    // After
    await mastra.observability.flush();

    Fixed the serverless flush docs in the observability config guide and Vercel deployment guide to use the correct API.

  • Fixed durable agent parity gaps for structured output, output processors, callbacks, error processors, suspend/resume, and tool lifecycle hooks. Durable agents now support structured output schemas, per-chunk output processor streaming, onStepFinish/onFinish/onError callbacks, error processor retry loops, tool context.writer chunks, and suspend/resume with proper data flow. These fixes bring durable agent scenario test coverage from 43% to over 90%. (#18857)

  • Add unit test coverage for storage utility functions in packages/core/src/storage/utils.ts. (#18895)

  • Fixed listSuspendedRuns() reporting toolCallId: undefined for tool calls parked via suspend(). The id was only stored as the workflow resume label, so discovery dropped it and sendToolApproval({ toolCallId }) could never match the run once it had to be resolved from storage. The suspend payload now carries the id (agentic and durable loops), and discovery recovers it from resume labels for snapshots persisted before this change. (#18940)

  • Fixed agent.generate() and agent.stream() rejecting AI SDK v7 messages under strict TypeScript. AI SDK v7 ModelMessage and UIMessage inputs are now accepted, matching the existing v4-v6 support. (#18956) (#18997)

  • Fixed message hydration to backfill resource IDs when thread IDs are already present. (#18931)

  • Fixed an issue where writes to a shared RequestContext inside tools were lost because the tool received a cloned context instead of the original. Tool writes are now preserved by reusing the shared context instance. (#18872)

  • Hardened several string-parsing code paths against regular-expression denial of service (ReDoS). Path normalization, URL trimming, LLM token stripping, and observation parsing now use linear-time string scanning instead of regexes that could back-track polynomially on adversarial input. No behavior changes. (#18801)

  • Fixed a TypeScript build error caused by the regenerated provider registry adding per-model shape overrides (#18995)

@mastra/agent-browser@0.4.1

Patch Changes

  • Fixed a crash that could occur when using waitUntil with click, press, or select. If the page navigation timed out while the action was still running, the whole Node process could crash instead of the tool returning a normal error result. (#18870)

@mastra/auth-okta@0.1.2

Patch Changes

  • Hardened several string-parsing code paths against regular-expression denial of service (ReDoS). Path normalization, URL trimming, LLM token stripping, and observation parsing now use linear-time string scanning instead of regexes that could back-track polynomially on adversarial input. No behavior changes. (#18801)

@mastra/blaxel@0.5.1

Patch Changes

  • Fixed S3 mount race condition when mounting multiple S3 filesystems concurrently. Each mount now uses a unique per-path credentials file, preventing credentials from being overwritten mid-mount. Also added validation that rejects partial credential pairs with a clear error message. (#14950)

@mastra/client-js@1.31.0

Minor Changes

  • Added unified schedule methods and deprecated heartbeat methods. The client now manages agent schedules (previously heartbeats) and workflow schedules through one set of methods backed by /api/schedules. (#18874)

    Added createSchedule(), updateSchedule(), deleteSchedule(), and runSchedule(), alongside the existing listSchedules(), getSchedule(), pauseSchedule(), resumeSchedule(), and listScheduleTriggers(). ScheduleResponse.target is now a discriminated union of agent and workflow targets.

    // Schedule an agent (was createHeartbeat)
    const schedule = await client.createSchedule({
      agentId: 'chef',
      cron: '0 9 * * *',
      prompt: 'Suggest a dish of the day',
    });
    
    // Schedule a workflow with the same method
    await client.createSchedule({
      workflowId: 'daily-report',
      cron: '0 6 * * *',
    });

    Deprecated listHeartbeats(), getHeartbeat(), createHeartbeat(), updateHeartbeat(), deleteHeartbeat(), pauseHeartbeat(), resumeHeartbeat(), and runHeartbeat(). They now delegate to the schedule methods and will be removed in a future release.

Patch Changes

  • Added workspace-level provider registry to MastraEditor. You can now register WorkspaceProvider factories that build complete Workspace instances as a single unit, instead of composing from separate filesystem and sandbox providers. Stored agents can reference a workspace provider via { type: 'provider', provider: 'my-cloud', config: { ... } } and the editor will call the registered factory during agent hydration. (#18781)

    import { MastraEditor } from '@mastra/editor';
    import { Workspace } from '@mastra/core/workspace';
    
    const editor = new MastraEditor({
      workspaces: {
        'my-cloud': {
          id: 'my-cloud',
          name: 'My Cloud Workspace',
          createWorkspace: config =>
            new Workspace({
              id: 'cloud-ws',
              name: 'Cloud WS',
              filesystem: new MyCloudFilesystem(config),
              sandbox: new MyCloudSandbox(config),
            }),
        },
      },
    });
    
    // Stored agent workspace reference using the provider:
    // { type: 'provider', provider: 'my-cloud', config: { region: 'us-east-1' } }

@mastra/convex@1.3.2

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

  • Schedule rows persisted with the legacy target.type: 'heartbeat' are now normalized to target.type: 'agent' when read, so existing agent schedules keep firing after the heartbeats-to-schedules rename in @mastra/core. (#18874)

@mastra/daytona@0.5.1

Patch Changes

  • Fixed relative paths in executeCommand missing FUSE mounts when cwd is omitted. Commands now default to the first mount path, so relative-path writes land in cloud storage instead of silently going to /home/daytona. (#18984)

@mastra/deployer@1.50.0

Minor Changes

  • Auto-construct a Mastra instance when no index.ts exists. If your src/mastra (#18893)
    directory has file-based primitives but no entry file, mastra dev and
    mastra build now build and run the project without any boilerplate — no
    new Mastra({...}) required.

    src/mastra/
      storage.ts          // export default new LibSQLStore({ url: 'file:./mastra.db' })
      observability.ts    // export default new Observability({ ... })
      server.ts           // export default { port: 4111 }
      studio.ts           // export default { ... }
      agents/weather/     // file-based agent
      workflows/report.ts // export default createWorkflow({ ... })
    
    # No src/mastra/index.ts needed:
    mastra dev

    Projects that already export a mastra instance from index.ts are unaffected.

  • Added file-system-routed observability singleton. Place an observability.ts file in your mastra directory that default-exports an ObservabilityEntrypoint, and it will be auto-discovered and registered when running mastra dev or mastra build. Code-registered observability takes precedence if both are present. (#18887)

    // src/mastra/observability.ts
    import { Observability, MastraStorageExporter } from '@mastra/observability';
    
    export default new Observability({
      configs: { default: { serviceName: 'mastra', exporters: [new MastraStorageExporter()] } },
    });
  • Added file-system routed storage support. A storage.ts file under the mastra directory is now auto-discovered and registered during mastra dev / mastra build. The default export replaces the InMemoryStore fallback. Code-registered storage (passed to new Mastra({storage})) wins on collision. (#18885)

    // src/mastra/storage.ts
    import { LibSQLStore } from '@mastra/libsql';
    
    export default new LibSQLStore({ url: 'file:local.db' });
  • Added file-system-routed workflows support. Workflows placed in workflows/*.ts under the mastra directory are now auto-discovered and registered during mastra dev / mastra build, matching the existing file-based agents convention. Code-registered workflows win on name collisions. (#18883)

    // src/mastra/workflows/onboarding.ts
    import { createWorkflow } from '@mastra/core/workflows';
    
    export default createWorkflow({ id: 'onboarding' /* ...steps */ });
  • Added file-system routed server config singleton. Place a server.ts file in your mastra directory that default-exports a ServerConfig object, and it will be auto-discovered and registered when running mastra dev or mastra build. Code-registered server config takes precedence if both are present. (#18888)

  • Added file-system-routed agent processors. Place input and output processor files under agents/<name>/processors/input/ and agents/<name>/processors/output/. Each file default-exports a processor, and they are auto-discovered and merged with config-defined processors when running mastra dev or mastra build. Config-defined processors run first, and a dynamic (function) inputProcessors/outputProcessors in config.ts takes precedence over discovered files. (#18890)

    src/mastra/agents/support/
    ├── config.ts
    ├── instructions.md
    └── processors/
        ├── input/
        │   └── moderation.ts
        └── output/
            └── redact-pii.ts
    
    // src/mastra/agents/support/processors/input/moderation.ts
    import { ModerationProcessor } from '@mastra/core/processors';
    
    export default new ModerationProcessor({ model: 'openai/gpt-5-nano' });
  • Added file-system routed studio config singleton. Place a studio.ts file in your mastra directory that default-exports a StudioConfig object, and it will be auto-discovered and registered when running mastra dev or mastra build. Code-registered studio config takes precedence if both are present. (#18889)

Patch Changes

  • Fixed production builds so transitive workspace packages are bundled instead of being left as runtime imports. (#18879)

  • Fixed flat markdown skills crashing at runtime when missing a description in frontmatter. Discovery now fails early with a clear error pointing to the file and the Agent Skills spec. (#18935)

  • Fixed deployer output dependency versions for packages that do not export package.json. (#18930)

  • Fixed Studio HTML config injection so platform environment values are escaped before they are embedded in served or deployed index.html files. This keeps organization IDs, project IDs, observability endpoints and telemetry flags intact when they contain quotes, angle brackets, newlines or $ sequences, and exposes escapeStudioHtmlValue from @mastra/deployer/build for the shared injection paths. (#18812)

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

  • Hardened several string-parsing code paths against regular-expression denial of service (ReDoS). Path normalization, URL trimming, LLM token stripping, and observation parsing now use linear-time string scanning instead of regexes that could back-track polynomially on adversarial input. No behavior changes. (#18801)

@mastra/deployer-cloud@1.50.0

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/deployer-cloudflare@1.2.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/deployer-netlify@1.2.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/deployer-vercel@1.2.5

Patch Changes

  • Fixed Studio HTML config injection so platform environment values are escaped before they are embedded in served or deployed index.html files. This keeps organization IDs, project IDs, observability endpoints and telemetry flags intact when they contain quotes, angle brackets, newlines or $ sequences, and exposes escapeStudioHtmlValue from @mastra/deployer/build for the shared injection paths. (#18812)

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/e2b@0.5.1

Patch Changes

  • Fixed S3 mount race condition when mounting multiple S3 filesystems concurrently. Each mount now uses a unique per-path credentials file, preventing credentials from being overwritten mid-mount. Also added validation that rejects partial credential pairs with a clear error message. (#14950)

@mastra/editor@0.13.5

Patch Changes

  • Added workspace-level provider registry to MastraEditor. You can now register WorkspaceProvider factories that build complete Workspace instances as a single unit, instead of composing from separate filesystem and sandbox providers. Stored agents can reference a workspace provider via { type: 'provider', provider: 'my-cloud', config: { ... } } and the editor will call the registered factory during agent hydration. (#18781)

    import { MastraEditor } from '@mastra/editor';
    import { Workspace } from '@mastra/core/workspace';
    
    const editor = new MastraEditor({
      workspaces: {
        'my-cloud': {
          id: 'my-cloud',
          name: 'My Cloud Workspace',
          createWorkspace: config =>
            new Workspace({
              id: 'cloud-ws',
              name: 'Cloud WS',
              filesystem: new MyCloudFilesystem(config),
              sandbox: new MyCloudSandbox(config),
            }),
        },
      },
    });
    
    // Stored agent workspace reference using the provider:
    // { type: 'provider', provider: 'my-cloud', config: { region: 'us-east-1' } }

@mastra/express@1.4.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/fastify@1.4.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/hono@1.5.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/koa@1.6.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/libsql@1.15.1

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

  • Schedule rows persisted with the legacy target.type: 'heartbeat' are now normalized to target.type: 'agent' when read, so existing agent schedules keep firing after the heartbeats-to-schedules rename in @mastra/core. (#18874)

@mastra/livekit@0.2.0

Minor Changes

  • Added @mastra/livekit, a new package that turns Mastra agents into realtime voice agents using LiveKit. (#17896)

    LiveKit's agents framework runs the audio loop — WebRTC transport, voice activity detection, streaming speech-to-text, semantic turn detection, and barge-in — while your Mastra agent generates every reply with its own model, tools, and memory. When a caller interrupts the agent, LiveKit cancels the in-flight stream and Mastra stops generating.

    Build a voice worker

    • createLiveKitWorker() builds a LiveKit worker that answers voice sessions with your Mastra agents; runLiveKitWorker() starts its CLI (dev/start). Both live on the @mastra/livekit/worker entry point.
    • liveKitConnectionRoute() is an API route that mints LiveKit tokens and dispatches the voice agent into a room; dispatchVoiceSession() does the same programmatically for server-initiated sessions like outbound calls. These live on the @mastra/livekit entry point, which is safe to import from Mastra server code — it never loads the LiveKit agents runtime.
    // src/mastra/voice-worker.ts
    import { createLiveKitWorker } from '@mastra/livekit/worker';
    import { mastra } from './index';
    
    export default createLiveKitWorker({
      mastra,
      agent: 'support',
      stt: 'deepgram/nova-3',
      tts: 'cartesia/sonic-3',
      turnDetection: 'multilingual',
    });

    Drive replies with an agent or a workflow

    Each turn's reply can come from a Mastra agent (the default) or a Mastra workflow. With a workflow, LiveKit still owns the audio loop and calls into Mastra once per turn, so the workflow runs to completion each turn (no suspend/resume) — pass the transcript in, stream the reply out.

    • workflow / workflowInput options on createLiveKitWorker() drive replies with a workflow.
    • pipeAgentReplyToWriter(agentStream, writer) streams an agent's reply from inside a workflow step, forwarding both its words and its tool calls (piping only the text would drop the tool calls).
    • generate is an escape hatch to plug in any custom reply generator.
    export default createLiveKitWorker({
      mastra,
      workflow: 'phoneConversation',
      workflowInput: ({ messages }) => ({ turn: messages }),
      replyStep: 'generateResponse',
      stt: 'deepgram/nova-3',
      tts: 'cartesia/sonic-3',
    });

    Run work after each turn and at the end of the call

    • onTurnComplete runs once per turn, right after the reply finishes playing. It runs in the background — the worker never waits for it — so you can save memory, update your CRM, or record analytics without adding any delay for the caller or the next reply. It also runs with result.interrupted: true when the caller talks over the agent.
    • onCallEnd runs once when the call ends. Unlike onTurnComplete, the worker waits for it to finish before exiting, so it's the place for end-of-call work like summarizing the whole conversation into long-term memory once.
    • toolFeedback speaks a short phrase while a tool runs; memoryInstance gives the workflow path a Memory instance to open the call's thread and save the greeting, so the saved conversation is complete — greeting included — like the agent path.

    Both hooks work whether you drive replies with an agent or a workflow.

    createLiveKitWorker({
      mastra,
      agent: 'callCenter',
      onTurnComplete: async ({ result, memory }) => {
        if (memory) await crm.logContact(memory.resource, result.text);
      },
      onCallEnd: async ({ memory }) => {
        // After the caller hangs up: save a lasting summary of the call.
      },
    });

    Built-in observability

    When the Mastra instance has observability configured, each call opens a voice call trace that nests every turn's agent run and adds child spans for LiveKit's speech-to-text, text-to-speech, turn-detection, and LLM latency, closing with a per-model token, character, and audio usage roll-up. On by default; pass observability: false to disable.

    Studio voice mode

    Studio's agent chat gains a voice call mode: when the Mastra server exposes a LiveKit connection route and a voice worker is running, a phone button in the chat composer starts a realtime voice session with the agent. Live captions, agent state (listening, thinking, speaking), and barge-in all surface in the chat, and the conversation lands in the same memory thread as text chat.

    See the LiveKit voice guide for setup.

Patch Changes

@mastra/mcp@1.13.1

Patch Changes

  • Fixed MCP client tools missing output schemas in tool listings. Fixes #18850. (#18854)

    MCP tools that declare an outputSchema now expose that schema on the Mastra tool wrapper, so Studio and other consumers can document expected tool outputs.

    Mastra does not re-validate MCP tool results. The MCP SDK still validates structuredContent via AJV. This keeps full CallToolResult envelopes and extra fields intact while making output shapes visible again.

    const tools = await mcp.listTools();
    const outputSchema = tools['weather_getForecast'].outputSchema?.['~standard'].jsonSchema.output({
      target: 'draft-07',
    });

@mastra/mcp-registry-registry@1.1.1

Patch Changes

  • Add Remote OpenClaw to the registry list (#18900)

    import { registryData } from '@mastra/mcp-registry-registry';
    
    const remoteOpenClaw = registryData.registries.find(r => r.id === 'remoteopenclaw');
    console.log(remoteOpenClaw?.url); // https://www.remoteopenclaw.com/

@mastra/mongodb@1.12.1

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

  • Schedule rows persisted with the legacy target.type: 'heartbeat' are now normalized to target.type: 'agent' when read, so existing agent schedules keep firing after the heartbeats-to-schedules rename in @mastra/core. (#18874)

@mastra/mysql@0.3.4

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

  • Schedule rows persisted with the legacy target.type: 'heartbeat' are now normalized to target.type: 'agent' when read, so existing agent schedules keep firing after the heartbeats-to-schedules rename in @mastra/core. (#18874)

@mastra/nestjs@0.2.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/next@0.2.4

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/observability@1.16.0

Minor Changes

  • Added flush() to ObservabilityEntrypoint so mastra.observability.flush() works directly in serverless environments. (#18873)

    Previously, flush() only existed on individual ObservabilityInstance objects, requiring users to call mastra.observability.getDefaultInstance()?.flush(). The entrypoint-level flush() delegates to all registered instances, matching the existing shutdown() pattern.

    // Before (broken — getObservability() didn't exist, flush() wasn't on the entrypoint)
    const observability = mastra.getObservability();
    await observability.flush();
    
    // After
    await mastra.observability.flush();

    Fixed the serverless flush docs in the observability config guide and Vercel deployment guide to use the correct API.

Patch Changes

@mastra/pg@1.15.1

Patch Changes

  • Fixed the ESM build never creating the mastra_observational_memory table. The OM schema was loaded through a dynamic require that esbuild rewrites to a throwing shim in the ESM output, and the silent catch skipped the table's creation, so deleteThread() crashed with Postgres error 42P01 on databases initialized from ESM processes (plain node ESM, tsx, vitest). The schema is now imported statically, which the @mastra/core peer dependency range guarantees is available. (#18957)

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

  • Schedule rows persisted with the legacy target.type: 'heartbeat' are now normalized to target.type: 'agent' when read, so existing agent schedules keep firing after the heartbeats-to-schedules rename in @mastra/core. (#18874)

@mastra/playground-ui@40.0.0

Patch Changes

  • Deprecated the legacy line TabList fallback for new tabs while keeping existing tabs compatible. (#18978)

  • Deprecated legacy asChild props in Playground UI. Use Base UI's native render prop for typed composition. (#18880)

  • Improved Studio metrics latency tabs so empty entity types are clearly disabled. (#18996)

  • Added reusable message scroller and thread rail primitives for conversation navigation, plus a shared useIsomorphicLayoutEffect hook for layout work that must also render safely on the server. (#18902)

    import {
      MessageScroller,
      MessageScrollerButton,
      MessageScrollerContent,
      MessageScrollerItem,
      MessageScrollerProvider,
      MessageScrollerViewport,
    } from '@mastra/playground-ui/components/MessageScroller';
    import { ThreadRail, buildThreadRailTurns } from '@mastra/playground-ui/components/ThreadRail';
    
    const turns = buildThreadRailTurns(messages);
    
    <MessageScrollerProvider>
      <MessageScroller>
        <MessageScrollerViewport>
          <MessageScrollerContent>
            {messages.map(message => (
              <MessageScrollerItem key={message.id} messageId={message.id}>
                <MessageRow message={message} />
              </MessageScrollerItem>
            ))}
          </MessageScrollerContent>
        </MessageScrollerViewport>
        <MessageScrollerButton />
        <ThreadRail turns={turns} />
      </MessageScroller>
    </MessageScrollerProvider>;
  • Improved playground-ui's safety around array and object access. (#18860)
    This release reduces the risk of undefined reads without changing behavior.

  • Hardened several string-parsing code paths against regular-expression denial of service (ReDoS). Path normalization, URL trimming, LLM token stripping, and observation parsing now use linear-time string scanning instead of regexes that could back-track polynomially on adversarial input. No behavior changes. (#18801)

@mastra/react@1.2.3

Patch Changes

  • Fixed Studio agent chat hanging on the first message when thread signals are enabled. When the thread subscription was aborted during mount, useChat cached the failed attempt and never retried it, so the assistant reply never arrived until a full page reload. The subscription is now retried on the next send. Also, when a send fails for any reason (subscription setup, request, or stream), useChat now resets its running state instead of leaving the chat spinner stuck until reload. (#18903)

@mastra/server@1.50.0

Minor Changes

  • Merged /api/heartbeats into /api/schedules. The server now exposes one unified schedules API that covers both agent schedules (previously heartbeats) and workflow schedules. (#18874)

    • GET /api/schedules lists both kinds and supports agentId, workflowId, status, threadId, resourceId, and name filters.
    • POST /api/schedules creates an agent schedule (body with agentId, cron, prompt) or a workflow schedule (body with workflowId, cron).
    • PATCH, DELETE, and POST .../pause, .../resume, .../run work for both kinds.
    • The /api/heartbeats/* routes were removed. Use /api/schedules/* instead.
    curl -X POST http://localhost:4111/api/schedules \
      -H 'Content-Type: application/json' \
      -d '{"agentId":"chef-agent","cron":"0 9 * * *","prompt":"Suggest a dish of the day"}'

Patch Changes

  • Added workspace-level provider registry to MastraEditor. You can now register WorkspaceProvider factories that build complete Workspace instances as a single unit, instead of composing from separate filesystem and sandbox providers. Stored agents can reference a workspace provider via { type: 'provider', provider: 'my-cloud', config: { ... } } and the editor will call the registered factory during agent hydration. (#18781)

    import { MastraEditor } from '@mastra/editor';
    import { Workspace } from '@mastra/core/workspace';
    
    const editor = new MastraEditor({
      workspaces: {
        'my-cloud': {
          id: 'my-cloud',
          name: 'My Cloud Workspace',
          createWorkspace: config =>
            new Workspace({
              id: 'cloud-ws',
              name: 'Cloud WS',
              filesystem: new MyCloudFilesystem(config),
              sandbox: new MyCloudSandbox(config),
            }),
        },
      },
    });
    
    // Stored agent workspace reference using the provider:
    // { type: 'provider', provider: 'my-cloud', config: { region: 'us-east-1' } }
  • Fixed AgentController route handlers dropping the request context set by server middleware. Identity values set on the request context in server.middleware (for example a tenant id) now reach dynamic instructions and tools when an agent is driven through the AgentController API, matching the behavior of the plain agent routes. This applies to the send-message, steer, follow-up, tool-approval, and tool-suspension routes. Fixes #18916. (#18918)

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/spanner@1.2.3

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

  • Schedule rows persisted with the legacy target.type: 'heartbeat' are now normalized to target.type: 'agent' when read, so existing agent schedules keep firing after the heartbeats-to-schedules rename in @mastra/core. (#18874)

@mastra/tanstack-start@0.2.4

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

@mastra/temporal@0.2.5

Patch Changes

  • Update @mastra/core peer dependency for the unified schedules API (#18874)

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.