> Discover all available pages from the documentation index: https://mastra.zisheng.pro/llms.txt # Workspace **加入版本:** `@mastra/core@1.1.0` Mastra Workspace 为 Agent 提供用于存储文件和执行命令的持久环境。Agent 使用 Workspace Tool 读写文件、运行 shell 命令,并搜索已建立索引的内容。 Workspace 支持以下功能: - **[文件系统](https://mastra.zisheng.pro/docs/workspace/filesystem)**:文件 Storage(读取、写入、列出、删除、复制、移动、grep) - **[Sandbox](https://mastra.zisheng.pro/docs/workspace/sandbox)**:命令执行(shell 命令)和后台进程 - **[LSP 检查](https://mastra.zisheng.pro/docs/workspace/lsp)**:通过 Language Server 执行 hover、定义和实现查询 - **[搜索](https://mastra.zisheng.pro/docs/workspace/search)**:对已建立索引的内容进行 BM25、向量或混合搜索 - **[Skill](https://mastra.zisheng.pro/docs/workspace/skills)**:供 Agent 使用的可复用指令 ## 何时使用 Workspace 当 Agent 需要访问本地文件系统、运行 shell 命令、执行语义代码检查、搜索索引内容或使用可复用 Skill 指令时,请使用 Workspace。 ## 工作原理 将 Workspace 分配给 Agent 时,Mastra 会将相应 Tool 添加到 Agent 的 Toolset。随后,Agent 可以使用这些 Tool 与文件交互并执行命令。 可以使用任意组合的支持功能创建 Workspace。Agent 只会收到与已配置功能相关的 Tool。 ## 用法 ### 创建 Workspace 使用所需功能实例化 `Workspace` 类: ```typescript 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](https://mastra.zisheng.pro/docs/workspace/skills)。 ### 全局 Workspace 在 Mastra 实例上设置 Workspace。除非定义了自己的 Workspace,否则所有 Agent 都会继承它: ```typescript 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 将 Workspace 直接分配给 Agent,以覆盖全局 Workspace: ```typescript 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()`](https://mastra.zisheng.pro/reference/core/removeWorkspace)。如果在从 Registry 中移除前应销毁 Workspace,请传入 `{ destroy: true }`。 静态 Provider 由 Workspace 所有。基于 resolver 的 Provider 由应用所有,因为 Workspace 会在请求时创建它们。有关 resolver 清理模型,请参阅[运行时 Sandbox 生命周期所有权](https://mastra.zisheng.pro/docs/workspace/sandbox)。 ## 配置模式 Workspace 根据 Agent 需要的能力支持多种配置模式。主要构建块是 `filesystem`(文件 Tool)和 `sandbox`(命令执行),`mounts` 则用于将云 Storage 连接到 Sandbox。 ### 文件系统 + Sandbox(本地) 本地开发时,将 `LocalFilesystem` 和 `LocalSandbox` 指向同一目录。由于二者都在本地计算机上运行,通过文件系统写入的文件会立即供 Sandbox 中的命令使用: ```typescript const workspace = new Workspace({ filesystem: new LocalFilesystem({ basePath: './workspace' }), sandbox: new LocalSandbox({ workingDirectory: './workspace' }), }) ``` Agent 会同时获得文件 Tool 和 `execute_command`。这是最简单的全功能设置。 ### Mount + Sandbox(云 Storage) 当需要在 Sandbox 内访问云 Storage 时,请使用 `mounts`。这会通过 FUSE 将云文件系统 mount 到 Sandbox,使命令能够在 mount 路径读写文件: ```typescript 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](https://mastra.zisheng.pro/docs/workspace/filesystem),根据路径前缀将文件 Tool 操作路由到正确的 Provider。Sandbox 中的命令直接访问 mount 路径(例如 `ls /data`)。 可以将多个 Provider mount 到不同路径。每个 mount 路径必须唯一且不能重叠。 > **备注:** `filesystem` 与 `mounts` 互斥,不能在同一个 Workspace 中同时使用。对于不含 Sandbox 的单个 Provider,请使用 `filesystem`;需要将云 Storage 与 Sandbox 组合时,请使用 `mounts`。 ### 仅文件系统 如果 Agent 只需要读写文件,请仅使用 `filesystem`。此时无法执行命令。 ```typescript 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_file`、`write_file`、`list_directory`、`grep` 等)。 ### 仅 Sandbox 如果 Agent 只需要执行命令,请仅使用 `sandbox`。此时不会添加文件 Tool。 ```typescript const workspace = new Workspace({ sandbox: new E2BSandbox({ id: 'dev-sandbox' }), }) ``` Agent 会获得 `execute_command` Tool。 ### 动态文件系统(按请求) 向 `filesystem` 传入 resolver 函数,为每个请求返回不同的文件系统。它适用于多租户应用或多角色 Agent,其中每个请求需要不同的 Storage 根目录或权限。 ```typescript 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 执行时运行,因此每个请求都会获得自己的文件系统。有关详情,请参阅[动态文件系统](https://mastra.zisheng.pro/docs/workspace/filesystem)。 ### 动态 Sandbox(按请求) 向 `sandbox` 传入 resolver 函数,为每个请求返回不同的 Sandbox。它适用于多租户部署,其中每位用户或每种角色都需要隔离的工作目录或不同的执行权限。 ```typescript const workspace = new Workspace({ sandbox: ({ requestContext }) => { const userId = requestContext.get('user-id') as string return new LocalSandbox({ workingDirectory: `/workspaces/${userId}`, }) }, }) ``` Resolver 与 `mounts` 和 `lsp: true` 不兼容,因为二者都要求在构造时提供具体的 Sandbox 实例。有关详情,请参阅[动态 Sandbox](https://mastra.zisheng.pro/docs/workspace/sandbox)。 ### 应使用哪种模式? | 场景 | 模式 | | ------------------------------ | -------------------------------------------- | | 使用文件和命令进行本地开发 | `filesystem` + `sandbox`(二者均为本地,指向同一目录) | | 在云 Sandbox 内访问云 Storage | `mounts` + `sandbox` | | 在一个 Sandbox 中使用多个云 Provider | `mounts` + `sandbox`(每个 Provider 使用一个 mount) | | Agent 读写文件,无需执行命令 | 仅 `filesystem` | | Agent 运行命令,无需文件 Tool | 仅 `sandbox` | | 多角色或多租户 Agent,每个请求使用不同 Storage | 带 resolver 函数的 `filesystem` | | 多租户 Agent,每个请求具有不同执行 scope | 带 resolver 函数的 `sandbox` | ## Tool 配置 通过 Workspace 上的 `tools` 选项配置 Tool 行为。它控制启用哪些 Tool 及其行为。 ```typescript 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 选项 | 选项 | 类型 | 说明 | | ------------------------ | --------------------------------- | ----------------------------------------------------------- | | `enabled` | `boolean \| (context) => boolean` | Tool 是否可用(默认值:`true`)。如果为函数,会在列出 Tool 时求值。 | | `requireApproval` | `boolean \| (context) => boolean` | Tool 在执行前是否需要用户批准(默认值:`false`)。如果为函数,会在执行时求值,并可访问 `args`。 | | `requireReadBeforeWrite` | `boolean \| (context) => boolean` | 对于写入 Tool,是否要求先读取文件(默认值:`false`)。如果为函数,会在执行时求值,并可访问 `args`。 | | `name` | `string` | Tool 的自定义名称,替换默认的 `mastra_workspace_*` 名称。 | | `maxOutputTokens` | `number` | Tool 输出的最大 token 数(默认值:`2000`)。超出此限制的输出会使用 tiktoken 截断。 | ### 动态 Tool 配置 接受函数的 Tool 选项会接收上下文对象并返回 boolean,从而实现感知上下文的 Tool 行为。 ```typescript 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 }`。`requireApproval` 和 `requireReadBeforeWrite` 的函数还会接收 `args`,因为它们会在调用 Tool 时求值。 ### 重映射 Tool 名称 重命名 Workspace Tool,使其符合 Agent 预期的约定。配置键仍为原始 `WORKSPACE_TOOLS` 常量,只有暴露的名称会更改。 ```typescript 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 会看到 `view`、`search_content`、`find_files`、`execute_command` 和 `lsp_inspect`,而不是默认的 `mastra_workspace_*` 名称。Tool 名称必须唯一;名称重复或与其他默认名称冲突时会抛出错误。 ### Tool hook 设置 `tools.hooks`,在每次已启用 Workspace Tool 调用前后运行逻辑。Hook 在名称重映射后运行,因此 hook 上下文同时包含暴露的 `toolName` 和原始 `workspaceToolName`: ```typescript 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](https://mastra.zisheng.pro/docs/agents/using-tools),Workspace hook 会在 Agent hook wrapper 内运行。顺序为:Agent `beforeToolCall`、Workspace `beforeToolCall`、Tool、Workspace `afterToolCall`、Agent `afterToolCall`。 ## LSP 检查 在 Workspace 上启用 `lsp`,可通过 Language Server 添加语义代码检查。默认会添加 `mastra_workspace_lsp_inspect` Tool,它可以返回 hover 信息和定义位置,以及特定光标位置符号的实现。 有关配置、示例和 Tool 名称重映射,请参阅 [LSP 检查](https://mastra.zisheng.pro/docs/workspace/lsp)。 ### 输出截断 Workspace Tool 会自动截断较大的输出,避免超过 LLM 上下文限制。以下截断层会依次应用: 1. **按行保留末尾**:默认将命令输出限制为最后 200 行(可通过每条命令的 `tail` 参数配置) 2. **按 token 限制**:Tool 输出默认限制为 2000 个 token 为每个 Tool 设置 `maxOutputTokens` 可调整 token 限制: ```typescript 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`: ```typescript 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()`。 ```typescript 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()` 的作用 初始化会为每个已配置 Provider 运行设置逻辑: - `LocalFilesystem`:如果基础目录不存在,则创建它 - `LocalSandbox`:创建工作目录 - `Search`(如果已配置):为 `autoIndexPaths` 中的文件建立索引,请参阅[搜索和索引](https://mastra.zisheng.pro/docs/workspace/search) 外部 Provider 可能执行其他设置,例如建立连接或进行身份验证。 ## 相关内容 - [文件系统](https://mastra.zisheng.pro/docs/workspace/filesystem) - [Sandbox](https://mastra.zisheng.pro/docs/workspace/sandbox) - [LSP 检查](https://mastra.zisheng.pro/docs/workspace/lsp) - [Skill](https://mastra.zisheng.pro/docs/workspace/skills) - [搜索和索引](https://mastra.zisheng.pro/docs/workspace/search) - [Workspace 类 Reference](https://mastra.zisheng.pro/reference/workspace/workspace-class) - 📹 [Mastra Workspace 入门 workshop](https://www.youtube.com/watch?v=QcQLiYlJuNQ)