跳至主要內容

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:

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 array 指定包含 Skill 定義的目錄路徑,詳情請參閱 Skill

全域 Workspace
全域 Workspace 的直接連結

在 Mastra instance 上設定 Workspace。除非 Agent 定義自己的 Workspace,否則所有 Agent 都會繼承此 Workspace:

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 的直接連結

直接為 Agent 指派 Workspace,以覆寫全域 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。這會關閉語言伺服器、瀏覽器、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(本機) 的直接連結

進行本機開發時,將指向同一目錄的 LocalFilesystemLocalSandbox 配對使用。由於兩者都在本機運作,透過檔案系統寫入的檔案可立即供 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。每個掛載路徑必須獨一無二,且不可互相重疊。

備註

filesystemmounts 互相排斥,不能在同一個 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_filewrite_filelist_directorygrep 等)。

僅 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 與 mountslsp: true 不相容,因為兩者都需要在建構時提供具體的 Sandbox instance。詳情請參閱動態 Sandbox

應使用哪種模式?
應使用哪種模式? 的直接連結

情境模式
使用檔案及命令進行本機開發filesystem + sandbox(兩者均為本機並使用同一目錄)
在雲端 Sandbox 內存取雲端儲存空間mounts + sandbox
在一個 Sandbox 中使用多個雲端 Providermounts + sandbox(每個 Provider 使用一個掛載點)
Agent 讀寫檔案,無需執行命令filesystem
Agent 執行命令,無需檔案 Toolsandbox
多角色或多租戶 Agent 使用按請求提供的儲存空間使用 resolver function 的 filesystem
多租戶 Agent 使用按請求提供的執行範圍使用 resolver function 的 sandbox

Tool 設定
Tool 設定 的直接連結

透過 Workspace 的 tools option 設定 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 option
Tool option 的直接連結

Option類型說明
enabledboolean | (context) => booleanTool 是否可用(預設:true)。如為 function,會在列出 Tool 時求值。
requireApprovalboolean | (context) => booleanTool 執行前是否需要用戶批准(預設:false)。如為 function,會在執行時求值,並可存取 args
requireReadBeforeWriteboolean | (context) => boolean適用於寫入 Tool:是否要求先讀取檔案(預設:false)。如為 function,會在執行時求值,並可存取 args
namestringTool 的自訂名稱。取代預設的 mastra_workspace_* 名稱。
maxOutputTokensnumberTool 輸出的 token 上限(預設:2000)。超出此限制的輸出會使用 tiktoken 截斷。

動態 Tool 設定
動態 Tool 設定 的直接連結

接受 function 的 Tool option 會接收 context object 並傳回 boolean,從而實現可感知 context 的 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 的 function 會接收 { requestContext, workspace }requireApprovalrequireReadBeforeWrite 的 function 亦會接收 args,因為它們在呼叫 Tool 時才會求值。

重新映射 Tool 名稱
重新映射 Tool 名稱 的直接連結

重新命名 Workspace Tool,以配合 Agent 預期的慣例。config key 仍然是原有的 WORKSPACE_TOOLS constant,只有公開的名稱會改變。

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 context 會同時包含公開的 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 })
},
},
},
})

傳回 { 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 限制。截斷會按以下層級套用:

  1. 按行保留結尾:命令輸出預設只保留最後 200 行(可透過每個命令的 tail parameter 設定)
  2. 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 讀取後有所變更,寫入便會失敗

檔案寫入安全機制分兩層執行:

  1. Tool 層:寫入 Tool 運行前,讀取追蹤器會檢查檔案自上次讀取後是否已被修改。如檔案已修改,Tool 會引發 FileReadRequiredError
  2. 檔案系統層:寫入時,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()

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 可能會執行其他設定,例如建立連線或進行驗證。