github mastra-ai/mastra @mastra/core@1.74.0
October 1, 2026

3 hours ago

Highlights

Tool Context Can Read the Full Conversation (agent.getMessages())

Tools now have access to the current conversation state via context.agent.getMessages() in both standard and durable agent loops, including remembered messages and in-run responses—enabling richer, context-aware tool behavior without changing the existing input-only messages field.

Observational Memory History Search (Filtering, Ordering, Record Lookup)

getObservationalMemoryHistory gained group filtering (groupId), explicit ordering (sortDirection), and direct lookup by recordId, with adapter capability signaling via supportsObservationalMemoryHistorySearch (notably affecting multiple DB adapters; Convex requires a server function redeploy for the new filters to apply).

Memory Recall Can Page Through Observation Groups Around Search Hits

Recall now supports paging “before/after” from a matched groupId, including groups condensed by reflection and buffered-but-not-yet-activated groups—improving investigation workflows without requiring re-indexing, alongside clearer, chronologically ordered search results and better first-turn retrieval guidance.

Playground UI: New Accessible Form Field Primitives (Field, Fieldset, Form, SearchInput)

A new set of form-building components standardizes label/description/error wiring without manual id/htmlFor, improving accessibility and consistency; includes new Form and SearchInput, plus deprecations of the older *FieldBlock approach to move toward a single, safer pattern.

Breaking Changes

  • @mastra/playground-ui: anchorTraceId removed from ThreadViewByTrace, TraceThreadPanel, and ThreadTrace; ThreadTrace.LoadMoreSentinel removed. Use pageSize and onLoadOlder on ThreadTrace to control pagination/loading older turns.

Changelog

@mastra/core@1.74.0

