Workspace
新增於: @mastra/core@1.1.0
Mastra Workspace 為 Agent 提供持久環境,用於儲存檔案及執行命令。Agent 可使用 Workspace Tool 讀寫檔案、執行 shell 命令,以及搜尋已建立索引的內容。
Workspace 支援以下功能:
- 檔案系統:檔案儲存(讀取、寫入、列出、刪除、複製、移動、grep)
- Sandbox:執行命令(shell 命令)及背景程序
- LSP 檢查:透過語言伺服器查詢懸停資訊、定義及實作
- 搜尋:在已建立索引的內容中進行 BM25、向量或混合搜尋
- Skill:供 Agent 重用的指示
何時使用 Workspace何時使用 Workspace 的直接連結
當 Agent 需要存取本機檔案系統、使用 shell 命令、進行語義程式碼檢查、搜尋已建立索引的內容,或使用可重用的 Skill 指示時,便應使用 Workspace。
運作方式運作方式 的直接連結
當你為 Agent 指派 Workspace 時,Mastra 會將相應的 Tool 加入 Agent 的 Tool 集合。Agent 隨後便可使用這些 Tool 與檔案互動及執行命令。
你可以使用任意組合的支援功能來建立 Workspace。Agent 只會取得與已設定功能相關的 Tool。
使用方式使用方式 的直接連結
建立 Workspace建立 Workspace 的直接連結
使用所需功能實例化 Workspace class,即可建立 Workspace:
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。
全域 Workspace全域 Workspace 的直接連結
在 Mastra instance 上設定 Workspace。除非 Agent 定義自己的 Workspace,否則所有 Agent 都會繼承此 Workspace:
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 層級的 WorkspaceAgent 層級的 Workspace 的直接連結
直接為 Agent 指派 Workspace,以覆寫全域 Workspace:
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()。如需在從 registry 移除 Workspace 前將其銷毀,請傳入 { destroy: true }。
靜態 Provider 由 Workspace 擁有。由 resolver 支援的 Provider 則由你的應用程式擁有,因為 Workspace 會在請求時建立這些 Provider。有關 resolver 的清理模型,請參閱運行時 Sandbox 生命週期擁有權。
設定模式設定模式 的直接連結
Workspace 支援多種設定模式,視乎 Agent 所需的能力而定。主要構成部分是 filesystem(檔案 Tool)及 sandbox(執行命令),而 mounts 則用於將雲端儲存空間連接至 Sandbox。
檔案系統 + Sandbox(本機)檔案系統 + Sandbox(本機) 的直接連結
進行本機開發時,將指向同一目錄的 LocalFilesystem 與 LocalSandbox 配對使用。由於兩者都在本機運作,透過檔案系統寫入的檔案可立即供 Sandbox 中的命令使用:
const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
})
Agent 會同時取得檔案 Tool 及 execute_command。這是最簡單且功能完整的設定。
掛載 + Sandbox(雲端儲存空間)掛載 + Sandbox(雲端儲存空間) 的直接連結
如需在 Sandbox 內存取雲端儲存空間,請使用 mounts。這會透過 FUSE 將雲端檔案系統掛載至 Sandbox,讓命令可以在掛載路徑讀寫檔案:
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 中的命令可直接存取掛載路徑(例如 ls /data)。
你可以在不同路徑掛載多個 Provider。每個掛載路徑必須獨一無二,且不可互相重疊。
filesystem 與 mounts 互相排斥,不能在同一個 Workspace 中同時使用。如使用不設 Sandbox 的單一 Provider,請使用 filesystem;如需將雲端儲存空間與 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 會取得直接對儲存空間 Provider 操作的檔案 Tool(read_file、write_file、list_directory、grep 等)。
僅 Sandbox僅 Sandbox 的直接連結
當 Agent 只需執行命令時,請使用單一 sandbox。此模式不會加入檔案 Tool。
const workspace = new Workspace({
sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
})
Agent 會取得 execute_command Tool。
動態檔案系統(按請求)動態檔案系統(按請求) 的直接連結
向 filesystem 傳入 resolver function,便可為每個請求傳回不同的檔案系統。這適用於多租戶應用程式或多角色 Agent,讓每個請求使用不同的儲存根目錄或權限。
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 執行時運行,因此每個請求都會取得自己的檔案系統。詳情請參閱動態檔案系統。
動態 Sandbox(按請求)動態 Sandbox(按請求) 的直接連結
向 sandbox 傳入 resolver function,便可為每個請求傳回不同的 Sandbox。這適用於多租戶部署,讓每位用戶或每個角色使用獨立的工作目錄或不同的執行權限。
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。
應使用哪種模式?應使用哪種模式? 的直接連結
| 情境 | 模式 |
|---|---|
| 使用檔案及命令進行本機開發 | filesystem + sandbox(兩者均為本機並使用同一目錄) |
| 在雲端 Sandbox 內存取雲端儲存空間 | mounts + sandbox |
| 在一個 Sandbox 中使用多個雲端 Provider | mounts + sandbox(每個 Provider 使用一個掛載點) |
| Agent 讀寫檔案,無需執行命令 | 僅 filesystem |
| Agent 執行命令,無需檔案 Tool | 僅 sandbox |
| 多角色或多租戶 Agent 使用按請求提供的儲存空間 | 使用 resolver function 的 filesystem |
| 多租戶 Agent 使用按請求提供的執行範圍 | 使用 resolver function 的 sandbox |
Tool 設定Tool 設定 的直接連結
透過 Workspace 的 tools option 設定 Tool 行為。這可控制啟用哪些 Tool,以及它們的運作方式。
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 optionTool 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 設定動態 Tool 設定 的直接連結
接受 function 的 Tool option 會接收 context object 並傳回 boolean,從而實現可感知 context 的 Tool 行為。
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 名稱重新映射 Tool 名稱 的直接連結
重新命名 Workspace Tool,以配合 Agent 預期的慣例。config key 仍然是原有的 WORKSPACE_TOOLS constant,只有公開的名稱會改變。
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 hookTool hook 的直接連結
設定 tools.hooks,在每次呼叫已啟用的 Workspace Tool 前後運行邏輯。hook 會在名稱重新映射後運行,因此 hook context 會同時包含公開的 toolName 及原有的 workspaceToolName:
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,Workspace hook 會在 Agent hook wrapper 內運行。順序依次為 Agent beforeToolCall、Workspace beforeToolCall、Tool、Workspace afterToolCall,最後是 Agent afterToolCall。
LSP 檢查LSP 檢查 的直接連結
在 Workspace 啟用 lsp,即可透過語言伺服器加入語義程式碼檢查。預設會加入 mastra_workspace_lsp_inspect Tool,它可以傳回懸停資訊及定義位置,並可傳回指定游標位置的 symbol 實作。
有關設定、範例及 Tool 名稱重新映射的詳情,請參閱 LSP 檢查。
輸出截斷輸出截斷 的直接連結
Workspace Tool 會自動截斷大量輸出,以免超出 LLM context 限制。截斷會按以下層級套用:
- 按行保留結尾:命令輸出預設只保留最後 200 行(可透過每個命令的
tailparameter 設定) - Token 上限:Tool 輸出預設上限為 2000 個 token
為個別 Tool 設定 maxOutputTokens,即可調整 token 上限:
const workspace = new Workspace({
// ...
tools: {
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
maxOutputTokens: 5000,
},
},
})
命令輸出中的 ANSI escape code(顏色、游標序列)會在送達模型前自動移除。
寫入前先讀取寫入前先讀取 的直接連結
在寫入 Tool 啟用 requireReadBeforeWrite 後,Agent 必須先讀取檔案,然後才可寫入。這可防止 Agent 覆寫尚未讀取的檔案:
- 新檔案:無需讀取即可寫入(因為檔案尚不存在)
- 現有檔案:必須先讀取
- 由外部修改的檔案:如果檔案在 Agent 讀取後有所變更,寫入便會失敗
檔案寫入安全機制分兩層執行:
- Tool 層:寫入 Tool 運行前,讀取追蹤器會檢查檔案自上次讀取後是否已被修改。如檔案已修改,Tool 會引發
FileReadRequiredError。 - 檔案系統層:寫入時,
writeFile()會比較檔案目前的修改時間與預期值(透過 write option 中的expectedMtime傳入)。如果兩者不符,便會引發StaleFileError。這可捕捉在 Tool 層檢查與實際寫入之間發生的外部修改(例如編輯器儲存檔案)。
啟用 requireReadBeforeWrite 後,Workspace Tool 會自動傳遞記錄的修改時間。你亦可在 Tool 以外直接使用 expectedMtime 呼叫 filesystem.writeFile():
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()。
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 可能會執行其他設定,例如建立連線或進行驗證。