跳到主要内容

Workspace

加入版本: @mastra/core@1.1.0

Mastra Workspace 为 Agent 提供用于存储文件和执行命令的持久环境。Agent 使用 Workspace Tool 读写文件、运行 shell 命令,并搜索已建立索引的内容。

Workspace 支持以下功能:

  • 文件系统:文件 Storage(读取、写入、列出、删除、复制、移动、grep)
  • Sandbox:命令执行(shell 命令)和后台进程
  • LSP 检查:通过 Language Server 执行 hover、定义和实现查询
  • 搜索:对已建立索引的内容进行 BM25、向量或混合搜索
  • Skill:供 Agent 使用的可复用指令

何时使用 Workspace
何时使用 Workspace的直接链接

当 Agent 需要访问本地文件系统、运行 shell 命令、执行语义代码检查、搜索索引内容或使用可复用 Skill 指令时,请使用 Workspace。

工作原理
工作原理的直接链接

将 Workspace 分配给 Agent 时,Mastra 会将相应 Tool 添加到 Agent 的 Toolset。随后,Agent 可以使用这些 Tool 与文件交互并执行命令。

可以使用任意组合的支持功能创建 Workspace。Agent 只会收到与已配置功能相关的 Tool。

用法
用法的直接链接

创建 Workspace
创建 Workspace的直接链接

使用所需功能实例化 Workspace 类:

src/mastra/workspaces.ts
import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({
basePath: './workspace',
}),
sandbox: new LocalSandbox({
workingDirectory: './workspace',
}),
skills: ['skills'],
})

skills 数组指定包含 Skill 定义的目录路径。请参阅 Skill

全局 Workspace
全局 Workspace的直接链接

在 Mastra 实例上设置 Workspace。除非定义了自己的 Workspace,否则所有 Agent 都会继承它:

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { Workspace, LocalFilesystem } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
})

const mastra = new Mastra({
workspace,
})

Agent 级 Workspace
Agent 级 Workspace的直接链接

将 Workspace 直接分配给 Agent,以覆盖全局 Workspace:

src/mastra/agents/my-agent.ts
import { Agent } from '@mastra/core/agent'
import { Workspace, LocalFilesystem } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './agent-workspace' }),
})

export const myAgent = new Agent({
id: 'my-agent',
model: 'openai/gpt-5.6-sol',
workspace,
})

生命周期和清理
生命周期和清理的直接链接

Mastra 会注册全局及 Agent Workspace,以便在运行时列出和获取它们。调用 mastra.shutdown() 时,Mastra 会销毁其拥有的已注册 Workspace。这会关闭 Language Server、浏览器、Sandbox 进程和文件系统 Provider handle 等 Workspace 资源。

如需手动清理,请使用 mastra.removeWorkspace()。如果在从 Registry 中移除前应销毁 Workspace,请传入 { destroy: true }

静态 Provider 由 Workspace 所有。基于 resolver 的 Provider 由应用所有,因为 Workspace 会在请求时创建它们。有关 resolver 清理模型,请参阅运行时 Sandbox 生命周期所有权

配置模式
配置模式的直接链接

Workspace 根据 Agent 需要的能力支持多种配置模式。主要构建块是 filesystem(文件 Tool)和 sandbox(命令执行),mounts 则用于将云 Storage 连接到 Sandbox。

文件系统 + Sandbox(本地)
文件系统 + Sandbox(本地)的直接链接

本地开发时,将 LocalFilesystemLocalSandbox 指向同一目录。由于二者都在本地计算机上运行,通过文件系统写入的文件会立即供 Sandbox 中的命令使用:

const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
})

Agent 会同时获得文件 Tool 和 execute_command。这是最简单的全功能设置。

Mount + Sandbox(云 Storage)
Mount + Sandbox(云 Storage)的直接链接

当需要在 Sandbox 内访问云 Storage 时,请使用 mounts。这会通过 FUSE 将云文件系统 mount 到 Sandbox,使命令能够在 mount 路径读写文件:

const workspace = new Workspace({
mounts: {
'/data': new S3Filesystem({
bucket: 'my-bucket',
region: 'us-east-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
}),
'/skills': new GCSFilesystem({
bucket: 'agent-skills',
}),
},
sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
})

底层的 mounts 会创建 CompositeFilesystem,根据路径前缀将文件 Tool 操作路由到正确的 Provider。Sandbox 中的命令直接访问 mount 路径(例如 ls /data)。

可以将多个 Provider mount 到不同路径。每个 mount 路径必须唯一且不能重叠。

备注

filesystemmounts 互斥,不能在同一个 Workspace 中同时使用。对于不含 Sandbox 的单个 Provider,请使用 filesystem;需要将云 Storage 与 Sandbox 组合时,请使用 mounts

仅文件系统
仅文件系统的直接链接

