UNPKG

@mastra/core

Version:

Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.

907 lines (639 loc) 1.38 MB
# @mastra/core ## 1.36.0 ### Minor Changes - Added `activateAfterIdle: "auto"` for Observational Memory early activation. ([#16663](https://github.com/mastra-ai/mastra/pull/16663)) Mastra can now choose an idle activation timeout from the active model provider's prompt cache behavior. OpenAI also respects `providerOptions.openai.promptCacheRetention` when available. ```ts const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', activateAfterIdle: 'auto', activateOnProviderChange: true, }, }, }); ``` - Added support for permission arrays in FGA checks and route configuration. When an array is provided, the user needs **any one** of the listed permissions (logical OR). ([#16605](https://github.com/mastra-ai/mastra/pull/16605)) **Affected types** - `FGACheckParams.permission` - `FGARouteConfig.permission` - `FGARouteInfo.requiresPermission` - `FGADeniedError.permission` - `CheckFGAOptions.permission` Single-permission usage continues to work unchanged. ```ts // Before — single permission only await fga.check({ resource: { type: 'agent', id: 'abc' }, permission: 'agents:read', }); // After — single permission or array (ANY-of) await fga.check({ resource: { type: 'agent', id: 'abc' }, permission: ['agents:read', 'agents:execute'], }); ``` - Added consistent FGA execution checks across agents, tools, memory, and workflows to prevent unauthenticated executions when FGA is configured. Pass an authenticated user through `requestContext` when invoking protected APIs directly: ([#16651](https://github.com/mastra-ai/mastra/pull/16651)) ```ts const requestContext = new RequestContext(); requestContext.set('user', user); await agent.generate('Summarize this thread', { requestContext, }); ``` - Added the `EditorFavorite*` types and an optional `favorites` namespace on `IMastraEditor` so editor implementations can expose favoriting of stored agents and skills. ([#16749](https://github.com/mastra-ai/mastra/pull/16749)) ```ts import type { IMastraEditor, IEditorFavoritesNamespace, EditorFavoriteTargetInput, EditorFavoriteToggleResult, } from '@mastra/core/editor'; interface IMastraEditor { // ...existing members... favorites?: IEditorFavoritesNamespace; } ``` The `favorites` field is optional — existing implementations of `IMastraEditor` continue to work unchanged. `@mastra/editor` ships a default `EditorFavoritesNamespace` that wires this up against the storage `favorites` domain. Also renamed `AgentFeatures.stars` to `AgentFeatures.favorites` in `@mastra/core/agent-builder/ee` so the feature flag aligns with the storage column (`favoriteCount`), HTTP routes (`/favorite`), and the editor `favorites` namespace. The field had no functional consumers, so this is a name-only change. - Enterprise edition now automatically captures PostHog telemetry for EE license checks and feature usage, including license validation status, RBAC access resolution, FGA authorization calls, and EE feature invocation metadata. Telemetry is enabled by default for EE customers and can be disabled with `MASTRA_TELEMETRY_DISABLED=1`; community users are unaffected. ([#16660](https://github.com/mastra-ai/mastra/pull/16660)) - Added new editor configuration primitives for browser providers, agent builder integration, and stored-agent visibility. ([#16778](https://github.com/mastra-ai/mastra/pull/16778)) **New: `BrowserProvider` interface** Implement a browser provider to expose browser automation tools to agents via the editor. Each provider declares an id, name, and config schema, then returns a `MastraBrowser` instance from `createBrowser`. ```ts import type { BrowserProvider } from '@mastra/core/editor'; const myProvider: BrowserProvider = { id: 'my-browser', name: 'My Browser', description: 'Custom browser automation', configSchema: z.object({ apiKey: z.string() }), createBrowser: async config => { return createMyBrowser(config.apiKey); }, }; ``` **New: `MastraEditorConfig.browsers` and `.builder`** Wire browser providers and agent-builder options into the editor: ```ts new MastraEditor({ browsers: { 'my-browser': myProvider }, builder: { features: { agent: { favorites: true } } }, }); ``` **New: `visibility` on `updateAgentMeta`** Set an agent's visibility (private or public) through the editor namespace: ```ts await editor.agent.updateAgentMeta('agent-id', { visibility: 'public' }); ``` - `publishSkill` now returns the full skill file tree so consumers can persist the UI-facing tree alongside storage blobs without re-walking the source. ([#16666](https://github.com/mastra-ai/mastra/pull/16666)) ```ts import { publishSkill } from '@mastra/core/workspace'; const result = await publishSkill({ workspace, skillId, source }); // New: nested tree of folders + files; binary content base64-encoded. for (const node of result.files) { console.log(node.type, node.path); } ``` Also added two optional capability methods to `IMastraEditor` for server-side gating of builder-aware behavior: ```ts interface IMastraEditor { // ...existing members... hasEnabledBuilderConfig?(): boolean; resolveBuilder?(): Promise<IAgentBuilder | undefined>; } ``` Both methods are optional — existing implementations of `IMastraEditor` continue to work unchanged. Servers that consume them treat `undefined` / missing implementation as "no builder configured." - Added route-specific CORS configuration so credentialed cross-origin access can be limited to selected custom routes and channel webhooks. ([#16689](https://github.com/mastra-ai/mastra/pull/16689)) ```ts registerApiRoute('/customer-webhook', { method: 'POST', cors: { origin: ['https://customer-saas.example'], credentials: true, }, handler: async c => c.json({ ok: true }), }); ``` ```ts new Agent({ id: 'support-agent', name: 'Support Agent', instructions: '...', model, channels: { adapters: { web: { adapter: createWebAdapter(), cors: { origin: ['https://customer-saas.example'], credentials: true, }, }, }, }, }); ``` Use `server.cors` for one global CORS policy across the server: ```ts new Mastra({ server: { cors: { origin: '*', }, }, }); ``` - Narrowed `AgentSignalContents` from `BaseMessageListInput` to `string | (TextPart | FilePart)[]`. ([#16622](https://github.com/mastra-ai/mastra/pull/16622)) Fixed two signal-content bugs: - `user-message` signal attributes now reach the LLM - multimodal non-`user-message` signals no longer lose file parts Callers that previously passed wrapped message shapes to `agent.sendSignal` should now pass a bare string or a bare parts array. Before: `{ type: 'user-message', contents: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }] }` After: `{ type: 'user-message', contents: [{ type: 'text', text: 'hi' }] }` Added an optional `providerOptions` field to `agent.sendSignal` that flows through to the resulting prompt turn (as `providerOptions` on the LLM message) and is persisted on the stored signal message (as `content.providerMetadata`). - `publishSkillFromSource()` (and `collectSkillForPublish()`) now return a `files` field containing the full skill source as a tree of `StorageSkillFileNode` entries with base64-encoded blob content — handy for storing a UI-facing copy of a skill alongside its content-addressable tree: ([#16673](https://github.com/mastra-ai/mastra/pull/16673)) ```ts const { snapshot, tree, files } = await publishSkillFromSource({ source }); // files: StorageSkillFileNode[] — name, mimeType, base64 content per node ``` Existing callers that only destructure `{ snapshot, tree }` are unaffected; the field is additive. Also adds `parseSkillSnapshotFromFiles()` for parsing skill snapshot frontmatter from a flat file list (used by the registry install flow): ```ts import { parseSkillSnapshotFromFiles, type SkillSnapshotFile } from '@mastra/core/workspace'; const files: SkillSnapshotFile[] = [{ path: 'SKILL.md', content: '...' }, ...]; const snapshot = parseSkillSnapshotFromFiles(files); ``` - Added delta polling support for observability list APIs in core, DuckDB, and ClickHouse. ([#16632](https://github.com/mastra-ai/mastra/pull/16632)) ### Patch Changes - Update provider registry and model documentation with latest models and providers ([`452036a`](https://github.com/mastra-ai/mastra/commit/452036a0d965b4f4c1efd93606e4f03b50b807a5)) - Fixed task_update to auto-demote previously in_progress tasks instead of returning an error when moving another task to in_progress. ([#16843](https://github.com/mastra-ai/mastra/pull/16843)) - Fixed durable agents to honor activeTools when streaming. ([#16646](https://github.com/mastra-ai/mastra/pull/16646)) - Fixed type error when a tool calls `suspend(...)` inside `execute` while also declaring an `outputSchema`. The `execute` return type now allows `void` in addition to the declared output shape, so the idiomatic `return await suspend(...)` pattern type-checks correctly. ([#16799](https://github.com/mastra-ai/mastra/pull/16799)) - Fixed a startup bug in `MastraCompositeStore.init()` when using `default` or `editor`. ([#16786](https://github.com/mastra-ai/mastra/pull/16786)) Before this fix, the composite initialized inner domains directly and could skip parent store initialization. That could skip adapter setup steps and cause missing-table errors during startup (most visibly with `LibSQLStore` on a local file). Now, `MastraCompositeStore.init()` runs parent `default` and `editor` initialization first, then initializes only domains not already covered by those parents. This preserves adapter-specific initialization behavior and prevents startup races. Fixes #16782. - Fixed CompositeAuth incorrectly advertising SSO, session, and user provider capabilities when no inner provider supports them. Studio would show an SSO login button even when no provider had SSO configured, leading to 401 errors on login attempts. The duck-typing check now verifies that interface methods are actual functions rather than just present on the prototype chain. ([#16664](https://github.com/mastra-ai/mastra/pull/16664)) - Hide internal workflow spans from Mastra-owned plumbing in exported traces. ([#16631](https://github.com/mastra-ai/mastra/pull/16631)) - Channels now serialize messages per thread to keep conversations in order, and the tool approval flow is fixed end-to-end: ([#16517](https://github.com/mastra-ai/mastra/pull/16517)) - Messages arriving while the agent is busy are delivered into the running agent loop instead of starting a new, conflicting stream on the same thread. Each Mastra thread shares one subscription, and channel/author facts (platform, message id, author name) are surfaced on the stored message under `providerMetadata.mastra.channels.<platform>`. - Tool approval flow: approving now drains the resumed run so the card is updated with the tool result and any follow-up assistant text is posted. Denying now resumes the run via `declineToolCall` instead of leaving it suspended. `agent.subscribeToThread()` consumers also receive chunks from resumed runs (the subscription used to drop the second registration for a resumed run that kept its original `runId`). - The original `ChannelConfig` is now exposed via the new `AgentChannels.channelConfig` field so channel providers can merge with existing adapters instead of replacing them. - Bumped `chat` to `^4.29.0`. - Added the `internalUsage?: UsageStats` field to `AIBaseAttributes`, so any span type can carry token usage rolled up from internal descendant spans. Populated automatically by `@mastra/observability` when an internal `MODEL_GENERATION` ends inside a non-internal ancestor. ([#16434](https://github.com/mastra-ai/mastra/pull/16434)) - Fixed trajectory scorers so tool calls stored only in V2 content.parts are included in extracted eval steps. ([#15439](https://github.com/mastra-ai/mastra/pull/15439)) - Fixed thread metadata updates to merge with existing fields instead of replacing them. Previously, updating a thread's metadata would silently drop any fields not included in the update. Now existing metadata fields are preserved when updating. ([#16846](https://github.com/mastra-ai/mastra/pull/16846)) Fixed MockMemory working memory tool to support partial JSON updates when using schema-based working memory. Previously, sending a partial update would overwrite all existing data. Now for schema-based configs, unchanged fields are preserved automatically (matching @mastra/memory behavior). Fixed MockMemory constructor to preserve workingMemory config options (like schema) when enableWorkingMemory is true. - Improved MastraCode quiet mode so terminal sessions are easier to scan. ([#16771](https://github.com/mastra-ai/mastra/pull/16771)) - Quiet mode is now the default for new installs, and existing classic users get a one-time prompt to choose whether to enable it. - Added compact tool previews with a configurable preview-line limit, including an option to hide previews. - Improved repeated tool-call rendering, path continuation handling, task wrapping, shell/error previews, and spacing between tools, messages, plans, and completed subagents. - Added edited line ranges to workspace edit results so tool UIs can show where replacements happened. - Remove hardcoded `/api/` prefix check from `registerApiRoute()`. The check incorrectly rejected custom routes starting with `/api/` even when users configured a different `apiPrefix`. Reserved-path validation is already handled at the server adapter level using the actual configured prefix. ([#16859](https://github.com/mastra-ai/mastra/pull/16859)) - Fixed infinite recursion in `RequestContext.toJSON()` when multiple ([#16686](https://github.com/mastra-ai/mastra/pull/16686)) `RequestContext` instances reference each other through stored values. Previously, serializing such cross-context cycles would cause a CPU hang. Cyclic references are now detected and omitted from the serialized output, consistent with how circular references within a single context are handled. - Fixed crash in CacheKeyGenerator.fromAIV4Part when a tool-invocation part has undefined toolInvocation. This can happen when observational memory seals a partially-streamed assistant message. Also guarded MessageMerger against the same condition. ([#16773](https://github.com/mastra-ai/mastra/pull/16773)) - Agent signals can now coordinate active thread runs across agents that share a PubSub instance, so thread subscribers and signal senders can observe the same run instead of being limited to one runtime instance. ([#16665](https://github.com/mastra-ai/mastra/pull/16665)) ```ts import { Agent } from '@mastra/core/agent'; import { EventEmitterPubSub } from '@mastra/core/events'; const pubsub = new EventEmitterPubSub(); const agent = new Agent({ id: 'agent', name: 'Agent', instructions: 'Help the user', model, pubsub, }); ``` - Exposed `formatSkillActivation(skill)` from `@mastra/core/workspace`. It returns the activation payload — instructions plus references, scripts, and assets listings — that the built-in `skill` tool uses, so callers (e.g. an explicit `/skill/<name>` slash command) can produce the same output without duplicating the formatting logic. ([#16618](https://github.com/mastra-ai/mastra/pull/16618)) Also preserves the `user-invocable` skill frontmatter field in workspace skill metadata. ```ts import { formatSkillActivation } from '@mastra/core/workspace'; const content = formatSkillActivation(skill); ``` - Fixed sub-agent streams so nested tool input progress is emitted while tool arguments are still being generated. This lets UIs show delegated agents preparing tool calls before the final tool input is available. Fixes #16422. ([#16553](https://github.com/mastra-ai/mastra/pull/16553)) - Fixed `backgroundTasks: { enabled: true }` silently dispatching foreground-only tools to the background. ([#16792](https://github.com/mastra-ai/mastra/pull/16792)) Previously, enabling `backgroundTasks` on the `Mastra` instance injected a system prompt into every agent that taught the LLM to flip any tool to background by passing `_background: { enabled: true }` in its arguments, and the resolver honored that override unconditionally. Models would readily do this for short, deterministic tools — a plain calculator could return `"Background task started…"` instead of `{ result: 42 }`, breaking `agent.generate()` / `agent.stream()` for tool-using flows. The LLM `_background` override is now treated as a _modifier_ on tools the developer has opted in at the tool or agent layer, not a standalone opt-in. If a tool hasn't been opted in via tool-level `background: { enabled: true }` or agent-level `backgroundTasks: { tools: { … } }` (or `tools: 'all'`), `_background.enabled: true` from the model is ignored and the tool runs in the foreground. Opted-in tools continue to honor LLM overrides for `enabled`, `timeoutMs`, and `maxRetries` as documented. Fixes https://github.com/mastra-ai/mastra/issues/16783 - Fixed scheduler performance and correctness issues that could cause excessive Postgres CPU and noisy failed runs. ([#16805](https://github.com/mastra-ai/mastra/pull/16805)) - Added missing indexes on the schedules tables that the tick loop polls every 10 seconds: `(status, next_fire_at)` on `mastra_schedules` and `(schedule_id, actual_fire_at)` on `mastra_schedule_triggers`. Without these the scheduler performed a full sequential scan on every tick. - The scheduler tick loop is now only started when at least one workflow declares a schedule (or `scheduler.enabled` is set explicitly), so deployments without scheduled workflows no longer poll the database at all. - The scheduler now validates that a schedule's target workflow is still registered before firing it. Schedules whose target workflow has been removed from the Mastra config are skipped for a short grace window and then deleted, so stale rows stop producing failed workflow runs forever. - The scheduler is now lazily initialized inside `startWorkers()`. Accessing `mastra.scheduler` before `startWorkers()` runs throws a descriptive error instead of returning a half-initialized instance. - Fixed Mastra getting stuck after a storage startup failure. Previously, if storage couldn't start up (for example, because the database was briefly unreachable), Mastra would keep returning the same error for every operation until the process was restarted. Now the next storage operation tries to start storage again, so brief outages recover on their own. Storage startup failures are also logged, so the problem is visible even when a later retry succeeds. ([#16427](https://github.com/mastra-ai/mastra/pull/16427)) - Restore MastraCode local command execution to inherit parent environment variables while redacting env-shaped and secret-looking workspace trace data. ([#16691](https://github.com/mastra-ai/mastra/pull/16691)) - Added a Unix socket PubSub transport and wired the Mastra Code TUI through a per-resource socket so local sessions can coordinate thread streams across processes. Programmatic `createMastraCode` usage remains opt-in: ([#16669](https://github.com/mastra-ai/mastra/pull/16669)) ```ts await createMastraCode({ unixSocketPubSub: true }); ``` - Fix in-memory observability storage to match the contract validated against DuckDB/ClickHouse vNext adapters. ([#16808](https://github.com/mastra-ai/mastra/pull/16808)) Previously, when running Mastra with the default in-memory storage, several observability operations behaved differently than they would against a production database: - **`getSpans`** threw 'This storage provider does not support batch-fetching spans'. It now batch-fetches spans by id within a trace, enabling the optimized `getBranch` path on in-memory storage. - **`batchCreateLogs`, `batchCreateMetrics`, `createScore`/`batchCreateScores`, `createFeedback`/`batchCreateFeedback`** appended duplicate records on retry. They now upsert by id, preserving the cursor id so delta polling does not re-emit the record. This makes client retries safe. - **Discovery operations** (`getEntityTypes`, `getEntityNames`, `getServiceNames`, `getEnvironments`, `getTags`) only inspected spans. They now also scan logs and metrics, so dimensions emitted on those surfaces are surfaced in discovery results. - **`getMetricTimeSeries`** merged grouped series whose label values contained the `|` character (e.g. `{segmentA: 'a', segmentB: 'b|c'}` collided with `{segmentA: 'a|b', segmentB: 'c'}`). Series are now keyed on the original label tuple, so colliding display names remain distinct series. ## 1.36.0-alpha.10 ### Minor Changes - Enterprise edition now automatically captures PostHog telemetry for EE license checks and feature usage, including license validation status, RBAC access resolution, FGA authorization calls, and EE feature invocation metadata. Telemetry is enabled by default for EE customers and can be disabled with `MASTRA_TELEMETRY_DISABLED=1`; community users are unaffected. ([#16660](https://github.com/mastra-ai/mastra/pull/16660)) ### Patch Changes - Fixed task_update to auto-demote previously in_progress tasks instead of returning an error when moving another task to in_progress. ([#16843](https://github.com/mastra-ai/mastra/pull/16843)) - Channels now serialize messages per thread to keep conversations in order, and the tool approval flow is fixed end-to-end: ([#16517](https://github.com/mastra-ai/mastra/pull/16517)) - Messages arriving while the agent is busy are delivered into the running agent loop instead of starting a new, conflicting stream on the same thread. Each Mastra thread shares one subscription, and channel/author facts (platform, message id, author name) are surfaced on the stored message under `providerMetadata.mastra.channels.<platform>`. - Tool approval flow: approving now drains the resumed run so the card is updated with the tool result and any follow-up assistant text is posted. Denying now resumes the run via `declineToolCall` instead of leaving it suspended. `agent.subscribeToThread()` consumers also receive chunks from resumed runs (the subscription used to drop the second registration for a resumed run that kept its original `runId`). - The original `ChannelConfig` is now exposed via the new `AgentChannels.channelConfig` field so channel providers can merge with existing adapters instead of replacing them. - Bumped `chat` to `^4.29.0`. - Fixed trajectory scorers so tool calls stored only in V2 content.parts are included in extracted eval steps. ([#15439](https://github.com/mastra-ai/mastra/pull/15439)) - Fixed thread metadata updates to merge with existing fields instead of replacing them. Previously, updating a thread's metadata would silently drop any fields not included in the update. Now existing metadata fields are preserved when updating. ([#16846](https://github.com/mastra-ai/mastra/pull/16846)) Fixed MockMemory working memory tool to support partial JSON updates when using schema-based working memory. Previously, sending a partial update would overwrite all existing data. Now for schema-based configs, unchanged fields are preserved automatically (matching @mastra/memory behavior). Fixed MockMemory constructor to preserve workingMemory config options (like schema) when enableWorkingMemory is true. - Remove hardcoded `/api/` prefix check from `registerApiRoute()`. The check incorrectly rejected custom routes starting with `/api/` even when users configured a different `apiPrefix`. Reserved-path validation is already handled at the server adapter level using the actual configured prefix. ([#16859](https://github.com/mastra-ai/mastra/pull/16859)) - Fixed scheduler performance and correctness issues that could cause excessive Postgres CPU and noisy failed runs. ([#16805](https://github.com/mastra-ai/mastra/pull/16805)) - Added missing indexes on the schedules tables that the tick loop polls every 10 seconds: `(status, next_fire_at)` on `mastra_schedules` and `(schedule_id, actual_fire_at)` on `mastra_schedule_triggers`. Without these the scheduler performed a full sequential scan on every tick. - The scheduler tick loop is now only started when at least one workflow declares a schedule (or `scheduler.enabled` is set explicitly), so deployments without scheduled workflows no longer poll the database at all. - The scheduler now validates that a schedule's target workflow is still registered before firing it. Schedules whose target workflow has been removed from the Mastra config are skipped for a short grace window and then deleted, so stale rows stop producing failed workflow runs forever. - The scheduler is now lazily initialized inside `startWorkers()`. Accessing `mastra.scheduler` before `startWorkers()` runs throws a descriptive error instead of returning a half-initialized instance. ## 1.36.0-alpha.9 ### Patch Changes - Fix in-memory observability storage to match the contract validated against DuckDB/ClickHouse vNext adapters. ([#16808](https://github.com/mastra-ai/mastra/pull/16808)) Previously, when running Mastra with the default in-memory storage, several observability operations behaved differently than they would against a production database: - **`getSpans`** threw 'This storage provider does not support batch-fetching spans'. It now batch-fetches spans by id within a trace, enabling the optimized `getBranch` path on in-memory storage. - **`batchCreateLogs`, `batchCreateMetrics`, `createScore`/`batchCreateScores`, `createFeedback`/`batchCreateFeedback`** appended duplicate records on retry. They now upsert by id, preserving the cursor id so delta polling does not re-emit the record. This makes client retries safe. - **Discovery operations** (`getEntityTypes`, `getEntityNames`, `getServiceNames`, `getEnvironments`, `getTags`) only inspected spans. They now also scan logs and metrics, so dimensions emitted on those surfaces are surfaced in discovery results. - **`getMetricTimeSeries`** merged grouped series whose label values contained the `|` character (e.g. `{segmentA: 'a', segmentB: 'b|c'}` collided with `{segmentA: 'a|b', segmentB: 'c'}`). Series are now keyed on the original label tuple, so colliding display names remain distinct series. ## 1.36.0-alpha.8 ### Patch Changes - Fixed type error when a tool calls `suspend(...)` inside `execute` while also declaring an `outputSchema`. The `execute` return type now allows `void` in addition to the declared output shape, so the idiomatic `return await suspend(...)` pattern type-checks correctly. ([#16799](https://github.com/mastra-ai/mastra/pull/16799)) ## 1.36.0-alpha.7 ### Minor Changes - Added new editor configuration primitives for browser providers, agent builder integration, and stored-agent visibility. ([#16778](https://github.com/mastra-ai/mastra/pull/16778)) **New: `BrowserProvider` interface** Implement a browser provider to expose browser automation tools to agents via the editor. Each provider declares an id, name, and config schema, then returns a `MastraBrowser` instance from `createBrowser`. ```ts import type { BrowserProvider } from '@mastra/core/editor'; const myProvider: BrowserProvider = { id: 'my-browser', name: 'My Browser', description: 'Custom browser automation', configSchema: z.object({ apiKey: z.string() }), createBrowser: async config => { return createMyBrowser(config.apiKey); }, }; ``` **New: `MastraEditorConfig.browsers` and `.builder`** Wire browser providers and agent-builder options into the editor: ```ts new MastraEditor({ browsers: { 'my-browser': myProvider }, builder: { features: { agent: { favorites: true } } }, }); ``` **New: `visibility` on `updateAgentMeta`** Set an agent's visibility (private or public) through the editor namespace: ```ts await editor.agent.updateAgentMeta('agent-id', { visibility: 'public' }); ``` ## 1.36.0-alpha.6 ### Patch Changes - Added a Unix socket PubSub transport and wired the Mastra Code TUI through a per-resource socket so local sessions can coordinate thread streams across processes. Programmatic `createMastraCode` usage remains opt-in: ([#16669](https://github.com/mastra-ai/mastra/pull/16669)) ```ts await createMastraCode({ unixSocketPubSub: true }); ``` ## 1.36.0-alpha.5 ### Patch Changes - Improved MastraCode quiet mode so terminal sessions are easier to scan. ([#16771](https://github.com/mastra-ai/mastra/pull/16771)) - Quiet mode is now the default for new installs, and existing classic users get a one-time prompt to choose whether to enable it. - Added compact tool previews with a configurable preview-line limit, including an option to hide previews. - Improved repeated tool-call rendering, path continuation handling, task wrapping, shell/error previews, and spacing between tools, messages, plans, and completed subagents. - Added edited line ranges to workspace edit results so tool UIs can show where replacements happened. - Fixed `backgroundTasks: { enabled: true }` silently dispatching foreground-only tools to the background. ([#16792](https://github.com/mastra-ai/mastra/pull/16792)) Previously, enabling `backgroundTasks` on the `Mastra` instance injected a system prompt into every agent that taught the LLM to flip any tool to background by passing `_background: { enabled: true }` in its arguments, and the resolver honored that override unconditionally. Models would readily do this for short, deterministic tools — a plain calculator could return `"Background task started…"` instead of `{ result: 42 }`, breaking `agent.generate()` / `agent.stream()` for tool-using flows. The LLM `_background` override is now treated as a _modifier_ on tools the developer has opted in at the tool or agent layer, not a standalone opt-in. If a tool hasn't been opted in via tool-level `background: { enabled: true }` or agent-level `backgroundTasks: { tools: { … } }` (or `tools: 'all'`), `_background.enabled: true` from the model is ignored and the tool runs in the foreground. Opted-in tools continue to honor LLM overrides for `enabled`, `timeoutMs`, and `maxRetries` as documented. Fixes https://github.com/mastra-ai/mastra/issues/16783 ## 1.36.0-alpha.4 ### Minor Changes - Added `activateAfterIdle: "auto"` for Observational Memory early activation. ([#16663](https://github.com/mastra-ai/mastra/pull/16663)) Mastra can now choose an idle activation timeout from the active model provider's prompt cache behavior. OpenAI also respects `providerOptions.openai.promptCacheRetention` when available. ```ts const memory = new Memory({ options: { observationalMemory: { model: 'google/gemini-2.5-flash', activateAfterIdle: 'auto', activateOnProviderChange: true, }, }, }); ``` ### Patch Changes - Fixed a startup bug in `MastraCompositeStore.init()` when using `default` or `editor`. ([#16786](https://github.com/mastra-ai/mastra/pull/16786)) Before this fix, the composite initialized inner domains directly and could skip parent store initialization. That could skip adapter setup steps and cause missing-table errors during startup (most visibly with `LibSQLStore` on a local file). Now, `MastraCompositeStore.init()` runs parent `default` and `editor` initialization first, then initializes only domains not already covered by those parents. This preserves adapter-specific initialization behavior and prevents startup races. Fixes #16782. - Agent signals can now coordinate active thread runs across agents that share a PubSub instance, so thread subscribers and signal senders can observe the same run instead of being limited to one runtime instance. ([#16665](https://github.com/mastra-ai/mastra/pull/16665)) ```ts import { Agent } from '@mastra/core/agent'; import { EventEmitterPubSub } from '@mastra/core/events'; const pubsub = new EventEmitterPubSub(); const agent = new Agent({ id: 'agent', name: 'Agent', instructions: 'Help the user', model, pubsub, }); ``` ## 1.36.0-alpha.3 ### Minor Changes - Added the `EditorFavorite*` types and an optional `favorites` namespace on `IMastraEditor` so editor implementations can expose favoriting of stored agents and skills. ([#16749](https://github.com/mastra-ai/mastra/pull/16749)) ```ts import type { IMastraEditor, IEditorFavoritesNamespace, EditorFavoriteTargetInput, EditorFavoriteToggleResult, } from '@mastra/core/editor'; interface IMastraEditor { // ...existing members... favorites?: IEditorFavoritesNamespace; } ``` The `favorites` field is optional — existing implementations of `IMastraEditor` continue to work unchanged. `@mastra/editor` ships a default `EditorFavoritesNamespace` that wires this up against the storage `favorites` domain. Also renamed `AgentFeatures.stars` to `AgentFeatures.favorites` in `@mastra/core/agent-builder/ee` so the feature flag aligns with the storage column (`favoriteCount`), HTTP routes (`/favorite`), and the editor `favorites` namespace. The field had no functional consumers, so this is a name-only change. - Added delta polling support for observability list APIs in core, DuckDB, and ClickHouse. ([#16632](https://github.com/mastra-ai/mastra/pull/16632)) ### Patch Changes - Fixed durable agents to honor activeTools when streaming. ([#16646](https://github.com/mastra-ai/mastra/pull/16646)) - Fixed infinite recursion in `RequestContext.toJSON()` when multiple ([#16686](https://github.com/mastra-ai/mastra/pull/16686)) `RequestContext` instances reference each other through stored values. Previously, serializing such cross-context cycles would cause a CPU hang. Cyclic references are now detected and omitted from the serialized output, consistent with how circular references within a single context are handled. - Fixed crash in CacheKeyGenerator.fromAIV4Part when a tool-invocation part has undefined toolInvocation. This can happen when observational memory seals a partially-streamed assistant message. Also guarded MessageMerger against the same condition. ([#16773](https://github.com/mastra-ai/mastra/pull/16773)) - Restore MastraCode local command execution to inherit parent environment variables while redacting env-shaped and secret-looking workspace trace data. ([#16691](https://github.com/mastra-ai/mastra/pull/16691)) ## 1.36.0-alpha.2 ### Minor Changes - Added support for permission arrays in FGA checks and route configuration. When an array is provided, the user needs **any one** of the listed permissions (logical OR). ([#16605](https://github.com/mastra-ai/mastra/pull/16605)) **Affected types** - `FGACheckParams.permission` - `FGARouteConfig.permission` - `FGARouteInfo.requiresPermission` - `FGADeniedError.permission` - `CheckFGAOptions.permission` Single-permission usage continues to work unchanged. ```ts // Before — single permission only await fga.check({ resource: { type: 'agent', id: 'abc' }, permission: 'agents:read', }); // After — single permission or array (ANY-of) await fga.check({ resource: { type: 'agent', id: 'abc' }, permission: ['agents:read', 'agents:execute'], }); ``` - Added consistent FGA execution checks across agents, tools, memory, and workflows to prevent unauthenticated executions when FGA is configured. Pass an authenticated user through `requestContext` when invoking protected APIs directly: ([#16651](https://github.com/mastra-ai/mastra/pull/16651)) ```ts const requestContext = new RequestContext(); requestContext.set('user', user); await agent.generate('Summarize this thread', { requestContext, }); ``` - `publishSkill` now returns the full skill file tree so consumers can persist the UI-facing tree alongside storage blobs without re-walking the source. ([#16666](https://github.com/mastra-ai/mastra/pull/16666)) ```ts import { publishSkill } from '@mastra/core/workspace'; const result = await publishSkill({ workspace, skillId, source }); // New: nested tree of folders + files; binary content base64-encoded. for (const node of result.files) { console.log(node.type, node.path); } ``` Also added two optional capability methods to `IMastraEditor` for server-side gating of builder-aware behavior: ```ts interface IMastraEditor { // ...existing members... hasEnabledBuilderConfig?(): boolean; resolveBuilder?(): Promise<IAgentBuilder | undefined>; } ``` Both methods are optional — existing implementations of `IMastraEditor` continue to work unchanged. Servers that consume them treat `undefined` / missing implementation as "no builder configured." - `publishSkillFromSource()` (and `collectSkillForPublish()`) now return a `files` field containing the full skill source as a tree of `StorageSkillFileNode` entries with base64-encoded blob content — handy for storing a UI-facing copy of a skill alongside its content-addressable tree: ([#16673](https://github.com/mastra-ai/mastra/pull/16673)) ```ts const { snapshot, tree, files } = await publishSkillFromSource({ source }); // files: StorageSkillFileNode[] — name, mimeType, base64 content per node ``` Existing callers that only destructure `{ snapshot, tree }` are unaffected; the field is additive. Also adds `parseSkillSnapshotFromFiles()` for parsing skill snapshot frontmatter from a flat file list (used by the registry install flow): ```ts import { parseSkillSnapshotFromFiles, type SkillSnapshotFile } from '@mastra/core/workspace'; const files: SkillSnapshotFile[] = [{ path: 'SKILL.md', content: '...' }, ...]; const snapshot = parseSkillSnapshotFromFiles(files); ``` ### Patch Changes - Fixed sub-agent streams so nested tool input progress is emitted while tool arguments are still being generated. This lets UIs show delegated agents preparing tool calls before the final tool input is available. Fixes #16422. ([#16553](https://github.com/mastra-ai/mastra/pull/16553)) ## 1.36.0-alpha.1 ### Minor Changes - Added route-specific CORS configuration so credentialed cross-origin access can be limited to selected custom routes and channel webhooks. ([#16689](https://github.com/mastra-ai/mastra/pull/16689)) ```ts registerApiRoute('/customer-webhook', { method: 'POST', cors: { origin: ['https://customer-saas.example'], credentials: true, }, handler: async c => c.json({ ok: true }), }); ``` ```ts new Agent({ id: 'support-agent', name: 'Support Agent', instructions: '...', model, channels: { adapters: { web: { adapter: createWebAdapter(), cors: { origin: ['https://customer-saas.example'], credentials: true, }, }, }, }, }); ``` Use `server.cors` for one global CORS policy across the server: ```ts new Mastra({ server: { cors: { origin: '*', }, }, }); ``` ### Patch Changes - Hide internal workflow spans from Mastra-owned plumbing in exported traces. ([#16631](https://github.com/mastra-ai/mastra/pull/16631)) - Added the `internalUsage?: UsageStats` field to `AIBaseAttributes`, so any span type can carry token usage rolled up from internal descendant spans. Populated automatically by `@mastra/observability` when an internal `MODEL_GENERATION` ends inside a non-internal ancestor. ([#16434](https://github.com/mastra-ai/mastra/pull/16434)) - Fixed Mastra getting stuck after a storage startup failure. Previously, if storage couldn't start up (for example, because the database was briefly unreachable), Mastra would keep returning the same error for every operation until the process was restarted. Now the next storage operation tries to start storage again, so brief outages recover on their own. Storage startup failures are also logged, so the problem is visible even when a later retry succeeds. ([#16427](https://github.com/mastra-ai/mastra/pull/16427)) ## 1.36.0-alpha.0 ### Minor Changes - Narrowed `AgentSignalContents` from `BaseMessageListInput` to `string | (TextPart | FilePart)[]`. ([#16622](https://github.com/mastra-ai/mastra/pull/16622)) Fixed two signal-content bugs: - `user-message` signal attributes now reach the LLM - multimodal non-`user-message` signals no longer lose file parts Callers that previously passed wrapped message shapes to `agent.sendSignal` should now pass a bare string or a bare parts array. Before: `{ type: 'user-message', contents: [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }] }` After: `{ type: 'user-message', contents: [{ type: 'text', text: 'hi' }] }` Added an optional `providerOptions` field to `agent.sendSignal` that flows through to the resulting prompt turn (as `providerOptions` on the LLM message) and is persisted on the stored signal message (as `content.providerMetadata`). ### Patch Changes - Update provider registry and model documentation with latest models and providers ([`452036a`](https://github.com/mastra-ai/mastra/commit/452036a0d965b4f4c1efd93606e4f03b50b807a5)) - Fixed CompositeAuth incorrectly advertising SSO, session, and user provider capabilities when no inner provider supports them. Studio would show an SSO login button even when no provider had SSO configured, leading to 401 errors on login attempts. The duck-typing check now verifies that interface methods are actual functions rather than just present on the prototype chain. ([#16664](https://github.com/mastra-ai/mastra/pull/16664)) - Exposed `formatSkillActivation(skill)` from `@mastra/core/workspace`. It returns the activation payload — instructions plus references, scripts, and assets listings — that the built-in `skill` tool uses, so callers (e.g. an explicit `/skill/<name>` slash command) can produce the same output without duplicating the formatting logic. ([#16618](https://github.com/mastra-ai/mastra/pull/16618)) Also preserves the `user-invocable` skill frontmatter field in workspace skill metadata. ```ts import { formatSkillActivation } from '@mastra/core/workspace'; const content = formatSkillActivation(skill); ``` ## 1.35.0 ### Minor Changes - Added FGA route policy coverage controls, built-in resource route metadata resolution, and resolver hooks. ([#16485](https://github.com/mastra-ai/mastra/pull/16485)) For example: ```ts import { MastraFGAWorkos } from '@mastra/auth-workos'; import type { FGARouteConfig, FGARouteResolver, IFGAProvider } from '@mastra/core/auth/ee'; import { createRoute } from '@mastra/server/server-adapter'; const routeFGA = { 'GET /billing/:accountId': { resourceType: 'account', resourceIdParam: 'accountId', permission: 'billing:read', }, } satisfies Record<string, FGARouteConfig>; const resolveRouteFGA: FGARouteResolver = ({ route }) => routeFGA[`${route.method} ${route.path}`]; const fga: IFGAProvider = new MastraFGAWorkos({ apiKey: process.env.WORKOS_API_KEY!, clientId: process.env.WORKOS_CLIENT_ID!, requireForProtectedRoutes: true, auditProtectedRoutes: 'warn', resolveRouteFGA, validatePermissions: async permissions => { /* validate mappings */ }, }); export const getProjectRoute = createRoute({ method: 'GET', path: '/projects/:projectId', responseType: 'json', requiresAuth: true, fga: { resourceType: 'project', resourceIdParam: 'projectId', permission: 'projects:read', }, handler: async () => { return { project: null }; }, }); ``` - Added a favorites storage domain that lets users mark stored agents and skills as favorites, plus `visibility` (`'private' | 'public'`) and `favoriteCount` fields on stored agents and skills so callers can list, filter, and order by favorite state. ([#16580](https://github.com/mastra-ai/mastra/pull/16580)) Existing rows without `visibility` or `favoriteCount` continue to work; the new fields and APIs are opt-in. **Example** ```ts const favorites = await storage.getStore('favorites'); await favorites?.favorite({ userId: 'u1', entityType: 'agent', entityId: 'agent-123' }); const favoritedIds = await favorites?.listFavoritedIds({ userId: 'u1', entityType: 'agent' }); // List agents the user has favorited, surfaced first const { agents } = await storage.getStore('agents').list({ pinFavoritedFor: 'u1', favoritedOnly: true, }); ``` ### Patch Changes - Update provider registry and model documentation with latest models and providers ([`b661349`](https://github.com/mastra-ai/mastra/commit/b661349281514691db78941a9044e6e4f1cde7a7)) - Fixed a workspace PATCH bug in the inmemory workspace adapter: omitted config fields in a PATCH no longer overwrite previously-persisted values with `undefined`. ([#16580](https://github.com/mastra-ai/mastra/pull/16580)) - Fixed active signals so they stay in the correct order when conversations are reloaded from memory. ([#16623](https://github.com/mastra-ai/mastra/pull/16623)) - Fixed scheduled workflows created from the public @mastra/core/workflows entry point so declared schedules are applied correctly. ([#16637](https://github.com/mastra-ai/mastra/pull/16637)) - Fixed a crash when importing `@mastra/core/workflows/workflow` from tests or apps, which previously failed with `TypeError: Class extends value undefined is not a constructor or null` (caused by a circular ESM import through the `workflows` barrel). ([#16661](https://github.com/mastra-ai/mastra/pull/16661)) ## 1.35.0-alpha.3 ### Patch Changes - Fixed active signals so they stay in the correct order when conversations are reloaded from memory. ([#16623](https://github.com/mastra-ai/mastra/pull/16623)) - Fixed a crash when importing `@mastra/core/workflows/workflow` from tests or apps, which previously failed with `TypeError: Class extends value undefined is not a constructor or null` (caused by a circular ESM import through the `workflows` barrel). ([#16661](https://github.com/mastra-ai/mastra/pull/16661)) ## 1.35.0-alpha.2 ### Minor Changes - Added a favorites storage domain that lets users mark stored agents and skills as favorites, plus `visibility` (`'private' | 'public'`) and `favoriteCount` fields on stored agents and skills so callers can list, filter, and order by favorite state. ([#16580](https://github.com/mastra-ai/mastra/pull/16580)) Existing rows without `visibility` or `favoriteCount` continue to work; the new fields and APIs are opt-in. **Example** ```ts const favorites = await storage.getStore('favorites'); await favorites?.favorite({ userId: 'u1', entityType: 'agent', entityId: 'agent-123' }); const favoritedIds = await favorites?.listFavoritedIds({ userId: 'u1', entityType: 'agent' }); // List agents the user has favorited, surfaced first const { agents } = await storage.getStore('agents').list({ pinFavoritedFor: 'u1', favoritedOnly: true, }); ``` ### Patch Changes - Fixed a workspace PATCH bug in the inmemory workspace adapter: omitted config fields in a PATCH no longer overwrite previously-persisted values with `undefined`. ([#16580](https://github.com/mastra-ai/mastra/pull/16580)) - Fixed scheduled workflows created from the public @mastra/core/workflows entry point so declared schedules are applied correctly. ([#16637](https://github.com/mastra-ai/mastra/pull/16637)) ## 1.35.0-alpha.1 ### Minor Changes - Added FGA route policy coverage controls, built-in resource route metadata resolution, and resolver hooks. ([#16485](https://github.com/mastra-ai/mastra/pull/16485)) For example: ```ts import { MastraFGAWorkos } from '@mastra/auth-workos'; import type { FGARouteConfig, FGARouteResolver, IFGAProvider } from '@mastra/core/auth/ee'; import { createRoute } from '@mastra/server/server-adapter'; const routeFGA = { 'GET /billing/:accountId': { resourceType: 'account', resourceIdParam: 'accountId', permission: 'billing:read', }, } satisfies Record<string, FGARouteConfig>; const resolveRouteFGA: FGARouteResolver = ({ route }) => routeFGA[`${route.method} ${route.path}`]; const fga: IFGAProvider = new MastraFGAWorkos({ apiKey: process.env.WORKOS_API_KEY!, clientId: process.env.WORKOS_CLIENT_ID!, requireForProtectedRoutes: true, auditProtectedRoutes: 'warn', resolveRouteFGA, validatePermissions: async permissions => { /* validate mappings */ }, }); export const getProjectRoute = createRoute({ method: 'GET', path: '/projects/:projectId', responseType: 'json', requiresAuth: true, fga: { resourceType: 'project', resourceIdParam: 'projectId', permission: 'projects:read', }, handler: async () => { return { project: null }; }, }); ``` ## 1.34.1-alpha.0 ### Patch Changes - Update provider registry and model documentation with latest models and providers ([`b661349`](https://github.com/mastra-ai/mastra/commit/b661349281514691db78941a9044e6e4f1cde7a7)) ## 1.34.0 ### Minor Changes - You can now run ACP-compatible coding agents as Mastra tools or lightweight subagents. ACP agents support incremental response streaming and can be used anywhere Mastra accepts a `SubAgent`, including supervisor delegation and workflow steps. ([#16423](https://github.com/mastra-ai/ma