github mastra-ai/mastra @mastra/core@1.35.0
May 15, 2026

4 hours ago

Highlights

FGA Route Policy Coverage + Resolver Hooks (Core/Server/WorkOS)

New FGA route policy coverage controls add guardrails for protected routes, with built-in resource route metadata resolution and resolver hooks so you can centrally map route → {resourceType, resourceId, permission} while still overriding per-route config.

Favorites Storage Domain for Agents/Skills (Core + Storage Adapters)

A new favorites storage domain lets users favorite/unfavorite stored agents and skills, and adds visibility (private|public) and favoriteCount fields so listings can be filtered and ordered by favorite state (e.g., pinFavoritedFor, favoritedOnly).

Favorites Support Across Major Storage Backends

Favorites is implemented across multiple adapters (@mastra/pg, @mastra/libsql, @mastra/mongodb, @mastra/clickhouse, @mastra/cloudflare), enabling consistent favoriting/visibility queries regardless of your chosen persistence layer.

Observational Memory: Accurate Token Estimation for Large File Parts

@mastra/memory improves local token estimation for non-image file parts (notably large PDFs), preventing observational memory from missing thresholds and replaying excessive history when provider token-count endpoints aren’t available.

Reliability Fixes for Workspaces, Workflows, and Route Matching

Multiple fixes improve correctness: workspace PATCH no longer overwrites stored values with undefined, scheduled workflows created via @mastra/core/workflows apply schedules correctly, NestJS adapter prefix matching is stricter, and a circular ESM import crash in @mastra/core/workflows/workflow is resolved.

Breaking Changes

  • None called out in this changelog.

Changelog

@mastra/core@1.35.0

Minor Changes

  • Added FGA route policy coverage controls, built-in resource route metadata resolution, and resolver hooks. (#16485)

    For example:

    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)

    Existing rows without visibility or favoriteCount continue to work; the new fields and APIs are opt-in.

    Example

    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)

  • 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)

  • Fixed active signals so they stay in the correct order when conversations are reloaded from memory. (#16623)

  • Fixed scheduled workflows created from the public @mastra/core/workflows entry point so declared schedules are applied correctly. (#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)

@mastra/auth-workos@1.4.0

Minor Changes

  • Added FGA route policy coverage controls, built-in resource route metadata resolution, and resolver hooks. (#16485)

    For example:

    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 };
      },
    });

