Workspace
追加バージョン: @mastra/core@1.1.0
Mastra Workspace は、ファイルの保存やコマンドの実行に使用できる永続的な環境を Agent に提供します。Agent は Workspace Tool を使用して、ファイルの読み書き、シェルコマンドの実行、インデックス化されたコンテンツの検索を行います。
Workspace は次の機能をサポートします。
- Filesystem: ファイルストレージ(読み取り、書き込み、一覧表示、削除、コピー、移動、grep)
- Sandbox: コマンド実行(シェルコマンド)とバックグラウンドプロセス
- LSP inspection: Language Server を介したホバー、定義、実装の照会
- Search: インデックス化されたコンテンツに対する BM25、ベクトル、またはハイブリッド検索
- Skills: Agent 向けの再利用可能な指示
Workspace を使用する場面Workspace を使用する場面への直接リンク
Agent がローカルファイルシステム、シェルコマンド、セマンティックなコード検査、インデックス検索、または再利用可能な Skill の指示にアクセスする必要がある場合に Workspace を使用します。
仕組み仕組みへの直接リンク
Agent に Workspace を割り当てると、Mastra は対応する Tool を Agent の Tool セットに追加します。これにより、Agent はこれらの Tool を使用してファイルを操作し、コマンドを実行できます。
サポートされている機能を任意に組み合わせて Workspace を作成できます。Agent が受け取るのは、設定された機能に関連する Tool だけです。
使用方法使用方法への直接リンク
Workspace の作成Workspace の作成への直接リンク
必要な機能を指定して Workspace クラスをインスタンス化し、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 配列には、Skill 定義を含むディレクトリへのパスを指定します。詳しくは Skills を参照してください。
グローバル Workspaceグローバル Workspaceへの直接リンク
Mastra インスタンスに Workspace を設定します。独自の 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への直接リンク
グローバル Workspace を上書きするには、Agent に 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 はグローバル Workspace と Agent の Workspace を登録するため、実行時に一覧表示および取得できます。mastra.shutdown() を呼び出すと、Mastra が所有する登録済み Workspace が破棄されます。これにより、Language Server、ブラウザー、Sandbox プロセス、Filesystem Provider のハンドルなどの Workspace リソースが閉じられます。
手動でクリーンアップするには、mastra.removeWorkspace() を使用します。レジストリから削除する前に Workspace を破棄する場合は、{ destroy: true } を渡します。
静的 Provider は Workspace が所有します。Resolver ベースの Provider はリクエスト時に Workspace が作成するため、アプリケーションが所有します。Resolver のクリーンアップモデルについては、実行時の Sandbox ライフサイクルの所有権を参照してください。
設定パターン設定パターンへの直接リンク
Workspace は、Agent に必要な機能に応じて複数の設定パターンをサポートします。主な構成要素は filesystem(ファイル Tool)と sandbox(コマンド実行)で、mounts を使用するとクラウドストレージを Sandbox に接続できます。
Filesystem + Sandbox(ローカル)Filesystem + Sandbox(ローカル)への直接リンク
ローカル開発では、同じディレクトリを指す LocalFilesystem と LocalSandbox を組み合わせます。どちらもローカルマシン上で動作するため、Filesystem 経由で書き込まれたファイルは Sandbox 内のコマンドからすぐに利用できます。
const workspace = new Workspace({
filesystem: new LocalFilesystem({ basePath: './workspace' }),
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
})
Agent はファイル Tool と execute_command の両方を受け取ります。これは、すべての機能を利用できる最もシンプルな設定です。
Mounts + Sandbox(クラウドストレージ)Mounts + Sandbox(クラウドストレージ)への直接リンク
Sandbox 内からクラウドストレージにアクセスする必要がある場合は、mounts を使用します。クラウドの Filesystem が 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 を使用してください。
Filesystem のみFilesystem のみへの直接リンク
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(リクエスト単位)動的 Filesystem(リクエスト単位)への直接リンク
リクエストごとに異なる Filesystem を返すには、Resolver 関数を filesystem に渡します。これは、リクエストごとに異なるストレージルートや権限が必要なマルチテナントアプリケーションや、複数のロールを扱う Agent に便利です。
const workspace = new Workspace({
filesystem: ({ requestContext }) => {
const role = requestContext.get('agent-role') || 'guest'
return new LocalFilesystem({
basePath: `/workspaces/${role}`,
readOnly: role !== 'admin',
})
},
})
1つの Workspace インスタンスですべてのリクエストを処理します。Resolver は Tool の実行時に動作するため、リクエストごとに専用の Filesystem が割り当てられます。詳しくは動的 Filesystemを参照してください。
動的 Sandbox(リクエスト単位)動的 Sandbox(リクエスト単位)への直接リンク
リクエストごとに異なる Sandbox を返すには、Resolver 関数を sandbox に渡します。これは、ユーザーやロールごとに分離された作業ディレクトリや異なる実行権限が必要なマルチテナント環境で便利です。
const workspace = new Workspace({
sandbox: ({ requestContext }) => {
const userId = requestContext.get('user-id') as string
return new LocalSandbox({
workingDirectory: `/workspaces/${userId}`,
})
},
})
mounts と lsp: true は構築時に具体的な Sandbox インスタンスを必要とするため、Resolver と併用できません。詳しくは動的 Sandboxを参照してください。
どのパターンを使用すべきですか?どのパターンを使用すべきですか?への直接リンク
| シナリオ | パターン |
|---|---|
| ファイルとコマンドを使用するローカル開発 | filesystem + sandbox(両方ともローカルで、同じディレクトリ) |
| クラウド Sandbox 内からアクセスできるクラウドストレージ | mounts + sandbox |
| 1つの Sandbox で複数のクラウド Provider を使用 | mounts + sandbox(Provider ごとに1つのマウント) |
| Agent はファイルを読み書きし、コマンド実行は不要 | filesystem のみ |
| Agent はコマンドを実行し、ファイル Tool は不要 | sandbox のみ |
| リクエスト単位のストレージを使用する、複数ロール対応またはマルチテナントの Agent | Resolver 関数を指定した filesystem |
| リクエスト単位の実行スコープを使用するマルチテナント Agent | Resolver 関数を指定した sandbox |
Tool の設定Tool の設定への直接リンク
Workspace の tools オプションを使用して 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 オプション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 出力の最大トークン数(デフォルト: 2000)。この制限を超えた出力は、tiktoken を使用して切り詰められます。 |
Tool の動的設定Tool の動的設定への直接リンク
関数を受け取る Tool オプションにはコンテキストオブジェクトが渡され、関数は真偽値を返します。これにより、コンテキストに応じた 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 の関数は { requestContext, workspace } を受け取ります。requireApproval と requireReadBeforeWrite の関数は Tool の呼び出し時に評価されるため、さらに args も受け取ります。
Tool 名の再マッピングTool 名の再マッピングへの直接リンク
Agent が想定する命名規則に合わせて Workspace Tool の名前を変更できます。設定キーには元の WORKSPACE_TOOLS 定数を使用し、公開される名前だけが変わります。
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 には、デフォルトの mastra_workspace_* 名ではなく、view、search_content、find_files、execute_command、lsp_inspect が表示されます。Tool 名は一意である必要があり、重複した名前や他のデフォルト名と競合する名前を指定するとエラーがスローされます。
Tool フックTool フックへの直接リンク
有効な Workspace Tool の各呼び出し前後にロジックを実行するには、tools.hooks を設定します。フックは名前の再マッピング後に実行されるため、フックのコンテキストには、公開された 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 })
},
},
},
})
beforeToolCall から { proceed: false, output } を返すと、Tool の呼び出しをスキップし、output を結果として使用します。
所有元の Agent にも Tool フックが定義されている場合、Workspace のフックは Agent のフックラッパー内で実行されます。実行順序は、Agent の beforeToolCall、Workspace の beforeToolCall、Tool、Workspace の afterToolCall、Agent の afterToolCall です。
LSP inspectionLSP inspectionへの直接リンク
Workspace で lsp を有効にすると、Language Server を介したセマンティックなコード検査が追加されます。デフォルトでは mastra_workspace_lsp_inspect Tool が追加され、ホバー情報、定義位置、および特定のカーソル位置にあるシンボルの実装を返せます。
設定、例、Tool 名の再マッピングについては、LSP inspectionを参照してください。
出力の切り詰め出力の切り詰めへの直接リンク
Workspace Tool は、LLM のコンテキスト制限を超えないように大きな出力を自動的に切り詰めます。次の切り詰め処理が適用されます。
- 行数に基づく末尾の取得: コマンド出力はデフォルトで末尾の200行に制限されます(コマンドごとに
tailパラメーターで設定可能) - トークン数に基づく制限: Tool の出力はデフォルトで2000トークンに制限されます
Tool ごとに maxOutputTokens を設定して、トークン数の上限を調整します。
const workspace = new Workspace({
// ...
tools: {
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
maxOutputTokens: 5000,
},
},
})
ANSI エスケープコード(色、カーソルシーケンス)は、モデルに渡される前にコマンド出力から自動的に削除されます。
書き込み前の読み取り書き込み前の読み取りへの直接リンク
書き込み Tool で requireReadBeforeWrite を有効にすると、Agent はファイルを書き込む前にそのファイルを読み取る必要があります。これにより、Agent が確認していないファイルの上書きを防ぎます。
- 新規ファイル: 読み取らずに書き込めます(まだ存在しないため)
- 既存ファイル: 最初に読み取る必要があります
- 外部で変更されたファイル: Agent が読み取った後にファイルが変更されていると、書き込みは失敗します
ファイル書き込みの安全性は、次の2つのレイヤーで確保されます。
- Tool レイヤー: 書き込み Tool の実行前に、読み取りトラッカーが、ファイルが最後に読み取られてから変更されていないか確認します。変更されている場合、Tool は
FileReadRequiredErrorをスローします。 - Filesystem レイヤー: 書き込み時に、
writeFile()がファイルの現在の変更時刻を、書き込みオプションのexpectedMtimeで渡された想定値と比較します。一致しない場合はStaleFileErrorをスローします。これにより、Tool レイヤーでの確認から実際の書き込みまでの間に行われた外部変更(たとえば、エディターによるファイル保存)を検出できます。
requireReadBeforeWrite が有効な場合、Workspace Tool は記録された変更時刻を自動的に渡します。Tool の外部で filesystem.writeFile() を呼び出す場合は、expectedMtime を直接指定することもできます。
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() を手動で呼び出してください。
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のファイルをインデックス化します。詳しくは Search and Indexing を参照してください
外部 Provider では、接続の確立や認証など、追加のセットアップが行われる場合があります。