@mastra/core@1.36.0
mastra-ai/mastra@mastra/core@1.36.0May 28, 2026by PaulieScanlon
AI Summary
This release adds a full HTTP surface for stored entities (Agents, Skills, Workspaces), browser automation primitives, and delta polling for observability list APIs. It also enforces FGA execution checks across agents/tools/memory/workflows and introduces Convex Native Vector Search and Durable Server Cache for production workloads.
Key Highlights
- Stored Entity HTTP APIs (Agents/Skills/Workspaces) + Builder/Registry Introspection
- Browser Automation & Screencast Session Probing (incl. Stored Agents)
- Delta Polling for Observability List APIs (Server/Client/Stores/UI)
- Harder Authorization Defaults: FGA Coverage + ANY-of Permissions + Safer Context Keys
- Convex Production Upgrades: Native Vector Search + Durable Server Cache
Breaking Changes
- AgentSignalContents narrowed to string | (TextPart | FilePart)[]
- @mastra/playground-ui Button variants changed (cta/contrast/link removed, default/primary/outline/ghost added)
- PopoverContent no longer forwards onOpenAutoFocus/onCloseAutoFocus
New Features
- HTTP API for CRUD, versioning, activation/restore, and favorites metadata on stored entities
- Browser session probing endpoint to safely open screencast WebSockets
- Delta polling support for observability list endpoints
- FGA route policy coverage controls and resolver hooks
- ConvexNativeVector adapter and ConvexServerCache
Full Release Notes
## Highlights
### Stored Entity HTTP APIs (Agents/Skills/Workspaces) + Builder/Registry Introspection
`@mastra/server` adds a full HTTP surface for stored entities (CRUD, versioning, activation/restore) including favorites metadata, plus builder introspection endpoints and an external skill-registry proxy that Studio and `@mastra/client-js` can consume.
### Browser Automation & Screencast Session Probing (incl. Stored Agents)
New browser-provider/editor primitives wire browser automation into the editor, while deployers/adapters add a probeable `GET /agents/:agentId/browser/session` endpoint and client SDK methods (`agent.browserSession()` / `agent.closeBrowser()`) so UIs can safely open screencast WebSockets only when supported—now also working for stored agents via editor fallback lookup.
### Delta Polling for Observability List APIs (Server/Client/Stores/UI)
Observability list endpoints now support `mode: 'delta'` with cursors across core + `@mastra/server`, with store support in DuckDB/ClickHouse (and in-memory alignment) and typed client support; Playground UI’s traces list updates live via delta polling instead of full-page refetches.
### Harder Authorization Defaults: FGA Coverage + ANY-of Permissions + Safer Context Keys
FGA execution checks are now enforced consistently across agents/tools/memory/workflows (requiring authenticated `requestContext` when invoking protected APIs), and both FGA checks and route permissions accept permission arrays (ANY-of semantics); server auth middleware also writes namespaced request-context keys to avoid collisions.
### Convex Production Upgrades: Native Vector Search + Durable Server Cache
`@mastra/convex` adds `ConvexNativeVector` backed by schema vector indexes/`ctx.vectorSearch` for production-grade retrieval, plus `ConvexServerCache` to persist durable stream replay and response-cache state in Convex.
### Breaking Changes
- `AgentSignalContents` narrowed to `string | (TextPart | FilePart)[]` (no longer accepts wrapped `BaseMessageListInput` shapes); update `agent.sendSignal` callers accordingly.
- `@mastra/playground-ui` Button variants changed: `cta`/`contrast`/`link` removed in favor of `default`/`primary`/`outline`/`ghost`; `ButtonWithTooltip` removed (use `Button` with `tooltip` prop).
- `PopoverContent` no longer forwards `onOpenAutoFocus`/`onCloseAutoFocus` (use `initialFocus`/`finalFocus` instead).
## Changelog
### [@mastra/core@1.36.0](https://github.com/mastra-ai/mastra/blob/@mastra/core@1.36.0/packages/core/CHANGELOG.md)
#### 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.
### [@mastra/ai-sdk@1.4.3](https://github.com/mastra-ai/mastra/blob/@mastra/ai-sdk@1.4.3/client-sdks/ai-sdk/CHANGELOG.md)
#### 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))
### [@mastra/auth-okta@0.0.3](https://github.com/mastra-ai/mastra/blob/@mastra/auth-okta@0.0.3/auth/okta/CHANGELOG.md)
#### Patch Changes
- Fix endpoint URL construction for Okta org authorization servers. ([#15694](https://github.com/mastra-ai/mastra/pull/15694))
`MastraAuthOkta` concatenated `/v1/authorize` (and `/token`, `/keys`, `/logout`) directly onto `OKTA_ISSUER`. That yields the right endpoint for a custom authorization server (`https://{domain}/oauth2/default` → `.../oauth2/default/v1/authorize`), but 404s on an Okta org authorization server (`https://{domain}` → `.../v1/authorize`, whereas the real org endpoint is `.../oauth2/v1/authorize`).
An internal `endpointBase` is now derived from the issuer — verbatim when it already contains `/oauth2/`, otherwise `${issuer}/oauth2` — and used for the authorize, token, keys, and logout URLs. JWT `iss`-claim validation still uses the raw issuer so token validation stays correct on both server types. Trailing slashes on the issuer are also normalized so `OKTA_ISSUER=https://{domain}/` no longer produces `.../oauth2//v1/...`.
### [@mastra/auth-workos@1.5.0](https://github.com/mastra-ai/mastra/blob/@mastra/auth-workos@1.5.0/auth/workos/CHANGELOG.md)
#### Minor Changes
- FGA `check()` and `require()` now accept an array of permissions and short-circuit on the first one that resolves to allow (ANY-of semantics). Single-permission usage continues to work unchanged. ([#16605](https://github.com/mastra-ai/mastra/pull/16605))
```ts
// Before — one permission per call
await fgaProvider.check({
user,
resource: { type: 'agent', id: 'abc' },
permission: 'agents:read',
});
// After — single permission or ANY-of array
await fgaProvider.check({
user,
resource: { type: 'agent', id: 'abc' },
permission: ['agents:read', 'agents:execute'],
});
```
When all permissions in the array are denied, the thrown `FGADeniedError` lists them as `any of [a, b, c]` in its message.
#### Patch Changes
### [@mastra/clickhouse@1.9.0](https://github.com/mastra-ai/mastra/blob/@mastra/clickhouse@1.9.0/stores/clickhouse/CHANGELOG.md)
#### Minor Changes
- 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 duplicate entries in the ClickHouse v-next observability discovery endpoints — tags, services, environments, entities, metric names, and metric labels now return each value once. Existing deployments are reconciled automatically on next startup; no manual migration required. ([#16798](https://github.com/mastra-ai/mastra/pull/16798))
### [@mastra/client-js@1.20.0](https://github.com/mastra-ai/mastra/blob/@mastra/client-js@1.20.0/client-sdks/client-js/CHANGELOG.md)
#### Minor Changes
- Added `agent.browserSession(threadId?)` and `agent.closeBrowser(threadId?)` to the `Agent` resource, plus a `GetAgentBrowserSessionResponse` type. ([#16668](https://github.com/mastra-ai/mastra/pull/16668))
`browserSession` probes the server's browser session state before opening a screencast WebSocket, so the connection is only made when the server has screencast support installed and an active session exists for the thread. `closeBrowser` ends the agent's browser session (or a single thread's session if `threadId` is passed). Both methods go through the configured client `baseUrl` and `apiPrefix`, so they work with servers mounted under a non-default API prefix.
```ts
const probe = await client.getAgent('my-agent').browserSession(threadId);
if (probe.screencastAvailable && probe.hasSession) {
// safe to open the screencast WebSocket
}
await client.getAgent('my-agent').closeBrowser(threadId);
```
- Added typed client-side resources for the stored-entity HTTP surface so you no longer have to hand-roll `fetch` calls. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
```ts
import { MastraClient } from '@mastra/client-js';
const client = new MastraClient({ baseUrl: 'http://localhost:4111' });
// List/get with favorite metadata
const { items } = await client.storedAgents.list({ page: 1, perPage: 20 });
const agent = await client.storedAgents.get(items[0].id);
console.log(agent.favoriteCount, agent.isFavorited);
// Favorite toggle
await client.storedAgents.favorite(agent.id);
await client.storedAgents.unfavorite(agent.id);
// Versioning + publish
const draft = await client.storedSkills.create({
/* ... */
});
const published = await client.storedSkills.publish(draft.id);
await client.storedSkills.restore(draft.id, { version: 1 });
```
Also regenerated `route-types.generated.ts` to cover the new editor-builder introspection routes (`/editor/builder/settings`, `/editor/builder/infrastructure`) and the external skill-registry endpoints under `/editor/builder/registries` (list, search, popular, preview, install).
- Added delta polling support for observability list endpoints. ([#16632](https://github.com/mastra-ai/mastra/pull/16632))
```ts
const page = await client.observability.listTraces({
mode: 'page',
filters: { entityName: 'agent-1' },
});
const delta = await client.observability.listTraces({
mode: 'delta',
filters: { entityName: 'agent-1' },
after: page.deltaCursor,
});
```
Use `mode: 'delta'` to fetch only new items after the last cursor.
Page-mode responses include `pagination` and `deltaCursor` when delta polling is supported. Delta-mode responses include `delta` and do not include `pagination`.
If you read these responses directly in typed code, note that `pagination` is only included in page mode.
- 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
- Fixed provider and dataset item history response types to include fields returned by the API. ([#16213](https://github.com/mastra-ai/mastra/pull/16213))
- Fixed an issue where recursive client-tool continuations after `resumeStream` (and `resumeStreamUntilIdle`) incorrectly re-hit the one-shot resume endpoint instead of falling back to the regular stream endpoint. The resume routes consume server-side `resumeData` and cannot be replayed, so client-tool continuations now route to `/stream` and `/stream-until-idle` respectively. ([#16670](https://github.com/mastra-ai/mastra/pull/16670))
- Fixed the playground memory configuration display for agents using observationalMemory: true. ([#16213](https://github.com/mastra-ai/mastra/pull/16213))
### [@mastra/convex@1.1.0](https://github.com/mastra-ai/mastra/blob/@mastra/convex@1.1.0/stores/convex/CHANGELOG.md)
#### Minor Changes
- Added native Convex vector search support for production workloads. The new `ConvexNativeVector` adapter uses ([#16729](https://github.com/mastra-ai/mastra/pull/16729))
Convex schema-defined vector indexes and `ctx.vectorSearch` instead of loading vectors through `ConvexVector` and
scoring them in JavaScript.
Define a native vector table in `convex/schema.ts`:
```ts
import { defineSchema } from 'convex/server';
import { defineMastraNativeVectorTable } from '@mastra/convex/schema';
export default defineSchema({
docs_vectors: defineMastraNativeVectorTable({
dimensions: 1536,
}),
});
```
Export the native vector handlers:
```ts
import { mastraNativeVectorAction, mastraNativeVectorMutation, mastraNativeVectorQuery } from '@mastra/convex/server';
export const query = mastraNativeVectorAction;
export const read = mastraNativeVectorQuery;
export const write = mastraNativeVectorMutation;
```
Then configure `ConvexNativeVector` in your Mastra app:
```ts
import { ConvexNativeVector } from '@mastra/convex';
const vectorStore = new ConvexNativeVector({
id: 'convex-native-vectors',
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
indexes: {
docs: {
tableName: 'docs_vectors',
vectorIndexName: 'by_embedding',
dimension: 1536,
},
},
});
```
- Added `ConvexServerCache` so Convex-backed Mastra apps can keep durable stream replay and response cache state in Convex. ([#16736](https://github.com/mastra-ai/mastra/pull/16736))
```ts
import { ConvexServerCache } from '@mastra/convex';
const cache = new ConvexServerCache({
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
});
```
The package also exports the Convex cache schema tables and server mutation for mounting the cache handler in a Convex app.
Existing Convex users who adopt the cache must add `mastra_cache` and `mastra_cache_list_items` to their Convex schema, mount the `mastraCache` handler, and deploy the schema update.
#### Patch Changes
### [@mastra/datadog@1.2.1](https://github.com/mastra-ai/mastra/blob/@mastra/datadog@1.2.1/observability/datadog/CHANGELOG.md)
#### Patch Changes
- Fixed Datadog LLM output tool calls so they render as structured tool call blocks. ([#16789](https://github.com/mastra-ai/mastra/pull/16789))
- Fixed Datadog LLM span input formatting to remove empty user messages. ([#16785](https://github.com/mastra-ai/mastra/pull/16785))
### [@mastra/deployer@1.36.0](https://github.com/mastra-ai/mastra/blob/@mastra/deployer@1.36.0/packages/deployer/CHANGELOG.md)
#### 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
- Browser streaming now works for stored agents. The deployer's `getToolset` first checks the runtime agent registry, then falls back to the editor's stored-agent lookup, so agents created at runtime through the editor can stream browser sessions without being pre-registered in code. ([#16778](https://github.com/mastra-ai/mastra/pull/16778))
- When browser streaming is unavailable (the `ws` and `@hono/node-ws` packages aren't installed, or the deployer is running in a serverless environment), the deployer now registers a fallback `GET /api/agents/:agentId/browser/session` route that returns `{ hasSession: false, screencastAvailable: false }`. This lets clients detect that screencast won't work and skip the WebSocket upgrade instead of triggering a noisy reconnect loop. ([#16668](https://github.com/mastra-ai/mastra/pull/16668))
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/deployer-cloud@1.36.0](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-cloud@1.36.0/deployers/cloud/CHANGELOG.md)
#### Patch Changes
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/deployer-cloudflare@1.1.37](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-cloudflare@1.1.37/deployers/cloudflare/CHANGELOG.md)
#### Patch Changes
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/deployer-netlify@1.1.13](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-netlify@1.1.13/deployers/netlify/CHANGELOG.md)
#### Patch Changes
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/deployer-vercel@1.1.31](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-vercel@1.1.31/deployers/vercel/CHANGELOG.md)
#### Patch Changes
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/duckdb@1.4.0](https://github.com/mastra-ai/mastra/blob/@mastra/duckdb@1.4.0/stores/duckdb/CHANGELOG.md)
#### Minor Changes
- 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 DuckDB observability storage so dev server restarts no longer fail when replaying cursor migrations. ([#16803](https://github.com/mastra-ai/mastra/pull/16803))
### [@mastra/editor@0.9.0](https://github.com/mastra-ai/mastra/blob/@mastra/editor@0.9.0/packages/editor/CHANGELOG.md)
#### Minor Changes
- `EditorWorkspaceNamespace` can now snapshot a live `Workspace` for persistence — the reverse of `hydrateSnapshotToWorkspace()`: ([#16673](https://github.com/mastra-ai/mastra/pull/16673))
```ts
const snapshot = await editor.workspace.snapshotFromWorkspace(runtimeWorkspace);
await editor.workspace.create({ id: 'my-workspace', ...snapshot });
```
`snapshotFromWorkspace()` is `async` and awaits `sandbox.getInfo()` and `filesystem.getInfo()` so async providers like `CompositeFilesystem` keep their mount metadata in the stored config.
Also includes two smaller behavioral fixes:
- `EditorSkillNamespace.publishSkillFromSource()` stores the new `files` field on the published skill version and strips `undefined` keys before calling `update()` (libsql/pg adapters reject `undefined` bind arguments).
- `CrudEditorNamespace.clearCache(id)` always calls `onCacheEvict(id)`, even when the entity wasn't cached, so subclasses can clean up runtime registries for version-specific lookups that bypass the editor cache.
- Added an `editor.favorites` namespace so direct (non-HTTP) callers can favorite, unfavorite, and query favorited stored agents/skills through the editor instance. ([#16749](https://github.com/mastra-ai/mastra/pull/16749))
```ts
import { MastraEditor } from '@mastra/editor';
const editor = new MastraEditor({ mastra });
// Toggle
await editor.favorites.favorite({ userId, entityType: 'agent', entityId });
await editor.favorites.unfavorite({ userId, entityType: 'agent', entityId });
// Lookups
const isFav = await editor.favorites.isFavorited({ userId, entityType: 'agent', entityId });
const favSet = await editor.favorites.isFavoritedBatch({ userId, entityType: 'agent', entityIds });
const ids = await editor.favorites.listFavoritedIds({ userId, entityType: 'agent' });
```
The namespace performs the storage mutation only — visibility and ownership enforcement still belong to the caller (the HTTP route handlers in `@mastra/server` already do this).
#### Patch Changes
### [@mastra/express@1.3.23](https://github.com/mastra-ai/mastra/blob/@mastra/express@1.3.23/server-adapters/express/CHANGELOG.md)
#### Patch Changes
- Updated the adapter permission check to read user permissions from the new namespaced request-context key `mastra__userPermissions` (was `userPermissions`). This matches the namespaced keys that `@mastra/server`'s core auth middleware now writes and avoids collisions with caller-supplied context entries. ([#16605](https://github.com/mastra-ai/mastra/pull/16605))
No action needed for typical users — install the matching `@mastra/server` release and the adapter will continue to enforce route permissions exactly as before.
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/fastembed@1.1.0](https://github.com/mastra-ai/mastra/blob/@mastra/fastembed@1.1.0/packages/fastembed/CHANGELOG.md)
#### Minor Changes
- Replace the abandoned `fastembed` npm dependency with a maintained, vendored implementation. The public API and all embedding models remain unchanged — no migration needed. ([#16772](https://github.com/mastra-ai/mastra/pull/16772))
### [@mastra/fastify@1.3.23](https://github.com/mastra-ai/mastra/blob/@mastra/fastify@1.3.23/server-adapters/fastify/CHANGELOG.md)
#### Patch Changes
- Updated the adapter permission check to read user permissions from the new namespaced request-context key `mastra__userPermissions` (was `userPermissions`). This matches the namespaced keys that `@mastra/server`'s core auth middleware now writes and avoids collisions with caller-supplied context entries. ([#16605](https://github.com/mastra-ai/mastra/pull/16605))
No action needed for typical users — install the matching `@mastra/server` release and the adapter will continue to enforce route permissions exactly as before.
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/hono@1.4.18](https://github.com/mastra-ai/mastra/blob/@mastra/hono@1.4.18/server-adapters/hono/CHANGELOG.md)
#### Patch Changes
- Updated the adapter permission check to read user permissions from the new namespaced request-context key `mastra__userPermissions` (was `userPermissions`). This matches the namespaced keys that `@mastra/server`'s core auth middleware now writes and avoids collisions with caller-supplied context entries. ([#16605](https://github.com/mastra-ai/mastra/pull/16605))
No action needed for typical users — install the matching `@mastra/server` release and the adapter will continue to enforce route permissions exactly as before.
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
- Added `GET /agents/:agentId/browser/session` endpoint (under the configured `apiPrefix`, default `/api`) that reports whether a screencast WebSocket should be opened for an agent and thread. Clients can probe this before upgrading to a WebSocket to avoid idle connections and reconnect storms. ([#16668](https://github.com/mastra-ai/mastra/pull/16668))
```bash
curl "http://localhost:4111/api/agents/my-agent/browser/session?threadId=thread-1"
# {"hasSession":true,"screencastAvailable":true}
```
The response shape is `{ hasSession: boolean, screencastAvailable: true }`. `screencastAvailable` is always `true` when this route is registered; the deployer registers a fallback that returns `{ hasSession: false, screencastAvailable: false }` when browser streaming packages aren't installed, so clients can use the same probe in both cases.
`setupBrowserStream` now accepts an optional `apiPrefix` so the probe and existing `POST /agents/:agentId/browser/close` routes are mounted under the same prefix as the rest of the server. The deployer wires this from `mastra.getServer().apiPrefix` automatically.
- The Hono adapter now awaits `getToolset` calls in browser-stream routes, supporting deployers that resolve agents asynchronously (such as stored agents looked up via the editor). ([#16778](https://github.com/mastra-ai/mastra/pull/16778))
### [@mastra/koa@1.5.6](https://github.com/mastra-ai/mastra/blob/@mastra/koa@1.5.6/server-adapters/koa/CHANGELOG.md)
#### Patch Changes
- Updated the adapter permission check to read user permissions from the new namespaced request-context key `mastra__userPermissions` (was `userPermissions`). This matches the namespaced keys that `@mastra/server`'s core auth middleware now writes and avoids collisions with caller-supplied context entries. ([#16605](https://github.com/mastra-ai/mastra/pull/16605))
No action needed for typical users — install the matching `@mastra/server` release and the adapter will continue to enforce route permissions exactly as before.
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/libsql@1.11.1](https://github.com/mastra-ai/mastra/blob/@mastra/libsql@1.11.1/stores/libsql/CHANGELOG.md)
#### Patch Changes
- 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.
### [@mastra/mcp@1.8.0](https://github.com/mastra-ai/mastra/blob/@mastra/mcp@1.8.0/packages/mcp/CHANGELOG.md)
#### Minor Changes
- Added MCP tool annotations to the `requireToolApproval` context and exposed them on tools returned from `listTools()` / `listToolsets()`. ([#16784](https://github.com/mastra-ai/mastra/pull/16784))
The `requireToolApproval` callback now receives the server-advertised `annotations` (`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) alongside `toolName` and `args`. This lets you write declarative approval policies instead of hardcoding tool name lists. Annotations are also propagated onto Mastra tools as `tool.mcp.annotations` so apps can render them in UI.
**Security caveat (per the MCP spec):** annotations are _hints_, not guarantees. Clients MUST treat them as untrusted unless they come from a trusted server. Do not use annotations alone as a security boundary for servers you do not control — set `requireToolApproval: true` for those. When the server omits annotations entirely, this field is `undefined`, so policies can distinguish "no annotations" from "annotated as safe".
```ts
import { MCPClient } from '@mastra/mcp';
// Before — hardcoded tool name lists, server-specific
const mcp = new MCPClient({
servers: {
github: {
url: new URL('https://example.com/mcp'),
requireToolApproval: ({ toolName }) => toolName === 'delete_repo',
},
},
});
// After — annotation-driven, works across any trusted MCP server
const mcp = new MCPClient({
servers: {
github: {
url: new URL('https://example.com/mcp'),
requireToolApproval: ({ annotations }) => {
if (!annotations) return true;
if (annotations.readOnlyHint) return false;
if (annotations.destructiveHint) return true;
return false;
},
},
},
});
// Annotations are also visible on tools returned by listTools()
const tools = await mcp.listTools();
for (const tool of Object.values(tools)) {
console.log(tool.mcp?.annotations);
}
```
Closes #16766.
#### Patch Changes
- Fixed an issue where OAuth token requests dropped `client_id` and `client_secret` for confidential clients. The provider previously shipped an empty `addClientAuthentication` method that satisfied the MCP SDK's existence check and short-circuited its default credential attachment, causing `invalid_request` errors on token exchange and refresh against confidential-client OAuth servers. The empty stub has been removed so the SDK's built-in client authentication runs again. See [#16854](https://github.com/mastra-ai/mastra/issues/16854). ([#16862](https://github.com/mastra-ai/mastra/pull/16862))
- Close previous SSE transport before accepting a new connection in `MCPServer.connectSSE()`. Previously, sequential SSE connections to the same server would fail with "Already connected to a transport" because the underlying protocol was never closed when the previous client disconnected. ([#16695](https://github.com/mastra-ai/mastra/pull/16695))
### [@mastra/memory@1.19.0](https://github.com/mastra-ai/mastra/blob/@mastra/memory@1.19.0/packages/memory/CHANGELOG.md)
#### 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,
},
},
});
```
- Add `observeAttachments` to `ObservationConfig` for Observational Memory. Use it to control whether image/file parts on observed messages are forwarded to the Observer model alongside their placeholder text lines. ([#16671](https://github.com/mastra-ai/mastra/pull/16671))
- `true` (default) — forward all attachments (existing behavior).
- `false` — drop all attachments; placeholders still appear in the observer transcript.
- `string[]` — allowlist of mimeType patterns, e.g. `['image/*']` or `['application/pdf']`. Matching is case-insensitive and supports exact, `type/*`, and `*` patterns.
Useful when the Observer model is text-only (some DeepSeek endpoints, etc.) while the main agent uses a multimodal model. Tool-result attachments are filtered with the same rule.
```ts
new Memory({
options: {
observationalMemory: {
observation: {
model: 'deepseek/deepseek-chat', // text-only observer
observeAttachments: false, // or e.g. ['image/*', 'application/pdf']
},
},
},
});
```
#### Patch Changes
- feat(memory): start background buffering of unobserved messages when agent goes idle ([#16694](https://github.com/mastra-ai/mastra/pull/16694))
In OM buffering mode, when the agent goes idle (turn.end()), any unobserved messages are now buffered in the background via a fire-and-forget buffer() call. This ensures observations are computed proactively rather than waiting for the next turn's step.prepare().
### [@mastra/nestjs@0.1.7](https://github.com/mastra-ai/mastra/blob/@mastra/nestjs@0.1.7/server-adapters/nestjs/CHANGELOG.md)
#### Patch Changes
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/observability@1.13.0](https://github.com/mastra-ai/mastra/blob/@mastra/observability@1.13.0/observability/mastra/CHANGELOG.md)
#### Minor Changes
- Roll up token usage from internal MODEL_GENERATION spans onto the closest exported ancestor span. When `tracingPolicy.internal` filters a model call out of exported traces, its tokens used to disappear from both the trace UI and metrics. Now: ([#16434](https://github.com/mastra-ai/mastra/pull/16434))
- The visible ancestor (e.g. `PROCESSOR_RUN`, `AGENT_RUN`) gets an `internalUsage` attribute summing the tokens consumed by its hidden descendants — so a Mastra-owned processor that runs an internal agent (moderation, PII detector, structured output, etc.) shows its aggregate cost on the visible `PROCESSOR_RUN` span.
- Token / cost metrics still emit, but are attributed via labels to the visible ancestor instead of the hidden agent.
No action required — the rollup applies automatically whenever an internal `MODEL_GENERATION` ends inside a non-internal ancestor.
- `MastraStorageExporter` now notifies custom exporters and connected integrations when it cannot persist observability events, such as unsupported storage or retries being exceeded. This matches the behavior already available on `DefaultExporter`. ([#16755](https://github.com/mastra-ai/mastra/pull/16755))
Also fixed an issue in both exporters where span updates waiting on their parent span could be silently lost if a later flush in the same cycle failed.
#### Patch Changes
### [@mastra/pg@1.11.1](https://github.com/mastra-ai/mastra/blob/@mastra/pg@1.11.1/stores/pg/CHANGELOG.md)
#### Patch Changes
- 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.
### [@mastra/playground-ui@29.0.0](https://github.com/mastra-ai/mastra/blob/@mastra/playground-ui@29.0.0/packages/playground-ui/CHANGELOG.md)
#### Minor Changes
- Added `ContextMenu` for right-click interactions. Supports submenus, checkbox and radio items, keyboard shortcuts, and a `destructive` variant for dangerous actions like delete. ([#16791](https://github.com/mastra-ai/mastra/pull/16791))
```tsx
import { ContextMenu } from '@mastra/playground-ui';
<ContextMenu>
<ContextMenu.Trigger className="…">Right click here</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item>Rename</ContextMenu.Item>
<ContextMenu.Item variant="destructive">Delete</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu>;
```
- Removed `ButtonWithTooltip` from `@mastra/playground-ui`. Use `Button` with the `tooltip` prop instead. ([#16719](https://github.com/mastra-ai/mastra/pull/16719))
**Migration**
```tsx
// before
import { ButtonWithTooltip } from '@mastra/playground-ui';
<ButtonWithTooltip tooltipContent="Search">
<Search />
</ButtonWithTooltip>;
// after
import { Button } from '@mastra/playground-ui';
<Button tooltip="Search">
<Search />
</Button>;
```
`tooltip` supports the same values as `tooltipContent`. Icon-only buttons that pass a string `tooltip` now also get it as their `aria-label` automatically, matching how labelled controls have always behaved. Pass an explicit `aria-label` to override.
- Added a custom date range option to the Metrics page date picker. You can now filter metrics by an arbitrary start and end date and time, matching the Traces page, alongside the existing relative presets (last 24 hours, 3, 7, 14, and 30 days). ([#16832](https://github.com/mastra-ai/mastra/pull/16832))
The selected range is reflected in the URL so it can be bookmarked or shared:
```txt
/metrics?period=custom&dateFrom=2026-05-01T00:00:00.000Z&dateTo=2026-05-07T23:59:59.999Z
```
- Refreshed Button + Card design system tokens. ([#16769](https://github.com/mastra-ai/mastra/pull/16769))
**Button variants (breaking)**: consolidated to `default`, `primary`, `outline`, `ghost`. The `cta`, `contrast`, and unused `link` variants have been removed. `primary` now uses a high-contrast `neutral6` fill instead of `surface4`, so it reads clearly as the form submit action in both themes.
```tsx
// Before
<Button variant="cta">Save</Button>
<Button variant="contrast">Done</Button>
<Button variant="link">Open</Button>
// After
<Button variant="primary">Save</Button> // cta → primary (no brand green; theme-aware high contrast)
<Button variant="primary">Done</Button> // contrast → primary (same recipe, renamed)
<Button as="a" href="…" variant="ghost">Open</Button> // link → ghost (or plain <a> for inline text links)
```
**New tokens**: `--surface-overlay-soft` and `--surface-overlay-strong` — alpha overlays of the opposite-theme color, used by `SectionCard` header strip and `DashboardCard` fill so cards read consistently on any surface.
**Other**:
- DashboardCard radius reduced to `rounded-xl` and padding tightened to `px-4 py-3` for better grid density.
- SectionCard wrapper no longer fills its background — header strip + border carry definition.
- Dark `surface2` / `surface3` darkened slightly (16.84% → 16%, 19.13% → 18%) so the main frame reads as a distinct surface.
- Dark `border1` / `border2` alphas bumped (6% → 7%, 10% → 11%) for closer dark/light parity.
- Removed deprecated `--section-card-*` tokens and their `@utility` blocks.
#### Patch Changes
- Added a `destructive` variant on `DropdownMenu.Item` to highlight dangerous actions like delete. ([#16791](https://github.com/mastra-ai/mastra/pull/16791))
```tsx
<DropdownMenu.Item variant="destructive">Delete project</DropdownMenu.Item>
```
- `PopoverContent` no longer forwards the underlying library's auto-focus event handlers (`onOpenAutoFocus`, `onCloseAutoFocus`). To control focus when the popover opens or closes, use `initialFocus` and `finalFocus`. ([#16791](https://github.com/mastra-ai/mastra/pull/16791))
```tsx
// Before
<PopoverContent onOpenAutoFocus={(e) => e.preventDefault()} />
// After
<PopoverContent initialFocus={false} />
```
- Fixed a crash in filter menus with nested submenus (such as the Filter on the Agent review page) that showed "`MenuPortal` must be used within `Menu`". The submenu content now uses the design system's `DropdownMenu.SubContent` instead of the underlying library's portal directly. ([#16829](https://github.com/mastra-ai/mastra/pull/16829))
- Fixed type definitions and shared UI component types for `@mastra/playground-ui`. ([#16213](https://github.com/mastra-ai/mastra/pull/16213))
- `AlertDialog`'s API and behavior are unchanged — `asChild` on `AlertDialog.Trigger`, and `AlertDialog.Action` and `AlertDialog.Cancel`, all work exactly as before. (Internally it now builds on Base UI primitives.) ([#16824](https://github.com/mastra-ai/mastra/pull/16824))
- Moved the `Collapsible` component to Base UI, with a smoother height-based expand and collapse animation. The public API is unchanged — `asChild` on `CollapsibleTrigger` still works. ([#16825](https://github.com/mastra-ai/mastra/pull/16825))
- Upgraded `@base-ui/react` to 1.5, making popups noticeably faster — components built on Base UI such as `Tooltip`, `Popover`, `DropdownMenu` and `ContextMenu` now open and close more quickly. ([#16819](https://github.com/mastra-ai/mastra/pull/16819))
- Moved the Level icon from its own column into the Name column, next to the trace name, on the Observability traces list. ([#16712](https://github.com/mastra-ai/mastra/pull/16712))
- The Traces list now updates live via delta polling. Previously the list was refetched every 10 seconds, replacing the whole page with no signal about what changed; now new traces appear within a few seconds of being created, with a brief highlight to draw attention. Status changes on already-visible rows (running → success / error) also propagate without intervention, and returning to the tab after being idle re-syncs from a fresh cursor. ([#16727](https://github.com/mastra-ai/mastra/pull/16727))
**New `useTraces` return fields**
- `isRefetching` — true while any meaningful refetch is in flight. Use it to drive a heartbeat indicator.
- `autoRefetch` / `setAutoRefetch` — pause / resume all automatic polling so the consumer can render an opt-out toggle.
- `recentlyAddedKeys` — `Set<string>` of `traceId:spanId` for rows that just arrived via delta polling. Drives the temporary highlight in `TracesListView`.
**New polling config**
Every timing in the hook is tunable per-instance via a new `polling` option:
```ts
import { useTraces, type TracesPollingConfig } from '@mastra/playground-ui';
useTraces({
filters,
listMode,
polling: {
deltaPollIntervalMs: 10_000,
idleGuardThresholdMs: 5 * 60_000,
},
});
```
Omitted fields fall through to the defaults (delta poll every 5s, idle reset after 15 min, status refresh every 60s, etc).
**TracesListView**
New optional `recentlyAddedKeys?: Set<string>` prop. Rows whose `traceId:spanId` is in the set get the `animate-row-highlight` class — a brief fade-out to transparent, added to `index.css`.
**Compatibility**
Requires `@mastra/server` and `@mastra/client-js` at the versions that ship the observability delta-polling endpoints, and a store that opts into delta polling (`@mastra/clickhouse`, `@mastra/duckdb`, and the in-memory store today). When unavailable — older server or a store without delta capability — the hook silently falls back to page-mode interval refetching. No consumer changes required.
- Added `align` and `stack` variants to `PageLayout.Row`. Use `stack="responsive"` for top bars that should collapse to a vertical stack on narrow viewports, and `align="center"` to vertically center children. Applied the new variants to the Prompts and Workflows top bars so the search field and primary action share a single row on desktop and stack on mobile. ([#16714](https://github.com/mastra-ai/mastra/pull/16714))
```tsx
<PageLayout.Row align="center" stack="responsive">
<ListSearch ... />
<Button ...>Create</Button>
</PageLayout.Row>
```
- Fixed the playground memory configuration display for agents using observationalMemory: true. ([#16213](https://github.com/mastra-ai/mastra/pull/16213))
- Fixed double-counted cache token costs in the Metrics dashboard. The Model Usage & Cost table and the Token Usage by Agent table were summing cache read/write costs on top of the total input cost, which already includes them. ([#16737](https://github.com/mastra-ai/mastra/pull/16737))
- Migrated the Tooltip primitive to Base UI while preserving the existing API. The popup explicitly sets `role="tooltip"` so consumers can keep querying it via `getByRole('tooltip')` (Base UI does not add this role automatically). Existing `<TooltipTrigger asChild>` usage continues to work unchanged, and Base UI's native `render` prop is now also supported on `TooltipTrigger` so consumers wrapping anchors, custom router links, or icons can pass the element directly without an `asChild` adapter: ([#16713](https://github.com/mastra-ai/mastra/pull/16713))
```tsx
// Still supported
<TooltipTrigger asChild>
<Button>Save</Button>
</TooltipTrigger>
// New: pass the element via Base UI's native API
<TooltipTrigger render={<Button>Save</Button>} />
```
Also fixed the arrow rendering so the diagonal stroke meets the popup outline at the exact same pixel center on every side, removing the ~1px seam previously visible where the arrow joined the popup edge.
- Migrated the Slider component to base-ui with a refined neutral visual design. ([#16788](https://github.com/mastra-ai/mastra/pull/16788))
**What changed**
- Replaced `@radix-ui/react-slider` with `@base-ui/react/slider` as the underlying primitive
- Refreshed visuals: thin rounded thumb with white border and neutral inside, opacity-based track that adapts to any surface, neutral filled indicator (no green/accent color)
- Larger click target via padded `Slider.Control` and an invisible hit area on the thumb so it is easier to grab
- Added `cursor-pointer` on the control and `cursor-not-allowed` when disabled
- Removed the now unused `@radix-ui/react-slider` and `@radix-ui/react-tabs` dependencies
**API compatibility**
The public API is preserved. `onValueChange` and `onValueCommitted` are wrapped so consumers always receive `number[]`, even though base-ui returns `number | number[]` internally. Existing call sites like `<Slider value={[temperature]} onValueChange={value => setTemperature(value[0])} />` continue to work without changes.
- Moved the `Dialog` component to Base UI. The public API is unchanged — `asChild` on `DialogTrigger` and `DialogClose` still works the same way, and open/close animations behave as before. ([#16821](https://github.com/mastra-ai/mastra/pull/16821))
### [@mastra/react@0.4.0](https://github.com/mastra-ai/mastra/blob/@mastra/react@0.4.0/client-sdks/react/CHANGELOG.md)
#### Minor Changes
- Added `clientTools` option to `useChat`'s `generate`/`stream` calls for forwarding browser-side tools to the agent on each invocation. ([#16778](https://github.com/mastra-ai/mastra/pull/16778))
```tsx
import { useChat } from '@mastra/react';
const { generate } = useChat({ agentId: 'my-agent' });
await generate({
messages: [{ role: 'user', content: 'Show a toast that says hi' }],
clientTools: {
showToast: {
description: 'Show a toast to the user',
inputSchema: z.object({ message: z.string() }),
execute: ({ message }) => toast(message),
},
},
});
```
Client tools are forwarded as-is to the underlying `agent.generate()` and `agent.stream()` calls.
- 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
### [@mastra/server@1.36.0](https://github.com/mastra-ai/mastra/blob/@mastra/server@1.36.0/packages/server/CHANGELOG.md)
#### Minor Changes
- Added delta polling support for observability list endpoints. ([#16632](https://github.com/mastra-ai/mastra/pull/16632))
```ts
const page = await client.observability.listTraces({
mode: 'page',
filters: { entityName: 'agent-1' },
});
const delta = await client.observability.listTraces({
mode: 'delta',
filters: { entityName: 'agent-1' },
after: page.deltaCursor,
});
```
Use `mode: 'delta'` to fetch only new items after the last cursor.
Page-mode responses include `pagination` and `deltaCursor` when delta polling is supported. Delta-mode responses include `delta` and do not include `pagination`.
If you read these responses directly in typed code, note that `pagination` is only included in page mode.
- Added automatic FGA metadata for stored resource routes plus optional request scope isolation for stored resource APIs. Enable protected-route coverage with provider options: ([#16651](https://github.com/mastra-ai/mastra/pull/16651))
```ts
const fga = new MastraFGAWorkos({
resourceMapping,
permissionMapping,
requireForProtectedRoutes: true,
auditProtectedRoutes: 'warn',
});
```
- Added an HTTP surface for stored agents/skills/workspaces, plus introspection endpoints for the agent-builder and an external skill-registry proxy. Studio and the client SDK use these endpoints to back the new "stored entity" management UI. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
```http
# Browse + manage stored entities (responses include favoriteCount + isFavorited)
GET /stored/agents?visibility=public&page=1&perPage=20
GET /stored/agents/:id
POST /stored/agents
PATCH /stored/agents/:id
DELETE /stored/agents/:id
# Versioning
POST /stored/skills/:id/publish
POST /stored/skills/:id/activate
POST /stored/skills/:id/restore
# Favorites
PUT /stored/agents/:id/favorite
DELETE /stored/agents/:id/favorite
# Builder introspection
GET /editor/builder/settings
GET /editor/builder/infrastructure
# External skill registry proxy (skills.sh)
GET /editor/builder/registries
GET /editor/builder/registries/:registryId/search
GET /editor/builder/registries/:registryId/popular
GET /editor/builder/registries/:registryId/skills/:owner/:repo/preview
POST /editor/builder/registries/:registryId/skills/:owner/:repo/install
```
Highlights:
- **Visibility + authorship gating.** Stored agents/skills now resolve a caller's author identity from the request context. Non-admin users only see their own + public entities. Admins see everything.
- **Favorites.** List/get responses include `favoriteCount` and the caller's `isFavorited` flag. `PUT`/`DELETE /stored/{agents|skills}/:id/favorite` toggle the favorite for the caller.
- **Avatar validation.** Stored-agent/skill metadata avatars are validated through a new `validateMetadataAvatarUrl` helper (rejects payloads over the size limit or with malformed base64).
- **Model-policy enforcement.** Stored-agent create/update routes invoke `assertModelAllowed` via the new `resolveBuilderModelPolicy` helper. Disallowed models map to HTTP 422 with a structured body — `{ code, attempted, offendingLabel, allowed }` — via `handleError`'s new `ModelNotAllowedError` mapping.
- **Builder introspection.** `GET /editor/builder/settings` returns feature flags, configuration, picker visibility, and model policy. `GET /editor/builder/infrastructure` reports browser-provider and sandbox status. Both default to `{ enabled: false }` when no `MastraEditor` is configured.
- **External skill registry.** `/editor/builder/registries/*` proxies the public skills.sh catalog so the builder UI can browse and install registered skills.
This also bumps the `@mastra/core` peer dependency floor to `>=1.34.0-0` (see the separate changeset) because the new handlers and error mapping import runtime values from `@mastra/core/agent-builder/ee`.
- 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`).
- Routes can now require **any one of multiple permissions** by passing an array to `requiresPermission`. When an array is provided, the request is allowed if the caller holds any of the listed permissions. Existing single-string usage continues to work. ([#16605](https://github.com/mastra-ai/mastra/pull/16605))
```ts
// Before — single permission only
{
path: '/v1/things',
method: 'GET',
requiresPermission: 'things:read',
handler,
}
// After — single permission or ANY-of array
{
path: '/v1/things/:id/stream',
method: 'GET',
requiresPermission: ['things:read', 'things:execute'],
handler,
}
```
Denial messages now read `Missing required permission: a or b or c` when an array is used.
**New endpoint**
`GET /api/auth/roles/:roleId/permissions` returns the resolved permission list for a role. Useful for client-side gating and admin tooling.
```ts
const res = await fetch('/api/auth/roles/admin/permissions', { credentials: 'include' });
// { "roleId": "admin", "permissions": ["*"] }
```
**Namespaced request-context keys (non-breaking)**
`coreAuthMiddleware` now writes user state under namespaced keys (`mastra__user`, `mastra__userPermissions`, `mastra__userRoles`) in addition to the existing bare keys (`user`, `userPermissions`, `userRoles`). The bare keys are still written for backward compatibility, so existing middleware, integrations, and built-in handlers that read `requestContext.get('user')` continue to work unchanged.
New code should prefer the namespaced constants to avoid collisions with caller-supplied request-context entries:
```ts
import { MASTRA_USER_KEY, MASTRA_USER_PERMISSIONS_KEY, MASTRA_USER_ROLES_KEY } from '@mastra/server/auth';
const user = requestContext.get(MASTRA_USER_KEY);
const permissions = requestContext.get(MASTRA_USER_PERMISSIONS_KEY) as string[] | undefined;
const roles = requestContext.get(MASTRA_USER_ROLES_KEY) as string[] | undefined;
```
The bare keys (`user`, `userPermissions`, `userRoles`) remain populated and are considered the documented public surface for this release; a future major release may deprecate them.
**Route permission derivation**
`getEffectivePermission()` now recognizes stored resource families (`stored-agents`, `stored-skills`, `stored-prompt-blocks`, `stored-mcp-clients`, `stored-scorers`, `stored-workspaces`) and `publish` / `activate` / `restore` action suffixes on stored-resource routes. Return type widened to `string | string[] | null` to support routes that map to multiple permissions.
#### Patch Changes
- Fixed stored resource updates to preserve existing metadata keys. ([#16651](https://github.com/mastra-ai/mastra/pull/16651))
- Hardened the stored-agent and stored-skill favorite toggle endpoints (`PUT`/`DELETE /stored/{agents,skills}/:id/favorite`) so callers can no longer favorite or unfavorite entities outside their tenant scope. ([#16749](https://github.com/mastra-ai/mastra/pull/16749))
Deployments that configure `storedResources.scope` now get the same 404-on-mismatch protection on favorite toggles that already applied to read/update/delete. Single-tenant deployments are unaffected.
Also corrected JSDoc on stored-agent and stored-skill handlers to reference the canonical resource/action names (`stored-agents:read`, `stored-skills:write`).
- Fix DELETE custom routes forwarding JSON request bodies. ([#16857](https://github.com/mastra-ai/mastra/pull/16857))
- 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))
- Fixed provider and dataset item history response types to include fields returned by the API. ([#16213](https://github.com/mastra-ai/mastra/pull/16213))
- Widened `BrowserStreamConfig.getToolset` to support async lookup. Existing synchronous implementations continue to work — the type now accepts `MastraBrowser | undefined` or `Promise<MastraBrowser | undefined>`. ([#16778](https://github.com/mastra-ai/mastra/pull/16778))
This unblocks server-adapter implementations that need to resolve agents asynchronously (for example, hydrating stored agents from storage on first browser-stream connection).
```ts
import { setupBrowserStream } from '@mastra/server';
await setupBrowserStream(app, {
getToolset: async agentId => {
const agent = await resolveAgent(agentId);
return agent?.browser;
},
apiPrefix,
});
```
- Align stored-entity authorship checks with their RBAC resource names. Stored-agent and stored-skill handlers were calling `hasAdminBypass` / `assertReadAccess` / `assertWriteAccess` / `resolveAuthorFilter` with `resource: 'agents'` and `resource: 'skills'`, but the routes are gated by `stored-agents:*` / `stored-skills:*` permissions. An admin granted `stored-agents:*` (or `stored-skills:*`) without the global `*` wildcard would pass route authorization but be treated as a non-admin inside the handler, so they could not list, read, or update private records owned by other users. Handlers now use `stored-agents` and `stored-skills` as the authorship resource string, matching the permission strings emitted by the route layer. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
- Restore backwards compatibility for the legacy `GET /api/memory/threads?orderBy=<field>&sortDirection=<dir>` query shape emitted by `@mastra/client-js` < 1.18 (and any hand-rolled HTTP clients written against pre-1.0 docs). Server 1.31.0 turned that shape into a hard 400 (`Invalid input: expected object, received undefined`); the legacy bare-string + `sortDirection` pair is now transparently fused into the current `{ orderBy: { field, direction } }` object shape before validation, so pinned clients keep working. ([#16745](https://github.com/mastra-ai/mastra/pull/16745))
Current callers using bracket notation (`orderBy[field]=...&orderBy[direction]=...`) or a JSON-stringified `orderBy` are unaffected.
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
- Fixed the playground memory configuration display for agents using observationalMemory: true. ([#16213](https://github.com/mastra-ai/mastra/pull/16213))
### [@mastra/slack@1.2.1](https://github.com/mastra-ai/mastra/blob/@mastra/slack@1.2.1/channels/slack/CHANGELOG.md)
#### Patch Changes
- - `SlackProvider.connect()` now merges with existing channel adapters instead of replacing them, preserving adapters the agent author already configured (e.g. Discord). ([#16517](https://github.com/mastra-ai/mastra/pull/16517))
- Slack interactive payloads (button clicks, modal submissions) no longer return `400 Malformed JSON body`. The provider only JSON-parses the body for the events callback path and forwards form-urlencoded payloads to the adapter's webhook handler unchanged.
- Bumped `chat` to `^4.29.0`.
### [@mastra/stagehand@0.2.3](https://github.com/mastra-ai/mastra/blob/@mastra/stagehand@0.2.3/browser/stagehand/CHANGELOG.md)
#### Patch Changes
- Silence Stagehand console logging by default and route logs through a logger hook to avoid corrupting host TUIs. ([#16677](https://github.com/mastra-ai/mastra/pull/16677))
### [@mastra/temporal@0.1.6](https://github.com/mastra-ai/mastra/blob/@mastra/temporal@0.1.6/workflows/temporal/CHANGELOG.md)
#### Patch Changes
- Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
### [@mastra/voice-openai-realtime@0.12.4](https://github.com/mastra-ai/mastra/blob/@mastra/voice-openai-realtime@0.12.4/voice/openai-realtime-api/CHANGELOG.md)
#### Patch Changes
- Fixed OpenAI Realtime voice output streaming for current audio event names. ([#16763](https://github.com/mastra-ai/mastra/pull/16763))
- Fixed user audio transcriptions missing or duplicating segments when OpenAI Realtime sends completion events. ([#16759](https://github.com/mastra-ai/mastra/pull/16759))
### Other updated packages
The following packages were updated with dependency changes only:
- [@mastra/agent-builder@1.0.37](https://github.com/mastra-ai/mastra/blob/@mastra/agent-builder@1.0.37/packages/agent-builder/CHANGELOG.md)
- [@mastra/arize@1.1.1](https://github.com/mastra-ai/mastra/blob/@mastra/arize@1.1.1/observability/arize/CHANGELOG.md)
- [@mastra/arthur@0.2.11](https://github.com/mastra-ai/mastra/blob/@mastra/arthur@0.2.11/observability/arthur/CHANGELOG.md)
- [@mastra/braintrust@1.1.1](https://github.com/mastra-ai/mastra/blob/@mastra/braintrust@1.1.1/observability/braintrust/CHANGELOG.md)
- [@mastra/laminar@1.1.1](https://github.com/mastra-ai/mastra/blob/@mastra/laminar@1.1.1/observability/laminar/CHANGELOG.md)
- [@mastra/langfuse@1.3.1](https://github.com/mastra-ai/mastra/blob/@mastra/langfuse@1.3.1/observability/langfuse/CHANGELOG.md)
- [@mastra/langsmith@1.2.1](https://github.com/mastra-ai/mastra/blob/@mastra/langsmith@1.2.1/observability/langsmith/CHANGELOG.md)
- [@mastra/longmemeval@1.0.42](https://github.com/mastra-ai/mastra/blob/@mastra/longmemeval@1.0.42/explorations/longmemeval/CHANGELOG.md)
- [@mastra/mcp-docs-server@1.1.39](https://github.com/mastra-ai/mastra/blob/@mastra/mcp-docs-server@1.1.39/packages/mcp-docs-server/CHANGELOG.md)
- [@mastra/opencode@0.0.39](https://github.com/mastra-ai/mastra/blob/@mastra/opencode@0.0.39/integrations/opencode/CHANGELOG.md)
- [@mastra/otel-bridge@1.1.1](https://github.com/mastra-ai/mastra/blob/@mastra/otel-bridge@1.1.1/observability/otel-bridge/CHANGELOG.md)
- [@mastra/otel-exporter@1.1.1](https://github.com/mastra-ai/mastra/blob/@mastra/otel-exporter@1.1.1/observability/otel-exporter/CHANGELOG.md)
- [@mastra/posthog@1.0.25](https://github.com/mastra-ai/mastra/blob/@mastra/posthog@1.0.25/observability/posthog/CHANGELOG.md)
- [@mastra/sentry@1.0.24](https://github.com/mastra-ai/mastra/blob/@mastra/sentry@1.0.24/observability/sentry/CHANGELOG.md)