Patch Changes

  • Fixed WorkOS FGA missing resources so authorization checks deny access instead of surfacing provider errors. (#16485)

@mastra/clickhouse@1.8.0

Minor Changes

  • Added favorites support to storage adapters so callers can favorite/unfavorite stored agents and skills, query favorite state alongside list results, and filter listings by visibility. (#16580)

    Example

    const storage = new LibSQLStore({
      /* config */
    });
    const favorites = await storage.getStore('favorites');
    
    await favorites?.favorite({
      userId: 'user-1',
      entityType: 'agent',
      entityId: 'agent-42',
    });

Patch Changes

  • Bumped @mastra/core peer dependency floor to >=1.34.0-0 so the new @mastra/core/storage/domains/favorites subpath is available. Older @mastra/core versions don't ship the FavoritesStorage base class these adapters now extend. (#16580)

@mastra/cloudflare@1.4.0

Minor Changes

  • Added favorites support to storage adapters so callers can favorite/unfavorite stored agents and skills, query favorite state alongside list results, and filter listings by visibility. (#16580)

    Example

    const storage = new LibSQLStore({
      /* config */
    });
    const favorites = await storage.getStore('favorites');
    
    await favorites?.favorite({
      userId: 'user-1',
      entityType: 'agent',
      entityId: 'agent-42',
    });

Patch Changes

  • Bumped @mastra/core peer dependency floor to >=1.34.0-0 so the new @mastra/core/storage/domains/favorites subpath is available. Older @mastra/core versions don't ship the FavoritesStorage base class these adapters now extend. (#16580)

@mastra/libsql@1.11.0

Minor Changes

  • Added favorites support to storage adapters so callers can favorite/unfavorite stored agents and skills, query favorite state alongside list results, and filter listings by visibility. (#16580)

    Example

    const storage = new LibSQLStore({
      /* config */
    });
    const favorites = await storage.getStore('favorites');
    
    await favorites?.favorite({
      userId: 'user-1',
      entityType: 'agent',
      entityId: 'agent-42',
    });

Patch Changes

  • Bumped @mastra/core peer dependency floor to >=1.34.0-0 so the new @mastra/core/storage/domains/favorites subpath is available. Older @mastra/core versions don't ship the FavoritesStorage base class these adapters now extend. (#16580)

  • Fixed a workspace PATCH bug: omitted config fields in a PATCH no longer overwrite previously-persisted values with undefined. (#16580)

@mastra/memory@1.18.2

Patch Changes

  • Fixed thread deletion so it also clears thread-scoped observational memory. (#16628)

  • Fixed Observational Memory missing the observation threshold for messages with large file parts. Previously TokenCounter's local/sync counting path only stringified the file descriptor (type, mimeType, filename) for non-image files, so a 100KB PDF looked like ~8 tokens to OM and the conversation kept replaying the full unobserved history past every reasonable threshold. (#16562)

    TokenCounter now estimates non-image file part tokens locally from the attachment's byte size and mime type using a per-provider heuristic, mirroring the existing local image-token estimator:

    • Anthropic PDFs ≈ bytes / 3 (floor 1500)
    • Google PDFs ≈ bytes / 20 (floor 258)
    • OpenAI / unknown PDFs ≈ bytes / 4 (floor 500)
    • Text-ish mime types (text/*, JSON, XML, YAML) ≈ bytes / 4
    • Other binary ≈ bytes / 4

    URL-only file parts (no body to size) keep the previous descriptor-only local estimate. countMessagesAsync() continues to prefer provider token-count endpoints for supported providers; this change only improves the local fallback used when no provider endpoint is available.

    // Before: this PDF counted as ~8 tokens locally regardless of size, so OM never triggered.
    const part = {
      type: 'file',
      data: largePdfBase64,
      mimeType: 'application/pdf',
      filename: 'report.pdf',
    };
    // counter.countMessage(message) ≈ 8
    
    // After: estimated locally from byte size on the active provider.
    // counter.countMessage(message) ≈ tens of thousands of tokens
    //   → OM threshold trips as expected.

    The internal token-estimate cache version was bumped, which invalidates persisted estimates from older @mastra/memory releases on the next read; entries are recomputed automatically.

    Fixes #16522

@mastra/mongodb@1.9.0

Minor Changes

  • Added favorites support to storage adapters so callers can favorite/unfavorite stored agents and skills, query favorite state alongside list results, and filter listings by visibility. (#16580)

    Example

    const storage = new LibSQLStore({
      /* config */
    });
    const favorites = await storage.getStore('favorites');
    
    await favorites?.favorite({
      userId: 'user-1',
      entityType: 'agent',
      entityId: 'agent-42',
    });

Patch Changes

  • Bumped @mastra/core peer dependency floor to >=1.34.0-0 so the new @mastra/core/storage/domains/favorites subpath is available. Older @mastra/core versions don't ship the FavoritesStorage base class these adapters now extend. (#16580)

@mastra/nestjs@0.1.6

Patch Changes

  • Fixed NestJS route matching so configured prefixes are enforced and partial prefix matches are ignored. For example, a prefix of /api no longer matches /apiish/agents; only /api and /api/* are treated as Mastra routes. (#16637)

@mastra/pg@1.11.0

Minor Changes

  • Added favorites support to storage adapters so callers can favorite/unfavorite stored agents and skills, query favorite state alongside list results, and filter listings by visibility. (#16580)

    Example

    const storage = new LibSQLStore({
      /* config */
    });
    const favorites = await storage.getStore('favorites');
    
    await favorites?.favorite({
      userId: 'user-1',
      entityType: 'agent',
      entityId: 'agent-42',
    });

Patch Changes

  • Fixed a workspace PATCH bug: omitted config fields in a PATCH no longer overwrite previously-persisted values with undefined. (#16580)

  • Bumped @mastra/core peer dependency floor to >=1.34.0-0 so the new @mastra/core/storage/domains/favorites subpath is available. Older @mastra/core versions don't ship the FavoritesStorage base class these adapters now extend. (#16580)

@mastra/playground-ui@28.0.1

Patch Changes

  • Fixed the Observability traces page on storage providers that don't support the Branches list mode. The page now falls back to Traces mode, hides the Branches option in the filter, and shows a dismissible notice instead of a full-screen error. (#16601)

  • Improved the Observability traces list to make the with-subtraces view more discoverable. (#16643)

    • Added: A Level column whose icon distinguishes top-level Trace rows from nested Subtrace rows.
    • Added: A tooltip legend on the Level header showing both icons side by side.
    • Added: A standalone Show subtraces toggle next to Add Filter — off keeps the default top-level view, on includes subtraces.
    • Removed: The List mode entry from the Add Filter menu (now driven by the toggle).

    Usage: Open Observability → Traces → switch Show subtraces on. The Level column updates: top-level rows keep the Trace icon, nested rows show the Subtrace (↳) icon. The toggle is hidden automatically when the active storage provider doesn't support subtraces.

  • Removed the "Group traces by thread" option from the Observability traces page. The list now always displays a flat view of traces, without thread-id subheaders. To narrow results to a specific thread, use the Thread ID property in the Add filter menu (open Observability → Traces → Add filter → Thread ID → paste the threadId). (#16633)

  • Polished the property filter dropdown so the chevron icon next to each option keeps the same shape when its side panel opens (#16635)

@mastra/server@1.35.0

Minor Changes

  • Added FGA route policy coverage controls, built-in resource route metadata resolution, and resolver hooks. (#16485)

    For example:

    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 };
      },
    });

Patch Changes

Other updated packages

The following packages were updated with dependency changes only:

Don't miss a new mastra release

NewReleases is sending notifications on new releases.