> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # Workspace **新增於:** `@mastra/core@1.1.0` Mastra Workspace 為 Agent 提供持久環境,用於儲存檔案及執行命令。Agent 可使用 Workspace Tool 讀寫檔案、執行 Shell 命令,以及搜尋已建立索引的內容。 Workspace 支援下列功能: - **[檔案系統](https://mastra.zisheng.pro/zh-TW/docs/workspace/filesystem)**:檔案儲存(讀取、寫入、列出、刪除、複製、移動、grep) - **[Sandbox](https://mastra.zisheng.pro/zh-TW/docs/workspace/sandbox)**:命令執行(Shell 命令)與背景處理程序 - **[LSP 檢查](https://mastra.zisheng.pro/zh-TW/docs/workspace/lsp)**:透過語言伺服器進行懸停、定義與實作查詢 - **[搜尋](https://mastra.zisheng.pro/zh-TW/docs/workspace/search)**:在已建立索引的內容上進行 BM25、向量或混合搜尋 - **[Skills](https://mastra.zisheng.pro/zh-TW/docs/workspace/skills)**:可供 Agent 重複使用的指示 ## 適合使用 Workspace 的情境 當 Agent 需要存取本機檔案系統、Shell 命令、語意程式碼檢查、索引搜尋或可重複使用的 Skill 指示時,請使用 Workspace。 ## 運作方式 將 Workspace 指派給 Agent 後,Mastra 會把對應的 Tool 加入 Agent 的 Tool 集合。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 定義的目錄路徑,請參閱 [Skills](https://mastra.zisheng.pro/zh-TW/docs/workspace/skills)。 ### 全域 Workspace 在 Mastra 執行個體上設定 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 直接將 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,關閉語言伺服器、瀏覽器、Sandbox 處理程序及檔案系統 Provider Handle 等資源。 若要手動清理,請使用 [`mastra.removeWorkspace()`](https://mastra.zisheng.pro/zh-TW/reference/core/removeWorkspace)。若 Workspace 應在從登錄中移除前銷毀,請傳入 `{ destroy: true }`。 靜態 Provider 由 Workspace 擁有。以解析器為基礎的 Provider 由應用程式擁有,因為 Workspace 會在請求時建立它們。解析器清理模型請參閱[執行階段 Sandbox 生命週期擁有權](https://mastra.zisheng.pro/zh-TW/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-TW/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`,即可為每個請求傳回不同檔案系統。這適合多租戶應用程式或多角色 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 執行個體可處理所有請求。解析器會在 Tool 執行時運作,因此每個請求都有自己的檔案系統。詳情請參閱[動態檔案系統](https://mastra.zisheng.pro/zh-TW/docs/workspace/filesystem)。 ### 動態 Sandbox(依請求) 將解析器函式傳給 `sandbox`,即可為每個請求傳回不同 Sandbox。這適合每位使用者或角色需要隔離工作目錄或不同執行權限的多租戶部署。 ```typescript const workspace = new Workspace({ sandbox: ({ requestContext }) => { const userId = requestContext.get('user-id') as string return new LocalSandbox({ workingDirectory: `/workspaces/${userId}`, }) }, }) ``` 解析器與 `mounts` 及 `lsp: true` 不相容,因為兩者在建構時都需要具體的 Sandbox 執行個體。詳情請參閱[動態 Sandbox](https://mastra.zisheng.pro/zh-TW/docs/workspace/sandbox)。 ### 應該使用哪種模式? | 情境 | 模式 | | ---------------------------- | --------------------------------------- | | 使用檔案及命令進行本機開發 | `filesystem` + `sandbox`(兩者均為本機且使用相同目錄) | | 在雲端 Sandbox 中存取雲端儲存空間 | `mounts` + `sandbox` | | 在單一 Sandbox 中使用多個雲端 Provider | `mounts` + `sandbox`(每個 Provider 一個掛載點) | | Agent 讀寫檔案,不需執行命令 | 僅 `filesystem` | | Agent 執行命令,不需檔案 Tool | 僅 `sandbox` | | 多角色或多租戶 Agent 使用依請求區分的儲存空間 | 含解析器函式的 `filesystem` | | 多租戶 Agent 使用依請求區分的執行範圍 | 含解析器函式的 `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 選項會接收情境物件並傳回布林值,讓 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` 函式因在呼叫 Tool 時評估,也會收到 `args`。 ### 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 在名稱重新對應後執行,因此情境同時包含公開的 `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` 作為結果。 若擁有此 Workspace 的 Agent 也定義了 [Tool Hook](https://mastra.zisheng.pro/zh-TW/docs/agents/using-tools),Workspace Hook 會在 Agent Hook 包裝器內執行。順序為 Agent `beforeToolCall`、Workspace `beforeToolCall`、Tool、Workspace `afterToolCall`、Agent `afterToolCall`。 ## LSP 檢查 在 Workspace 上啟用 `lsp`,即可透過語言伺服器加入語意程式碼檢查。預設會加入 `mastra_workspace_lsp_inspect` Tool,可傳回特定游標位置符號的懸停資訊、定義位置與實作。 設定、範例及 Tool 名稱重新對應請參閱 [LSP 檢查](https://mastra.zisheng.pro/zh-TW/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 Escape Code(顏色、游標序列)。 ### 寫入前讀取 在寫入 Tool 上啟用 `requireReadBeforeWrite` 後,Agent 必須先讀取檔案才能寫入,避免覆寫 Agent 尚未查看的檔案: - **新檔案**:不必讀取即可寫入(因為尚不存在) - **現有檔案**:必須先讀取 - **外部修改的檔案**:若檔案在 Agent 讀取後有變更,寫入會失敗 檔案寫入安全性會在兩層強制執行: 1. **Tool 層**:寫入 Tool 執行前,讀取追蹤器會檢查檔案自上次讀取後是否修改。若有修改,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/zh-TW/docs/workspace/search) 外部 Provider 可能進行其他設定,例如建立連線或驗證身分。 ## 相關資源 - [檔案系統](https://mastra.zisheng.pro/zh-TW/docs/workspace/filesystem) - [Sandbox](https://mastra.zisheng.pro/zh-TW/docs/workspace/sandbox) - [LSP 檢查](https://mastra.zisheng.pro/zh-TW/docs/workspace/lsp) - [Skills](https://mastra.zisheng.pro/zh-TW/docs/workspace/skills) - [搜尋與索引](https://mastra.zisheng.pro/zh-TW/docs/workspace/search) - [Workspace class 參考](https://mastra.zisheng.pro/zh-TW/reference/workspace/workspace-class) - 📹 [Mastra Workspaces 入門工作坊](https://www.youtube.com/watch?v=QcQLiYlJuNQ)