@ag-ui/mastra

中文文档
2.0.2发布于 2026/10/31Apache-2.0TypeScriptESM + CJS构建来源已验证近 30 天下载 65.8万

Implementation of the AG-UI protocol for Mastra.

原始使用文档
文档目录9 节
  1. Installation
  2. Usage
  3. Features
  4. Interrupts (tool suspend/resume)
  5. Tool approval
  6. How a run ends
  7. Sub-agents
  8. Reasoning and tool results
  9. To run the example server in the dojo

@ag-ui/mastra

Implementation of the AG-UI protocol for Mastra.

Connects Mastra agents (local and remote) to frontend applications via the AG-UI protocol. Supports streaming responses, memory management, and tool execution.

Installation

Install the @ag-ui/mastra package:

# npm
npm install @ag-ui/mastra
# pnpm
pnpm add @ag-ui/mastra
# yarn
yarn add @ag-ui/mastra

Install the required peer dependencies:

npm install @mastra/client-js @mastra/core @ag-ui/core @ag-ui/client

The optional CopilotKit integration is available from @ag-ui/mastra/copilotkit. Install its peer dependency only when using that entry point. It needs @copilotkit/runtime ^1.76.0, which uses AG-UI 1.0 agent types and protocol. This raises the optional runtime peer from ^1.60.1; applications using this entry point must upgrade CopilotKit. The runtime and shared development dependencies also use 1.76.0 so integration tests exercise that baseline:

npm install @copilotkit/runtime@^1.76.0

Usage

import { MastraAgent } from "@ag-ui/mastra";
import { mastra } from "./mastra"; // Your Mastra instance

// Create an AG-UI compatible agent
const agent = new MastraAgent({
  agent: mastra.getAgent("weather-agent"),
  resourceId: "user-123",
});

// Run with streaming
const result = await agent.runAgent({
  messages: [{ role: "user", content: "What's the weather like?" }],
});

Features

  • Local & remote agents – Works with in-process and network Mastra agents
  • Memory integration – Automatic thread and working memory management
  • Tool streaming – Real-time tool call execution and results
  • State management – Bidirectional state synchronization
  • Human-in-the-loop – Mastra tool suspend/resume bridged to AG-UI interrupts

Interrupts (tool suspend/resume)

When a Mastra tool suspends, the bridge ends the run with RunFinishedEvent.outcome = { type: "interrupt", interrupts }. Each suspend maps to an Interrupt (reason, toolCallId, responseSchema parsed from resumeSchema, and message when the suspend payload has a string message); the Mastra payload (toolName, suspendPayload, args, resumeSchema and the snapshot-keying runId) lives under metadata.mastra. Its id is `${runId}::${toolCallId}`: a client only round-trips interruptId on resume, so the snapshot runId is encoded into the id and decoded back out.

A run reports at most one interrupt, because a resume can continue only one suspended call. Mastra runs suspendable and approval-gated tools one at a time, so a later call pauses on the resumed run instead. If a stream still pauses a second call, the bridge logs a warning and leaves it out of the outcome.

Resume with one RunAgentInput.resume entry for that id. A resolved entry passes its payload to Mastra's resumeStream; a cancelled entry declines the call and ends the run without resuming. This needs a client that reads the interrupt outcome and sends RunAgentInput.resume, such as CopilotKit >= 1.76.0.

Remote interrupt and approval support requires an agent handle with a callable resumeStream. Older @mastra/client-js versions remain supported for ordinary streaming, but getCapabilities().humanInTheLoop reports supported, interrupts, and approvals as false when that method is unavailable. Attempting to resume through such a handle reports an upgrade error.

Tool approval

Mastra's native approval gate is bridged to AG-UI interrupts. Mark a tool with requireApproval: true, or set requireToolApproval: true in the agent's defaultOptions to gate every tool:

const recordExpense = createTool({
  id: "record-expense",
  inputSchema: z.object({ amount: z.number() }),
  requireApproval: true,
  execute: async ({ amount }) => ({ recorded: true, amount }),
});

Mastra pauses the call before execute runs and streams tool-call-approval. The bridge holds back that tool call and ends the run with an interrupt whose reason is mastra:tool_approval, with the call's toolCallId, responseSchema (Mastra's { approved: boolean } schema), and toolName, args and the snapshot runId under metadata.mastra. Its id is `mastra-approval::${runId}::${toolCallId}`, and metadata.mastra.type is mastra_tool_approval.