如果 Agent 只需要读写文件,请仅使用 filesystem。此时无法执行命令。

const workspace = new Workspace({
filesystem: new S3Filesystem({
bucket: 'my-bucket',
region: 'us-east-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
}),
})

Agent 会获得直接操作 Storage Provider 的文件 Tool(read_filewrite_filelist_directorygrep 等)。

仅 Sandbox
仅 Sandbox的直接链接

如果 Agent 只需要执行命令,请仅使用 sandbox。此时不会添加文件 Tool。

const workspace = new Workspace({
sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
})

Agent 会获得 execute_command Tool。

动态文件系统(按请求)
动态文件系统(按请求)的直接链接

filesystem 传入 resolver 函数,为每个请求返回不同的文件系统。它适用于多租户应用或多角色 Agent,其中每个请求需要不同的 Storage 根目录或权限。

const workspace = new Workspace({
filesystem: ({ requestContext }) => {
const role = requestContext.get('agent-role') || 'guest'
return new LocalFilesystem({
basePath: `/workspaces/${role}`,
readOnly: role !== 'admin',
})
},
})

一个 Workspace 实例即可服务所有请求。Resolver 在 Tool 执行时运行,因此每个请求都会获得自己的文件系统。有关详情,请参阅动态文件系统

动态 Sandbox(按请求)
动态 Sandbox(按请求)的直接链接

sandbox 传入 resolver 函数,为每个请求返回不同的 Sandbox。它适用于多租户部署,其中每位用户或每种角色都需要隔离的工作目录或不同的执行权限。

const workspace = new Workspace({
sandbox: ({ requestContext }) => {
const userId = requestContext.get('user-id') as string
return new LocalSandbox({
workingDirectory: `/workspaces/${userId}`,
})
},
})

Resolver 与 mountslsp: true 不兼容,因为二者都要求在构造时提供具体的 Sandbox 实例。有关详情,请参阅动态 Sandbox

应使用哪种模式?
应使用哪种模式?的直接链接

场景模式
使用文件和命令进行本地开发filesystem + sandbox(二者均为本地,指向同一目录)
在云 Sandbox 内访问云 Storagemounts + sandbox
在一个 Sandbox 中使用多个云 Providermounts + sandbox(每个 Provider 使用一个 mount)
Agent 读写文件,无需执行命令filesystem
Agent 运行命令,无需文件 Toolsandbox
多角色或多租户 Agent,每个请求使用不同 Storage带 resolver 函数的 filesystem
多租户 Agent,每个请求具有不同执行 scope带 resolver 函数的 sandbox

Tool 配置
Tool 配置的直接链接

通过 Workspace 上的 tools 选项配置 Tool 行为。它控制启用哪些 Tool 及其行为。

src/mastra/workspaces.ts
import { Workspace, LocalFilesystem, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
tools: {
// Global defaults
enabled: true,
requireApproval: false,

// Per-tool overrides
[WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: {
requireApproval: true,
requireReadBeforeWrite: true,
},
[WORKSPACE_TOOLS.FILESYSTEM.DELETE]: {
enabled: false,
},
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
requireApproval: true,
},
},
})

Tool 选项
Tool 选项的直接链接

选项类型说明
enabledboolean | (context) => booleanTool 是否可用(默认值:true)。如果为函数,会在列出 Tool 时求值。
requireApprovalboolean | (context) => booleanTool 在执行前是否需要用户批准(默认值:false)。如果为函数,会在执行时求值,并可访问 args
requireReadBeforeWriteboolean | (context) => boolean对于写入 Tool,是否要求先读取文件(默认值:false)。如果为函数,会在执行时求值,并可访问 args
namestringTool 的自定义名称,替换默认的 mastra_workspace_* 名称。
maxOutputTokensnumberTool 输出的最大 token 数(默认值:2000)。超出此限制的输出会使用 tiktoken 截断。

动态 Tool 配置
动态 Tool 配置的直接链接

接受函数的 Tool 选项会接收上下文对象并返回 boolean,从而实现感知上下文的 Tool 行为。

src/mastra/workspaces.ts
const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
tools: {
// Dynamic enabled: disable command execution unless explicitly allowed
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
enabled: async ({ requestContext }) => {
return requestContext['allowExecution'] === 'true'
},
},

// Dynamic requireApproval: only require approval for protected paths
[WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: {
requireApproval: async ({ args }) => {
return (args.path as string).startsWith('/protected')
},
requireReadBeforeWrite: true,
},
},
})

enabled 的函数接收 { requestContext, workspace }requireApprovalrequireReadBeforeWrite 的函数还会接收 args,因为它们会在调用 Tool 时求值。

重映射 Tool 名称
重映射 Tool 名称的直接链接

