> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # Workspace **新增於:** `@mastra/core@1.1.0` Mastra Workspace 為 Agent 提供持久環境,用於儲存檔案及執行命令。Agent 可使用 Workspace Tool 讀寫檔案、執行 shell 命令,以及搜尋已建立索引的內容。 Workspace 支援以下功能: - **[檔案系統](https://mastra.zisheng.pro/zh-HK/docs/workspace/filesystem)**:檔案儲存(讀取、寫入、列出、刪除、複製、移動、grep) - **[Sandbox](https://mastra.zisheng.pro/zh-HK/docs/workspace/sandbox)**:執行命令(shell 命令)及背景程序 - **[LSP 檢查](https://mastra.zisheng.pro/zh-HK/docs/workspace/lsp)**:透過語言伺服器查詢懸停資訊、定義及實作 - **[搜尋](https://mastra.zisheng.pro/zh-HK/docs/workspace/search)**:在已建立索引的內容中進行 BM25、向量或混合搜尋 - **[Skill](https://mastra.zisheng.pro/zh-HK/docs/workspace/skills)**:供 Agent 重用的指示 ## 何時使用 Workspace 當 Agent 需要存取本機檔案系統、使用 shell 命令、進行語義程式碼檢查、搜尋已建立索引的內容,或使用可重用的 Skill 指示時,便應使用 Workspace。 ## 運作方式 當你為 Agent 指派 Workspace 時,Mastra 會將相應的 Tool 加入 Agent 的 Tool 集合。Agent 隨後便可使用這些 Tool 與檔案互動及執行命令。 你可以使用任意組合的支援功能來建立 Workspace。Agent 只會取得與已設定功能相關的 Tool。 ## 使用方式 ### 建立 Workspace 使用所需功能實例化 `Workspace` class,即可建立 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` array 指定包含 Skill 定義的目錄路徑,詳情請參閱 [Skill](https://mastra.zisheng.pro/zh-HK/docs/workspace/skills)。 ### 全域 Workspace 在 Mastra instance 上設定 Workspace。除非 Agent 定義自己的 Workspace,否則所有 Agent 都會繼承此 Workspace: ```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 直接為 Agent 指派 Workspace,以覆寫全域 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。這會關閉語言伺服器、瀏覽器、Sandbox 程序及檔案系統 Provider handle 等 Workspace 資源。 如要手動清理,請使用 [`mastra.removeWorkspace()`](https://mastra.zisheng.pro/zh-HK/reference/core/removeWorkspace)。如需在從 registry 移除 Workspace 前將其銷毀,請傳入 `{ destroy: true }`。 靜態 Provider 由 Workspace 擁有。由 resolver 支援的 Provider 則由你的應用程式擁有,因為 Workspace 會在請求時建立這些 Provider。有關 resolver 的清理模型,請參閱[運行時 Sandbox 生命週期擁有權](https://mastra.zisheng.pro/zh-HK/docs/workspace/sandbox)。 ## 設定模式 Workspace 支援多種設定模式,視乎 Agent 所需的能力而定。主要構成部分是 `filesystem`(檔案 Tool)及 `sandbox`(執行命令),而 `mounts` 則用於將雲端儲存空間連接至 Sandbox。 ### 檔案系統 + Sandbox(本機) 進行本機開發時,將指向同一目錄的 `LocalFilesystem` 與 `LocalSandbox` 配對使用。由於兩者都在本機運作,透過檔案系統寫入的檔案可立即供 Sandbox 中的命令使用: ```typescript const workspace = new Workspace({ filesystem: new LocalFilesystem({ basePath: './workspace' }), sandbox: new LocalSandbox({ workingDirectory: './workspace' }), }) ``` Agent 會同時取得檔案 Tool 及 `execute_command`。這是最簡單且功能完整的設定。 ### 掛載 + Sandbox(雲端儲存空間) 如需在 Sandbox 內存取雲端儲存空間,請使用 `mounts`。這會透過 FUSE 將雲端檔案系統掛載至 Sandbox,讓命令可以在掛載路徑讀寫檔案: ```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/zh-HK/docs/workspace/filesystem),並根據路徑前綴將檔案 Tool 操作路由至正確的 Provider。Sandbox 中的命令可直接存取掛載路徑(例如 `ls /data`)。 你可以在不同路徑掛載多個 Provider。每個掛載路徑必須獨一無二,且不可互相重疊。 > **備註:** `filesystem` 與 `mounts` 互相排斥,不能在同一個 Workspace 中同時使用。如使用不設 Sandbox 的單一 Provider,請使用 `filesystem`;如需將雲端儲存空間與 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 會取得直接對儲存空間 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 function,便可為每個請求傳回不同的檔案系統。這適用於多租戶應用程式或多角色 Agent,讓每個請求使用不同的儲存根目錄或權限。 ```typescript const workspace = new Workspace({ filesystem: ({ requestContext }) => { const role = requestContext.get('agent-role') || 'guest' return new LocalFilesystem({ basePath: `/workspaces/${role}`, readOnly: role !== 'admin', }) }, }) ``` 一個 Workspace instance 可處理所有請求。resolver 會在 Tool 執行時運行,因此每個請求都會取得自己的檔案系統。詳情請參閱[動態檔案系統](https://mastra.zisheng.pro/zh-HK/docs/workspace/filesystem)。 ### 動態 Sandbox(按請求) 向 `sandbox` 傳入 resolver function,便可為每個請求傳回不同的 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 instance。詳情請參閱[動態 Sandbox](https://mastra.zisheng.pro/zh-HK/docs/workspace/sandbox)。 ### 應使用哪種模式? | 情境 | 模式 | | ---------------------------- | ----------------------------------------- | | 使用檔案及命令進行本機開發 | `filesystem` + `sandbox`(兩者均為本機並使用同一目錄) | | 在雲端 Sandbox 內存取雲端儲存空間 | `mounts` + `sandbox` | | 在一個 Sandbox 中使用多個雲端 Provider | `mounts` + `sandbox`(每個 Provider 使用一個掛載點) | | Agent 讀寫檔案,無需執行命令 | 僅 `filesystem` | | Agent 執行命令,無需檔案 Tool | 僅 `sandbox` | | 多角色或多租戶 Agent 使用按請求提供的儲存空間 | 使用 resolver function 的 `filesystem` | | 多租戶 Agent 使用按請求提供的執行範圍 | 使用 resolver function 的 `sandbox` | ## Tool 設定 透過 Workspace 的 `tools` option 設定 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 option | Option | 類型 | 說明 | | ------------------------ | --------------------------------- | ----------------------------------------------------------------- | | `enabled` | `boolean \| (context) => boolean` | Tool 是否可用(預設:`true`)。如為 function,會在列出 Tool 時求值。 | | `requireApproval` | `boolean \| (context) => boolean` | Tool 執行前是否需要用戶批准(預設:`false`)。如為 function,會在執行時求值,並可存取 `args`。 | | `requireReadBeforeWrite` | `boolean \| (context) => boolean` | 適用於寫入 Tool:是否要求先讀取檔案(預設:`false`)。如為 function,會在執行時求值,並可存取 `args`。 | | `name` | `string` | Tool 的自訂名稱。取代預設的 `mastra_workspace_*` 名稱。 | | `maxOutputTokens` | `number` | Tool 輸出的 token 上限(預設:`2000`)。超出此限制的輸出會使用 tiktoken 截斷。 | ### 動態 Tool 設定 接受 function 的 Tool option 會接收 context object 並傳回 boolean,從而實現可感知 context 的 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` 的 function 會接收 `{ requestContext, workspace }`。`requireApproval` 及 `requireReadBeforeWrite` 的 function 亦會接收 `args`,因為它們在呼叫 Tool 時才會求值。 ### 重新映射 Tool 名稱 重新命名 Workspace Tool,以配合 Agent 預期的慣例。config key 仍然是原有的 `WORKSPACE_TOOLS` constant,只有公開的名稱會改變。 ```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 context 會同時包含公開的 `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 }) }, }, }, }) ``` 傳回 `{ proceed: false, output }`,即可略過 `beforeToolCall` 的 Tool 呼叫,並使用 `output` 作為結果。 如果擁有 Workspace 的 Agent 亦定義了 [Tool hook](https://mastra.zisheng.pro/zh-HK/docs/agents/using-tools),Workspace hook 會在 Agent hook wrapper 內運行。順序依次為 Agent `beforeToolCall`、Workspace `beforeToolCall`、Tool、Workspace `afterToolCall`,最後是 Agent `afterToolCall`。 ## LSP 檢查 在 Workspace 啟用 `lsp`,即可透過語言伺服器加入語義程式碼檢查。預設會加入 `mastra_workspace_lsp_inspect` Tool,它可以傳回懸停資訊及定義位置,並可傳回指定游標位置的 symbol 實作。 有關設定、範例及 Tool 名稱重新映射的詳情,請參閱 [LSP 檢查](https://mastra.zisheng.pro/zh-HK/docs/workspace/lsp)。 ### 輸出截斷 Workspace Tool 會自動截斷大量輸出,以免超出 LLM context 限制。截斷會按以下層級套用: 1. **按行保留結尾**:命令輸出預設只保留最後 200 行(可透過每個命令的 `tail` parameter 設定) 2. **Token 上限**:Tool 輸出預設上限為 2000 個 token 為個別 Tool 設定 `maxOutputTokens`,即可調整 token 上限: ```typescript const workspace = new Workspace({ // ... tools: { [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: { maxOutputTokens: 5000, }, }, }) ``` 命令輸出中的 ANSI escape code(顏色、游標序列)會在送達模型前自動移除。 ### 寫入前先讀取 在寫入 Tool 啟用 `requireReadBeforeWrite` 後,Agent 必須先讀取檔案,然後才可寫入。這可防止 Agent 覆寫尚未讀取的檔案: - **新檔案**:無需讀取即可寫入(因為檔案尚不存在) - **現有檔案**:必須先讀取 - **由外部修改的檔案**:如果檔案在 Agent 讀取後有所變更,寫入便會失敗 檔案寫入安全機制分兩層執行: 1. **Tool 層**:寫入 Tool 運行前,讀取追蹤器會檢查檔案自上次讀取後是否已被修改。如檔案已修改,Tool 會引發 `FileReadRequiredError`。 2. **檔案系統層**:寫入時,`writeFile()` 會比較檔案目前的修改時間與預期值(透過 write option 中的 `expectedMtime` 傳入)。如果兩者不符,便會引發 `StaleFileError`。這可捕捉在 Tool 層檢查與實際寫入之間發生的外部修改(例如編輯器儲存檔案)。 啟用 `requireReadBeforeWrite` 後,Workspace Tool 會自動傳遞記錄的修改時間。你亦可在 Tool 以外直接使用 `expectedMtime` 呼叫 `filesystem.writeFile()`: ```typescript const stat = await filesystem.stat('/docs/file.md') // ... later ... await filesystem.writeFile('/docs/file.md', newContent, { expectedMtime: stat.modifiedAt, }) ``` ## 初始化 在大部分情況下,呼叫 `init()` 並非必要,部分 Provider 會在首次操作時初始化。如在 Mastra 以外使用 Workspace(獨立 script、測試),或需要在 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/zh-HK/docs/workspace/search) 外部 Provider 可能會執行其他設定,例如建立連線或進行驗證。 ## 相關內容 - [檔案系統](https://mastra.zisheng.pro/zh-HK/docs/workspace/filesystem) - [Sandbox](https://mastra.zisheng.pro/zh-HK/docs/workspace/sandbox) - [LSP 檢查](https://mastra.zisheng.pro/zh-HK/docs/workspace/lsp) - [Skill](https://mastra.zisheng.pro/zh-HK/docs/workspace/skills) - [搜尋及建立索引](https://mastra.zisheng.pro/zh-HK/docs/workspace/search) - [Workspace class 參考](https://mastra.zisheng.pro/zh-HK/reference/workspace/workspace-class) - 📹 [Mastra Workspace 簡介工作坊](https://www.youtube.com/watch?v=QcQLiYlJuNQ)