Storage. The paused call lives in Mastra's workflow snapshot until the user decides, and the resume run loads it from storage. Configure persistent storage on the Mastra instance, and give the agent Memory backed by a persistent store so the thread keeps the settled tool call. For remote agents this is the server's storage. Don't use an in-memory libsql URL (:memory:): with pooled connections each connection gets its own empty database, so the snapshot is missing on resume. Use a file URL such as file:./mastra.db instead.

Approval UI. With CopilotKit v2, render Approve and Reject from useInterrupt, and have both call resolve. event.value is the Interrupt.

useInterrupt({
  agentId: "tool_approval",
  renderInChat: true,
  enabled: (event) =>
    (event.value as Interrupt)?.reason === "mastra:tool_approval",
  render: ({ resolve }) => (
    <ApprovalCard
      onApprove={() => resolve({ approved: true })}
      onReject={() => resolve({ approved: false })}
    />
  ),
});

Reject with resolve({ approved: false }) or cancel().

Resume. Send one entry for the interrupt id:

  • { status: "resolved", payload: { approved: true } } approves (so does payload: true).
  • { status: "resolved", payload: { approved: false } } declines.
  • { status: "cancelled" } declines, whatever payload it carries.
  • Any other resolved payload (none, null, {}, { approve: true }, { approved: "yes" }, a string) fails the run with a RUN_ERROR coded MASTRA_INVALID_TOOL_APPROVAL. Mastra is not called, so the approval stays pending and can still be answered.

The bridge then completes the original call, keyed by the snapshot runId and toolCallId: local agents call Mastra's approveToolCall or declineToolCall, and remote agents call resumeStream({ approved }), which is what those calls do on the server. The resumed run streams the original call with its result: the tool's output when approved, or Mastra's decline message when declined, without running the tool.