Minor Changes

  • Added agent.getMessages() to tool execution context in standard and durable agent loops. Tools can read the current conversation, including remembered messages and in-run responses, without changing the existing input-only messages field. (#25525)

    execute: async (input, context) => {
      const messages = context?.agent?.getMessages?.() ?? [];
      return { messageCount: messages.length };
    };

    The getter reflects message-list removals, but not transient transforms applied only to the provider prompt. Treat returned messages as read-only.

  • Added group filtering and generation ordering to observational memory history. For example, getObservationalMemoryHistory(threadId, resourceId, 1, { groupId, sortDirection: "ASC" }) finds the earliest retained record containing a group in active observations or persisted buffered chunks. Adapters advertise support through supportsObservationalMemoryHistorySearch. Pass recordId to read one record by ID; it only matches records for the requested thread or resource. (#25525)

    Convex users need to redeploy their Mastra server functions for these filters to apply.

    Also in: @mastra/convex@1.7.0, @mastra/libsql@1.25.0, @mastra/mongodb@1.21.0, @mastra/mysql@0.12.0, @mastra/oracledb@0.5.0, @mastra/pg@1.29.0

Patch Changes

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

  • Fixed chat channel agents ignoring mentions of their current display name after being renamed. For example, a Slack app renamed from acme-bot to helper now responds to @helper in channels, instead of only recognising its original username. The bot's current profile name is looked up once through the adapter and exposed as botDisplayName on the channel context. (#25652)

  • Raise transitive security dependency floors (dompurify, js-yaml, @ai-sdk/provider-utils) and bump nested/template deps (nodemailer, fastify, hono, ajv) for the 2026-10-01 Vanta remediation pass. (#25694)

@mastra/factory@0.19.1

Patch Changes

  • Repository-backed Slack sessions can now recover from a failed gh authentication attempt without restarting the session. Refresh GitHub access, then retry the failed command: (#25545)

    github_refresh_token({})
    
  • Fixed Slack-triggered Factory runs failing with "No usable credential" after a server restart. Slack mentions, DMs, and thread replies now load the linked user's model credentials before the run starts, instead of relying on that user having opened the web UI first. (#25653)

@mastra/memory@1.35.0

Minor Changes

  • Page through observation groups. Recall can now read the original observation groups around a search hit, including groups condensed away by reflection and buffered groups that haven't been activated yet. Existing records work without re-indexing. (#25525)

    recall({ mode: 'observations', groupId: 'group-id-from-search', direction: 'after', limit: 5 });

    Easier-to-read search results. Search results are dated, listed oldest first, and mark where groups may be hidden between hits. Hits already in the agent's context come back as short references, so more new hits fit. When a long group is shortened, its excerpt starts at the line that best matches the query.

    Better recall guidance. With retrieval enabled, the agent gets recall guidance from the first turn, including in read-only runs. It explains how to search, page, and confirm details against source messages, treats what the user said as authoritative and what the assistant proposed as a suggestion, and labels reflected groups as lossy summaries.

@mastra/playground-ui@60.2.0

Minor Changes

  • Added Field components for building form fields: Field, FieldLabel, FieldDescription, FieldError, FieldContent, FieldItem, Fieldset and FieldsetLegend, from @mastra/playground-ui/components/Field. They are built on Base UI Field and Fieldset. Put a label and any control inside a Field, and the label names the control. The description and error are linked to it too, and the control is marked invalid, with no ids to pass around. The part names follow shadcn/ui, but unlike shadcn, FieldLabel needs no htmlFor and the control no id. Code copied from shadcn that still passes them keeps working. (#25317)

    // Before
    <TextFieldBlock name="email" label="Email" helpText="Used to sign in." errorMsg={errors.email?.message} required />
    
    // After
    <Field invalid={Boolean(errors.email)}>
      <FieldLabel required>Email</FieldLabel>
      <Input {...register('email')} />
      <FieldDescription>Used to sign in.</FieldDescription>
      <FieldError>{errors.email?.message}</FieldError>
    </Field>

    This works for Input, Textarea, InputGroupInput, InputGroupTextarea, Select, Combobox, Checkbox, Switch, RadioGroup and CodeEditor. For a control that is not built on Base UI, such as a custom popover trigger, spread useFieldControlAria() on it to get the same label, description and invalid wiring. To hide a label and keep it for screen readers, use <FieldLabel className="sr-only">. To put the label beside the control, use <Field orientation="horizontal">: the row is centred, and when the label comes first the control sits at the far end, so a settings toggle needs no extra classes. Use orientation="responsive" to stack it on small screens. For a radio group, use <Fieldset render={<RadioGroup />}> with a FieldsetLegend, and wrap each option in a FieldItem.

    A Field holds one control. When one title covers several controls, use a Fieldset with a FieldsetLegend (it takes required like FieldLabel), and name each control with its own aria-label. For a settings row, use the new SettingsFieldsetRow:

    <SettingsFieldsetRow label="Releases" description="Where new issues go.">
      <SelectTrigger aria-label="Factory for Releases">…</SelectTrigger>
      <SelectTrigger aria-label="Board for Releases">…</SelectTrigger>
    </SettingsFieldsetRow>

    A control that has its own aria-label keeps that name inside a Field too, the same way aria-label wins over a native <label>.

    Labels are styled by the Field: a label beside a Checkbox, Switch or radio shows a pointer cursor, so no cursor-* or color classes are needed. To disable a field, put disabled on the Field, FieldItem or Fieldset rather than on the control: the control is disabled through it, and only then does the label show it can't be clicked. For compact rows, use <FieldLabel size="smaller">.

    Added Form (@mastra/playground-ui/components/Form), built on Base UI Form, with one standard gap between fields. Put a <FieldError /> with no children in a field that uses required, type="email", min or max: when a user submits an invalid value, the form stops, focuses that field and shows the browser's message there.

    Added SearchInput (@mastra/playground-ui/components/SearchInput), a search box with a hidden label, a search icon and a clear button that puts focus back in the field. It updates on every keystroke. Pass onClose for a search that collapses: the button then reads "Close search", stays visible and calls onClose after clearing. ListSearch is now built on it and adds the 300 ms debounce and the Cmd/Ctrl+Shift+F shortcut. Emptying a ListSearch, by typing or with the clear button, now calls onSearch('') right away. Both render <input type="search">, so tests find them by role searchbox instead of textbox.

    TimePicker takes an optional label (default "Time") that names its group, and its hour, minute and AM/PM selects now have names. DateTimeRangePicker labels its pickers "Start time" and "End time".

    InputGroupInput now types in the same text style as Input (text-label, 13px medium) at every size, instead of a lighter body style that shrank to 12px at sm. Search boxes, environment variable rows and comment inputs now match the text fields around them.

    Why

    Before, there were three ways to build a field: the *FieldBlock components, FieldBlock parts with hand-built ids, and Label with htmlFor. Mistakes in the id wiring left fields without an accessible name, such as hidden labels that were dropped and radio labels pointing at a div. Now there is one way to build a field, and it links the label, description and error for you.

    Deprecated

    These still work as before, so existing code keeps building. Studio and Factory no longer use them. They stay until no consumer does, then a later release removes them:

    • TextFieldBlock, TextareaFieldBlock, SelectFieldBlock, SearchFieldBlock, FieldBlock, FieldBlocksLayout and fieldErrorId (@mastra/playground-ui/components/FormFieldBlocks): build fields with the Field components. A select without a visible label, such as a toolbar filter, needs no Field: name it with <SelectTrigger aria-label="…">. For a search box, use SearchInput, which keeps SearchFieldBlock's immediate updates, or ListSearch for a list filter. ListSearch calls onSearch 300 ms after typing stops, and needs shortcutDisabled on a second search box on the same page.
    • FieldBlock.ErrorMsg for a message that belongs to no single control, such as a server error under a form: FieldError throws outside a Field, so wrap it in <Field invalid>.
    • Label (@mastra/playground-ui/components/Label): use FieldLabel inside a Field. For a group title, use FieldsetLegend inside a Fieldset.
    • The error prop on Input, Textarea, InputGroupInput and InputGroupTextarea: use <Field invalid>, or set aria-invalid on a control outside a Field.
    • The error and name props on Combobox, and the root and error keys of comboboxStyles: wrap the combobox in <Field invalid> with a FieldError.
    • The htmlFor prop on SettingsRow: pass the control as a child without an id, and the row's label names it.

    Changed

    • JSONSchemaForm.FieldName, JSONSchemaForm.FieldDescription and JSONSchemaForm.FieldType no longer accept the old TextFieldBlock or SelectFieldBlock props. FieldName and FieldDescription take label, labelIsHidden and the props of their input. FieldType takes label, labelIsHidden, placeholder, size, disabled and className.

Patch Changes

  • Added a repeat option to useKeydown. Set it to false so holding a key runs the handler once instead of on every key repeat, which suits toggles: (#25438)

    useKeydown({ '[': toggleSidebar }, { repeat: false });
  • Fixed SelectTrigger and Combobox triggers shrinking to their content instead of filling their field. Pickers in settings rows and forms line up with the container edge again. Combobox triggers with iconOnlyValue stay compact. (#25591)

  • Made SettingsRow give select and combobox controls one shared width (16rem) beside the label, so pickers line up across rows without each call site sizing them. A width class on the trigger still overrides it, and stacked rows on small screens keep full-width controls. Added a SettingsRow Storybook story. (#25635)

  • Fixed the thread view firing repeated scores requests for every trace. Scores now load only when a trace's Scores tab is open, and the tab no longer shows a count. (#25683)

  • The trace thread view now reads like a chat. It opens on the latest turns, stays on the newest turn while messages and spans load, and loads older turns as you scroll up without moving what you are reading. It now searches the last 31 days of traces, up from 30 (no limit when trace query is unavailable), and the new pageSize prop sets how many turns load at a time (default 10). (#25693)

    Breaking: anchorTraceId was removed from ThreadViewByTrace, TraceThreadPanel and ThreadTrace, and ThreadTrace.LoadMoreSentinel was removed. Pass onLoadOlder to ThreadTrace to load older turns.

    // Before
    <ThreadViewByTrace threadId={threadId} anchorTraceId={traceId} />
    
    // After
    <ThreadViewByTrace threadId={threadId} pageSize={20} />
  • Reduce observability polling in Studio: (#25705)

    • Thread view: stop fetching and polling feedback for every trace row just to show a count on the Feedback tab. Feedback is now only loaded while a row's Feedback tab is open, matching the Messages and Scores tabs.
    • Slow down the default refetch intervals: feedback polls every 30s (was 3s), scores and trace span scores every 15s (was 5s / 3s).

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.