🌏 中文版
Release Info
| Item | Value |
|---|---|
| Framework | Mastra |
| Version | @mastra/core@1.69.0 |
| Previous | @mastra/core@1.68.0 |
| Release date | 2026-09-24 |
| Release Notes | GitHub Release |
| GitHub | mastra-ai/mastra |
| Stars | 28.3k |
Why this release matters
The last post (1.67.0) covered agents that could generate their own workflows and wire up third-party services on their own. 1.69 fills in a different piece of infrastructure: it turns "making a judgment" into a typed primitive that can be traced and consumed directly by a workflow. Safety gating and routing decisions used to mean either an instruction buried in a prompt, or a hand-rolled helper function that calls an LLM and parses JSON back out. Neither approach gives you a consistent interface, and auditing what a given judgment actually evaluated — or how many tokens it burned — is close to impossible. Mastra 1.69's Classifier collapses this into a formal component: register it centrally on a Mastra instance, and every evaluation automatically opens a CLASSIFIER_EVALUATION tracing span. The same Classifier can act as a typed workflow step for branching, or be wrapped in a ClassifierProcessor to guard an agent's input, output, and streaming content — and the new processor fails closed by default, blocking a request outright when the judgment call itself fails rather than letting it through. Routing logic and safety policy now share the same piece of infrastructure for the first time, instead of two separate, ad hoc mechanisms.
Key Changes
- The Classifier primitive (
@mastra/core/classifier): a newClassifierclass for fixed-option evaluation, registerable vianew Mastra({ classifiers }), withgetClassifier/listClassifiers/addClassifier/removeClassifiermanagement APIs. An evaluation outside an active trace opens its own rootCLASSIFIER_EVALUATIONspan → a judgment call becomes a component you can test and observe on its own, instead of a hidden LLM call buried inside agent logic - Classifiers as typed workflow steps for branching: a workflow can chain
.classifier(router)directly into a fluent or dynamic graph, and branch conditions read the classifier's typed answer plus its token usage → hand-rolled conditional branches become a declarative.branch([...])fed by a structured judgment result ClassifierProcessor: a safety gate for agent input/output/streaming: the newClassifierProcessorplugs intoinputProcessors/outputProcessors, evaluates content through a classifier, and callsabort()fromonResultto reject a request. It fails closed by default — a failed classifier call blocks the request; opt into the old fail-open behavior witherrorStrategy: 'warn'→ safety policy no longer depends on the agent obediently following a prompt instruction, but sits in a separate layer with an explicit abort semanticcontext.background.adopt(): native background tool execution: a tool can acknowledge immediately, then hand a long-running operation to Mastra viacontext.background.adopt({ completion, cancel })for it to track completion and cancellation, instead of keepingexecute()pending → a long task (say, "research this topic for me") can confirm receipt right away while staying trackable and cancellable — though the adopted handle lives only in memory and won't survive a process restart@mastra/connect@0.3.0: ten SaaS integrations in one release: ten Nango-template-generated tool providers — Slack, GitHub, Google Mail, Google Calendar, Fireflies, PostHog, Stripe, Discord, Twitter/X, and HubSpot. Once a Mastra Platform connection is set up,tools: connect()resolves the right tools per request → agents no longer need hand-written tool wrappers to reach these services- More reliable durable execution on Inngest: workflows and durable agents accept a new
retriesoption, so a run can survive a process restart or redeploy by retrying and continuing past completed steps.resumeStream(),approveToolCall()and related resume methods fix two bugs — durable execution getting lost after an editor override, and a suspended run failing to find its snapshot → a long-running durable agent no longer fails outright over a single deploy
Breaking Changes
@mastra/playground-ui:@mastra/playground-ui/lib/springsis removed;FluidHoverHighlightnow only acceptshoverandclassName- Affected: projects customizing Mastra Studio UI with
FluidHoverHighlightor the spring animation API directly
- Affected: projects customizing Mastra Studio UI with
@mastra/playground-ui:PageLayout/shell APIs were reworked —PageLayoutRoot,MainContentLayout,MainContentContent, and severalAppShellheader-related props/contexts are removed. Migrate to the newPageLayout(breadcrumbs,headerActions,actionRow)- Affected: projects customizing Mastra Studio pages with these layout components
- Trace grouping is now deprecated across Core/Server/Client: the
groupoption onqueryTraces()and the trace-query contract is deprecated in favor ofqueryTraceThreads()/thequeryThreadscontract (still functional until the next major release)- Affected: code querying traces with
group: { by: ['threadId'] }
- Affected: code querying traces with
Migration Guide
Upgrading from 1.68.x to 1.69.0
pnpm add @mastra/core@1.69.0
// Before (1.68.x and earlier, playground-ui)
import { FluidHoverHighlight } from '@mastra/playground-ui/lib/springs';
<FluidHoverHighlight hover={hover} spring={mySpringConfig} className="rounded-lg" />;
// After (1.69.0)
import { FluidHoverHighlight } from '@mastra/playground-ui';
const hover = useFluidHover(containerRef);
<FluidHoverHighlight hover={hover} className="rounded-lg" />;
// Before: grouped trace query
await mastraClient.queryTraces({ timeRange, group: { by: ['threadId'] } });
// After: query threads instead
await mastraClient.queryTraceThreads({ traces: { timeRange } });
Projects that don't customize Mastra Studio's playground-ui components and don't use grouped trace queries have no breaking changes here — just upgrade.
Comparison with other frameworks
LangGraph's conditional branching (the when() syntax) wires a hand-written Python predicate function into the graph — the judgment logic itself is never a first-class part of the framework. Mastra's Classifier goes the other way: it structures the LLM judgment itself into a typed component with a management API and automatic tracing, then lets both workflows and agent input/output guards consume the same primitive. That's a different problem from what Composio solves with integration aggregation ("agents need to call lots of tools"); Mastra is addressing something more fundamental here — "agents need to make judgments." Safety gating and routing branches used to be two separately hand-rolled pieces of logic; now they're two uses of the same component.
Today's Takeaway
I used to think agent safety gating meant adding a line to the system prompt asking the model to "please refuse unsafe requests." Seeing ClassifierProcessor fail closed by default, as a component sitting outside the agent's main execution path, changed that: the reliability of a safety policy shouldn't rest on whether the model obediently follows a prompt instruction. It should be a piece of infrastructure with an explicit abort semantic — one that blocks by default when the judgment itself fails, rather than letting things through. That's a different order of guarantee than a few extra sentences in a prompt.
References
- Mastra @mastra/core@1.69.0 — GitHub Release
- mastra-ai/mastra — GitHub
- Mastra @mastra/core@1.67.0 — previous framework update
- PR #24738: Classifier registration API
- PR #24747: Classifier as a typed workflow step
- PR #24768:
ClassifierProcessor - PR #24793:
ClassifierProcessorfails closed by default - PR #24418:
context.background.adopt() - PR #24606: ten new
@mastra/connectproviders - PR #24741:
retriesoption for Inngest workflows/durable agents
Loading...