How a run ends

  • A run stopped on purpose (abortRun(), the remote handle's own ClientOptions.abortSignal, or Mastra's own abort) closes what it opened and ends with RUN_FINISHED carrying outcome: { type: "cancelled" }. A run whose subscriber unsubscribed is abandoned and sends nothing more.
  • A run that stops on frontend tool calls it left unanswered finishes as success and names them in outcome.pendingToolCallIds. Any other call the run left without a result (a server call, a backgrounded one, the A2UI render subagent's) gets a placeholder TOOL_CALL_RESULT first, so a consumer that derives the pending calls from the stream sees only the frontend ones.
  • When Mastra reported why the run ended (its finish reason: stop, length, tool-calls, ...), RUN_FINISHED carries it unchanged as metadata.mastra.finishReason, so a client can tell a turn cut off by the step limit or the length limit from a finished answer. A cancelled run carries none.
  • RUN_STARTED declares the AG-UI protocolVersion the bridge speaks, and getCapabilities() returns the adapter's AG-UI capabilities declaration.

Sub-agents

A Mastra supervisor delegates to its sub-agents (agents: { … }) through agent-<name> tool calls. Two options choose what the client sees of a delegation:

new MastraAgent({
  agent: supervisor,
  resourceId: "user-123",
  subagentVisibility: "attributed", // default "hidden"
  subagentToolResults: "omit", // default "full"
});
  • subagentVisibility: "hidden" (the default) keeps the bridge as it was: the client sees the delegating tool call and its result, and nothing of the sub-agent's own stream.
  • subagentVisibility: "attributed" makes each delegation an AG-UI subagent invocation: SUBAGENT_STARTED, then the sub-agent's text, reasoning and tool calls streamed live and tagged with its subagentRunId, then SUBAGENT_FINISHED or SUBAGENT_ERROR. A nested delegation's subagentRunId is its parent's followed by its own call id (D1/d9), so the run that resumes a suspended invocation announces the same id again. Needs an AG-UI 1.0 client.
  • subagentToolResults: "omit" sends an attributed sub-agent's own tool results empty (a failed call keeps its error), to keep large results off the wire. The delegation's own result, which the supervisor's model reads, is never omitted.
  • A sub-agent that fails ends with SUBAGENT_ERROR and the code MASTRA_SUBAGENT_ERROR (its model or a tool failed), MASTRA_TRIPWIRE (a processor blocked it) or CANCELLED (the run stopped first), with a message and never a stack. Only its invocation ends: the supervisor gets the delegation's result and the run goes on.
  • getCapabilities() of a local supervisor in "attributed" mode declares multiAgent with its sub-agents and their descriptions.
  • RUN_FINISHED usage includes every sub-agent's model calls in either visibility, one entry per provider and model. A local supervisor's sub-agents are labelled with their own models; a remote one's stay unlabelled, as its own usage does. Mastra forwards none of a sub-agent's usage while it is paused, so the run that resumes it counts the sub-agent's calls from before the pause too: each of them is counted once across the two runs.

A sub-agent's data-* parts, workflows used as tools and agent.network() are not attributed.

Reasoning and tool results

  • A reasoning span's provider artefacts (an Anthropic thinking signature or redacted block, an OpenAI reasoning item id and encrypted content) are sent as REASONING_ENCRYPTED_VALUE for the reasoning message. When that message comes back in the run input, directly ahead of its assistant message, the bridge hands the reasoning back to Mastra with those artefacts.
  • A tool whose toModelOutput returns the content form ({ type: "content" }) reports its result as AG-UI content parts in TOOL_CALL_RESULT; any other result is the JSON string it always was.
  • A tool message given as content parts (a frontend tool's answer, or a server tool's result the client sends back on a later turn) keeps its text as the raw result and hands Mastra its parts as the tool's model output:
    • text is a text item, and data bytes are media with their mimeType. A data source without a string value or a mimeType is dropped with a warning.
    • a URL is never sent as media: an image URL (an image/* mimeType, or an image part with none) is image-url, any other is file-url, and a data: URI is read as the bytes it holds.
    • a provider file handle is file-id or image-file-id.
  • Whether the model then sees an item is up to Mastra and the provider, not the bridge. Mastra's model router (model: "openai/gpt-4.1-mini" and the like) drops media items in a tool result, so base64 images and documents do not reach those models, on the first turn as well. Of the providers tested, none renders a provider file id in a tool result, @ai-sdk/anthropic 2 (AI SDK v5) has no URL form for tool output, and @ai-sdk/openai 3 drops file-url there.
  • Only the content form is replayed: for a tool whose toModelOutput returns text or json, a later turn gives the model the raw result instead.
  • Provider file handles (the file source) on user messages are dropped with a warning: Mastra has no input channel for a provider file id.

To run the example server in the dojo

cd integrations/mastra/typescript/examples
pnpm install
pnpm run dev

版本与发布记录

@ag-ui/mastra 共发布 43 个版本,首次发布于 2025/06/10;过去 12 个月发布了 24 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.0.2latest2026/10/318 天前
2.0.12026/10/1326 天前
2.0.02026/10/1226 天前
1.1.62026/10/021 个月前
1.1.52026/09/301 个月前
1.1.42026/09/151 个月前

其他发布通道:next → 0.1.0-next.1,beta → 0.2.1-beta.2,canary → 1.0.2-canary.1777064626.0,alpha → 1.1.0-alpha.0。

关于 @ag-ui/mastra 的常见问题

@ag-ui/mastra 是什么?

Implementation of the AG-UI protocol for Mastra.

如何安装 @ag-ui/mastra?

在项目目录运行 npm install @ag-ui/mastra,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@ag-ui/core(>=1.0.0)、@mastra/core(>=1.29.0 <2.0.0-0)、@ag-ui/client(>=1.0.0)、@mastra/client-js(>=1.0.0-0 <2.0.0-0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@ag-ui/mastra 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@ag-ui/mastra 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@ag-ui/mastra 可以商用吗?

@ag-ui/mastra 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@ag-ui/mastra 的下载量有多少?

根据 npm 官方下载统计,@ag-ui/mastra 在 2026/10/05 – 2026/11/03 这 30 天内被下载 658,067 次,日均约 21,936 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ag-ui/mastra 还在维护吗?

最新版本 2.0.2 发布于 2026/10/31(8 天前);至今共发布 43 个版本,其中过去 12 个月发布了 24 个;首次发布于 2025/06/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。