重命名 Workspace Tool,使其符合 Agent 预期的约定。配置键仍为原始 WORKSPACE_TOOLS 常量,只有暴露的名称会更改。

src/mastra/workspaces.ts
import { Workspace, LocalFilesystem, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
lsp: true,
tools: {
[WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: { name: 'view' },
[WORKSPACE_TOOLS.FILESYSTEM.GREP]: { name: 'search_content' },
[WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES]: { name: 'find_files' },
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: { name: 'execute_command' },
[WORKSPACE_TOOLS.LSP.LSP_INSPECT]: { name: 'lsp_inspect' },
},
})

Agent 会看到 viewsearch_contentfind_filesexecute_commandlsp_inspect,而不是默认的 mastra_workspace_* 名称。Tool 名称必须唯一;名称重复或与其他默认名称冲突时会抛出错误。

Tool hook
Tool hook的直接链接

设置 tools.hooks,在每次已启用 Workspace Tool 调用前后运行逻辑。Hook 在名称重映射后运行,因此 hook 上下文同时包含暴露的 toolName 和原始 workspaceToolName

src/mastra/workspaces.ts
import { Workspace, LocalFilesystem } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
tools: {
hooks: {
beforeToolCall: ({ toolName, workspaceToolName, input }) => {
console.log(`Running ${toolName} (${workspaceToolName})`, input)
},
afterToolCall: ({ toolName, output, error }) => {
console.log(`Finished ${toolName}`, { output, error })
},
},
},
})

beforeToolCall 返回 { proceed: false, output },可跳过 Tool 调用并将 output 用作结果。

如果所属 Agent 也定义了 Tool hook,Workspace hook 会在 Agent hook wrapper 内运行。顺序为:Agent beforeToolCall、Workspace beforeToolCall、Tool、Workspace afterToolCall、Agent afterToolCall

LSP 检查
LSP 检查的直接链接

在 Workspace 上启用 lsp,可通过 Language Server 添加语义代码检查。默认会添加 mastra_workspace_lsp_inspect Tool,它可以返回 hover 信息和定义位置,以及特定光标位置符号的实现。

有关配置、示例和 Tool 名称重映射,请参阅 LSP 检查

输出截断
输出截断的直接链接

Workspace Tool 会自动截断较大的输出,避免超过 LLM 上下文限制。以下截断层会依次应用:

  1. 按行保留末尾:默认将命令输出限制为最后 200 行(可通过每条命令的 tail 参数配置)
  2. 按 token 限制:Tool 输出默认限制为 2000 个 token

为每个 Tool 设置 maxOutputTokens 可调整 token 限制:

const workspace = new Workspace({
// ...
tools: {
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
maxOutputTokens: 5000,
},
},
})

命令输出到达模型前,会自动移除 ANSI 转义码(颜色、光标序列)。

写入前读取
写入前读取的直接链接

为写入 Tool 启用 requireReadBeforeWrite 后,Agent 必须先读取文件才能写入,防止覆盖 Agent 尚未查看的文件:

  • 新文件:无需读取即可写入(文件尚不存在)
  • 现有文件:必须先读取
  • 被外部修改的文件:如果文件在 Agent 读取后发生变化,写入会失败

文件写入安全性通过两层强制执行:

  1. Tool 层:写入 Tool 运行前,读取 tracker 会检查文件自上次读取后是否发生修改。如果发生修改,Tool 会抛出 FileReadRequiredError
  2. 文件系统层:写入时,writeFile() 会将文件当前修改时间与预期值(通过写入选项中的 expectedMtime 传入)比较。如果不匹配,则抛出 StaleFileError。这会捕获 Tool 层检查与实际写入之间发生的外部修改(例如编辑器保存文件)。

启用 requireReadBeforeWrite 后,Workspace Tool 会自动传递记录的修改时间。在 Tool 外调用 filesystem.writeFile() 时,也可以直接使用 expectedMtime

const stat = await filesystem.stat('/docs/file.md')
// ... later ...
await filesystem.writeFile('/docs/file.md', newContent, {
expectedMtime: stat.modifiedAt,
})

初始化
初始化的直接链接

大多数情况下,调用 init() 是可选的,部分 Provider 会在首次操作时初始化。在 Mastra 外使用 Workspace(独立脚本、测试),或需要在 Agent 首次交互前预配资源时,请手动调用 init()

src/mastra/workspaces.ts
import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
})

// Optional: pre-create directories and sandbox before first use
await workspace.init()

init() 的作用
what-init-does的直接链接

初始化会为每个已配置 Provider 运行设置逻辑:

  • LocalFilesystem:如果基础目录不存在,则创建它
  • LocalSandbox:创建工作目录
  • Search(如果已配置):为 autoIndexPaths 中的文件建立索引,请参阅搜索和索引

外部 Provider 可能执行其他设置,例如建立连接或进行身份验证。