自律AIエージェント - サンドボックス実行環境搭載
Semantic Kernel × Playwright × PowerShell × MCP × Sandbox Architecture × Multi-Interface
English | 日本語
Clawleash(クラウリッシュ)は、安全なサンドボックス環境で動作する自律AIエージェントです。Microsoft Semantic KernelとPlaywrightをベースに、Firecrawl風のWebスクレイピング機能と自律的なブラウザ操作を実現します。
- マルチインターフェース: CLI / Discord / Slack / WebSocket / WebRTC に対応
- E2EE対応: WebSocket・WebRTCでエンドツーエンド暗号化
- サンドボックス実行: AppContainer (Windows) / Bubblewrap (Linux) で安全に実行
- フォルダーポリシー: ディレクトリごとにアクセス権限・ネットワーク制御を設定
- ツールパッケージシステム: ZIP/DLLでツールを追加可能
- スキルシステム: YAML/JSONでプロンプトテンプレートを定義・再利用
- MCPクライアント: 外部MCPサーバーのツールを統合利用
- 承認システム: 危険な操作にはユーザー承認が必要
Clawleashは複数の入力インターフェースを同時にサポートします。
| インターフェース | 説明 | E2EE |
|---|---|---|
| CLI | 標準コンソール入力(ビルトイン) | - |
| Discord | Discord Bot経由でメッセージ受信 | - |
| Slack | Slack Bot (HTTP API + ポーリング) | - |
| WebSocket | SignalRによるリアルタイム通信 | ✅ AES-256-GCM |
| WebRTC | DataChannel経由のP2P通信 | ✅ DTLS-SRTP |
アーキテクチャ:
flowchart TB
subgraph Main["Clawleash (Main Application)"]
subgraph IL["InterfaceLoader + FileSystemWatcher (Hot Reload)"]
D1["%LocalAppData%\Clawleash\Interfaces\ を監視"]
D2["新規DLL追加 → 自動ロード → ChatInterfaceManagerに登録"]
end
subgraph CIM["ChatInterfaceManager"]
CLI["CLI<br/>(Built-in)"]
DISC["Discord<br/>(DLL)"]
SLK["Slack<br/>(DLL)"]
WS["WebSocket<br/>(DLL)"]
WRTC["WebRTC<br/>(DLL)"]
end
IL --> CIM
end
設定例 (appsettings.json):
{
"ChatInterface": {
"EnableCli": true,
"EnableHotReload": true,
"InterfacesDirectory": null,
"Discord": {
"Enabled": true,
"Token": "${DISCORD_BOT_TOKEN}",
"CommandPrefix": "!"
},
"Slack": {
"Enabled": true,
"BotToken": "${SLACK_BOT_TOKEN}"
},
"WebSocket": {
"Enabled": true,
"ServerUrl": "wss://localhost:8080/chat",
"EnableE2ee": true
},
"WebRtc": {
"Enabled": true,
"SignalingServerUrl": "wss://localhost:8080/signaling",
"EnableE2ee": true
}
}
}WebSocket・WebRTC通信でE2EEを有効にできます。
flowchart LR
subgraph Client["Client"]
KX1["1. 鍵交換<br/>X25519"]
ENC["2. 暗号化<br/>Plaintext → AES-256-GCM → Ciphertext"]
end
subgraph Server["Server"]
KX2["鍵交換"]
DEC["3. 復号化<br/>AES-256-GCM → Plaintext"]
end
KX1 <-.->|X25519| KX2
ENC -->|wss://| DEC
| 機能 | 説明 |
|---|---|
ScrapeUrl |
URLをスクレイプしてMarkdown形式でコンテンツを取得 |
CrawlWebsite |
Webサイト全体をクロールして複数ページのコンテンツを取得 |
MapWebsite |
サイトマップ(全URL一覧)を高速に取得 |
SearchWeb |
Webを検索(DuckDuckGo使用・APIキー不要) |
BatchScrape |
複数のURLを一括スクレイプ |
| 機能 | 説明 |
|---|---|
CreateFile / ReadFile |
ファイルの作成・読み込み |
ReplaceLine / ReplaceText |
行・テキストの置換 |
InsertLine / DeleteLine |
行の挿入・削除 |
MoveFile / CopyFile |
ファイルの移動・コピー |
CreateFolder / DeleteFolder |
フォルダの作成・削除 |
ShowTree |
ディレクトリ構造をツリー形式で表示 |
- 基本操作: ナビゲート、クリック、テキスト入力、フォーム送信
- スクロール: ページスクロール、最下部への移動
- 待機操作: 要素表示待機、時間待機、ページ読み込み待機
- キーボード: Enter, Tab, Escape, 矢印キーなど
- マウス操作: ダブルクリック、右クリック、ドラッグ&ドロップ
- ストレージ: Cookie、localStorage、sessionStorage
ExtractStructuredData: AIを使った構造化データ抽出ExtractProductInfo: 商品情報の自動抽出SummarizePage: ページ内容の要約
- 目標の計画・実行: 目標を設定して、AIが自動的にタスクを分解・実行
- 自己評価・修正: 実行結果を評価して、失敗時は別のアプローチを試行
- Human-in-the-Loop: 危険な操作にはユーザーの承認が必要
プロンプトテンプレートを再利用可能な「スキル」として定義・実行できます。
| 機能 | 説明 |
|---|---|
list_skills |
利用可能なスキル一覧を表示 |
execute_skill |
指定したスキルを実行 |
show_skill |
スキルの詳細情報を表示 |
register_skill |
新しいスキルを登録(YAML/JSON) |
remove_skill |
スキルを削除 |
スキル定義例(YAML):
name: summarize
description: テキストを要約します
version: "1.0.0"
tags: [text, summarization]
systemInstruction: |
あなたは専門的な要約アシスタントです。
parameters:
- name: text
type: string
description: 要約するテキスト
required: true
- name: style
type: string
description: 要約スタイル
required: false
default: 簡潔
enum: [簡潔, 詳細, 箇条書き]
prompt: |
以下のテキストを{{style}}に要約してください:
{{text}}スキルディレクトリ: %LocalAppData%\Clawleash\Skills\
外部MCPサーバーのツールをClawleash内で利用できます。
| 機能 | 説明 |
|---|---|
list_tools |
MCPサーバーのツール一覧を表示 |
execute_tool |
MCPツールを実行 |
トランスポート対応:
- stdio: ローカルNPXパッケージ、Dockerコンテナ
- SSE: リモートMCPサーバー(HTTP Server-Sent Events)
| プラットフォーム | 実装 | 機能 |
|---|---|---|
| Windows | AppContainer | ケーパビリティベースのアクセス制御 |
| Linux | Bubblewrap | 名前空間分離 |
Windows AppContainerでプロセスに付与するケーパビリティを設定できます。
{
"Sandbox": {
"Type": "AppContainer",
"AppContainerName": "Clawleash.Sandbox",
"Capabilities": "InternetClient, PrivateNetworkClientServer"
}
}利用可能なケーパビリティ:
| ケーパビリティ | 説明 |
|---|---|
InternetClient |
インターネットへの送信接続 |
InternetClientServer |
インターネットへの着信・送信接続 |
PrivateNetworkClientServer |
プライベートネットワークへの接続 |
PicturesLibrary |
画像ライブラリへのアクセス |
VideosLibrary |
ビデオライブラリへのアクセス |
MusicLibrary |
ミュージックライブラリへのアクセス |
DocumentsLibrary |
ドキュメントライブラリへのアクセス |
EnterpriseAuthentication |
企業認証 |
SharedUserCertificates |
共有証明書 |
RemovableStorage |
リムーバブルストレージ |
Appointments |
予定 |
Contacts |
連絡先 |
ディレクトリごとに詳細なアクセス制御を設定できます。より具体的なパスが優先され、子フォルダーで親の設定を上書き可能です。
{
"Sandbox": {
"FolderPolicies": [
{
"Path": "C:\\Projects",
"Access": "ReadWrite",
"Network": "Allow",
"Execute": "Allow",
"Name": "プロジェクトフォルダー"
},
{
"Path": "C:\\Projects\\Secrets",
"Access": "Deny",
"Network": "Deny",
"Name": "機密情報(アクセス禁止)"
},
{
"Path": "C:\\Projects\\Public",
"Access": "ReadOnly",
"Network": "Allow",
"Name": "公開エリア(読み取り専用)"
},
{
"Path": "C:\\Work",
"Access": "ReadWrite",
"Network": "Allow",
"DeniedExtensions": ["exe", "bat", "ps1"],
"MaxFileSizeMB": 50,
"Name": "作業フォルダー"
},
{
"Path": "C:\\Work\\Downloads",
"Access": "ReadWrite",
"Network": "Allow",
"Execute": "Deny",
"EnableAudit": true,
"Name": "ダウンロード(実行禁止・監査あり)"
}
]
}
}ポリシープロパティ:
| プロパティ | 値 | 説明 |
|---|---|---|
Access |
Deny / ReadOnly / ReadWrite / FullControl |
ファイルシステムアクセス |
Network |
Inherit / Allow / Deny |
ネットワークアクセス |
Execute |
Inherit / Allow / Deny |
プロセス実行権限 |
AllowedExtensions |
[".txt", ".json"] |
許可する拡張子 |
DeniedExtensions |
[".exe", ".bat"] |
禁止する拡張子 |
MaxFileSizeMB |
10 |
最大ファイルサイズ |
EnableAudit |
true |
アクセスログ記録 |
継承ルール:
C:\Projects → ReadWrite, Network=Allow
├─ \Secrets → Deny, Network=Deny ← 親を上書き(無効化)
├─ \Public → ReadOnly, Network=Allow ← 読み取り専用に変更
└─ \Data
└─ \Sensitive → Deny ← 深い階層でも上書き可能
- ConstrainedLanguage: デフォルトの安全なモード
- コマンドホワイトリスト: 許可されたコマンドのみ実行
- パス制限: 許可されたパスのみアクセス可能
// CLI用(コンソールで承認確認)
services.AddCliApprovalHandler();
// 自動化用(ルールベース)
services.AddSilentApprovalHandler(config);flowchart TB
subgraph Main["Clawleash (Main)"]
Kernel["Kernel<br/>(AI Agent)"]
ToolLoader["ToolLoader<br/>(ZIP/DLL)"]
ShellServer["ShellServer<br/>(ZeroMQ Router)"]
SkillLoader["SkillLoader<br/>(YAML/JSON)"]
McpClient["McpClientManager<br/>(stdio/SSE)"]
subgraph CIM["ChatInterfaceManager"]
CLI["CLI"]
DISC["Discord"]
SLK["Slack"]
WS["WebSocket"]
WRTC["WebRTC"]
end
end
Kernel --> SkillLoader
Kernel --> ToolLoader
Kernel --> McpClient
Kernel --> CIM
ToolLoader --> ShellServer
subgraph Shell["Clawleash.Shell (Sandboxed)"]
IpcClient["IpcClient<br/>(Dealer)"]
Runspace["ConstrainedRunspaceHost<br/>(PowerShell SDK)"]
end
ShellServer <-.->|MessagePack over ZeroMQ| IpcClient
IpcClient --> Runspace
subgraph Server["Clawleash.Server (Optional)"]
ChatHub["ChatHub<br/>(WebSocket/E2EE)"]
Signaling["SignalingHub<br/>(WebRTC Signaling)"]
Svelte["Svelte Client (Static Files)"]
end
WS --> ChatHub
WRTC --> Signaling
Clowleash/
├── Clawleash/ # メインアプリケーション
│ ├── Execution/
│ │ └── ShellServer.cs # IPCサーバー
│ ├── Tools/
│ │ ├── ToolLoader.cs # ツールローダー
│ │ ├── ToolPackage.cs # パッケージ管理
│ │ ├── ToolProxyGenerator.cs # プロキシ生成 (Reflection.Emit)
│ │ └── ShellToolExecutor.cs # IPC経由実行
│ ├── Skills/
│ │ └── SkillLoader.cs # スキルローダー (YAML/JSON)
│ ├── Mcp/
│ │ ├── McpClientManager.cs # MCPクライアント管理
│ │ ├── McpServerConfig.cs # MCPサーバー設定
│ │ └── McpToolAdapter.cs # Semantic Kernel統合
│ ├── Services/
│ │ ├── IApprovalHandler.cs # 承認システム
│ │ ├── IInputHandler.cs # 入力システム
│ │ ├── InterfaceLoader.cs # インターフェース動的ロード
│ │ ├── ChatInterfaceManager.cs # マルチインターフェース管理
│ │ └── CliChatInterface.cs # CLIインターフェース
│ ├── Sandbox/
│ │ ├── AppContainerProvider.cs # Windows (ケーパビリティ対応)
│ │ ├── BubblewrapProvider.cs # Linux
│ │ ├── FolderPolicy.cs # フォルダーポリシー定義
│ │ ├── FolderPolicyManager.cs # ポリシー管理・継承処理
│ │ ├── NativeMethods.cs # P/Invoke定義
│ │ └── AclManager.cs # ACL管理
│ ├── Security/
│ │ ├── UrlValidator.cs
│ │ ├── PathValidator.cs
│ │ └── CommandValidator.cs
│ └── Plugins/ # Semantic Kernel プラグイン
│ ├── WebCrawlerPlugin.cs
│ ├── BrowserActionsPlugin.cs
│ ├── FileOperationsPlugin.cs
│ ├── SkillPlugin.cs
│ └── ...
│
├── Clawleash.Shell/ # サンドボックスプロセス
│ ├── IPC/IpcClient.cs # IPCクライアント (DealerSocket)
│ └── Hosting/
│ └── ConstrainedRunspaceHost.cs # 制約付きPowerShell
│
├── Clawleash.Abstractions/ # 共有インターフェース
│ ├── Services/
│ │ ├── IChatInterface.cs # チャットインターフェース
│ │ └── ChatMessageReceivedEventArgs.cs
│ └── Security/
│ └── IE2eeProvider.cs # E2EEプロバイダー
│
├── Clawleash.Interfaces.Discord/ # Discord Bot インターフェース
│ ├── DiscordChatInterface.cs
│ └── DiscordSettings.cs
│
├── Clawleash.Interfaces.Slack/ # Slack Bot インターフェース
│ ├── SlackChatInterface.cs
│ └── SlackSettings.cs
│
├── Clawleash.Interfaces.WebSocket/ # WebSocket インターフェース (E2EE)
│ ├── WebSocketChatInterface.cs
│ ├── Security/
│ │ └── AesGcmE2eeProvider.cs
│ └── WebSocketSettings.cs
│
├── Clawleash.Interfaces.WebRTC/ # WebRTC インターフェース (E2EE)
│ ├── WebRtcChatInterface.cs
│ ├── Security/
│ │ └── WebRtcE2eeProvider.cs
│ └── WebRtcSettings.cs
│
├── Clawleash.Server/ # SignalRサーバー (WebSocket/WebRTC)
│ ├── Hubs/
│ │ ├── ChatHub.cs # チャットハブ (E2EE対応)
│ │ └── SignalingHub.cs # WebRTCシグナリング
│ ├── Security/
│ │ ├── KeyManager.cs # 鍵管理
│ │ └── E2eeMiddleware.cs # E2EEミドルウェア
│ └── Client/ # Svelteフロントエンド
│
├── Clawleash.Contracts/ # 共有型定義
│ └── Messages/
│ ├── ShellMessages.cs # IPCメッセージ
│ └── Enums.cs # 共有Enum
│
├── Clawleash.Tests/ # ユニットテスト
│
└── sample-skills/ # サンプルスキル
# リポジトリをクローン
git clone https://github.com/yourusername/Clowleash.git
cd Clawleash
# 依存関係を復元
dotnet restore
# Playwrightブラウザをインストール
pwsh bin/Debug/net10.0/.playwright/package/cli.js installappsettings.json:
{
"AI": {
"ApiKey": "your-api-key",
"ModelId": "gpt-4o",
"Endpoint": "https://api.openai.com/v1"
},
"Sandbox": {
"Type": "AppContainer",
"AppContainerName": "Clawleash.Sandbox",
"Capabilities": "InternetClient, PrivateNetworkClientServer",
"FolderPolicies": [
{
"Path": "C:\\Projects",
"Access": "ReadWrite",
"Network": "Allow",
"Execute": "Allow"
},
{
"Path": "C:\\Projects\\Secrets",
"Access": "Deny",
"Network": "Deny"
}
]
},
"ChatInterface": {
"EnableCli": true,
"EnableHotReload": true,
"Discord": { "Enabled": false },
"Slack": { "Enabled": false },
"WebSocket": { "Enabled": false },
"WebRtc": { "Enabled": false }
},
"Browser": {
"Headless": true
},
"Mcp": {
"Enabled": true,
"Servers": []
}
}dotnet run --project Clawleashdotnet run --project Clawleash.Server
# http://localhost:5000 でサーバー起動
# /chat - WebSocketハブ
# /signaling - WebRTCシグナリングハブ%LocalAppData%\Clawleash\Interfaces\
├── Discord\
│ ├── Clawleash.Interfaces.Discord.dll
│ └── Discord.Net.dll
├── Slack\
│ ├── Clawleash.Interfaces.Slack.dll
│ └── (依存DLL)
├── WebSocket\
│ └── Clawleash.Interfaces.WebSocket.dll
└── WebRTC\
└── Clawleash.Interfaces.WebRTC.dll
ホットリロード対応:新しいDLLを配置すると自動的に読み込まれます。
独自のチャットインターフェースを作成して追加できます。
手順:
Clawleash.Abstractionsを参照したクラスライブラリプロジェクトを作成IChatInterfaceを実装- ビルドして
%LocalAppData%\Clawleash\Interfaces\に配置
詳細な開発ガイドは Clawleash.Abstractions を参照してください。
実装例:
%LocalAppData%\Clawleash\Skills\
└── my-skill.skill.yaml # YAML形式
└── my-skill.skill.json # またはJSON形式
Main プロセスと Shell プロセス間の通信には ZeroMQ + MessagePack を使用します。
| 項目 | 仕様 |
|---|---|
| ライブラリ | NetMQ (ZeroMQ .NET実装) |
| パターン | Router/Dealer |
| シリアライズ | MessagePack (Union属性によるポリモーフィズム) |
| トランスポート | TCP (localhost) |
| 方向 | Main (Router/Server) ↔ Shell (Dealer/Client) |
flowchart TB
subgraph Main["Main プロセス"]
Router["RouterSocket (Server)<br/>- ランダムポートでバインド<br/>- 複数クライアント接続可能<br/>- Identity でクライアント識別"]
end
subgraph Shell["Shell プロセス (Sandboxed)"]
Dealer["DealerSocket (Client)<br/>- 動的に割り当てられたIdentity<br/>- 非同期リクエスト/レスポンス"]
end
Router <-.->|ZeroMQ TCP| Dealer
sequenceDiagram
participant Main
participant Shell
Main->>Main: 1. RouterSocket.BindRandomPort<br/>(例: tcp://127.0.0.1:5555)
Main->>Shell: 2. プロセス起動 --server "tcp://..."
Shell->>Shell: 3. DealerSocket.Connect()
Shell->>Main: ShellReadyMessage<br/>(ProcessId, Runtime, OS)
Main->>Shell: ShellInitializeRequest<br/>(AllowedCommands, Paths)
Shell->>Main: ShellInitializeResponse<br/>(Success, Version)
Note over Main,Shell: 準備完了
public abstract class ShellMessage
{
public string MessageId { get; set; } // 一意識別子
public DateTime Timestamp { get; set; } // UTC タイムスタンプ
}接続完了時に送信される準備完了通知。
public class ShellReadyMessage : ShellMessage
{
public int ProcessId { get; set; } // Shell プロセス ID
public string Runtime { get; set; } // .NET ランタイム情報
public string OS { get; set; } // OS 情報
}Shell 実行環境の初期化。
Request:
public class ShellInitializeRequest : ShellMessage
{
public string[] AllowedCommands { get; set; } // 許可コマンド
public string[] AllowedPaths { get; set; } // 読み書き許可パス
public string[] ReadOnlyPaths { get; set; } // 読み取り専用パス
public ShellLanguageMode LanguageMode { get; set; } // ConstrainedLanguage
}Response:
public class ShellInitializeResponse : ShellMessage
{
public bool Success { get; set; }
public string? Error { get; set; }
public string Version { get; set; }
public string Runtime { get; set; }
}PowerShell コマンドの実行。
Request:
public class ShellExecuteRequest : ShellMessage
{
public string Command { get; set; } // 実行コマンド
public Dictionary<string, object?> Parameters { get; set; }
public string? WorkingDirectory { get; set; }
public int TimeoutMs { get; set; } = 30000;
public ShellExecutionMode Mode { get; set; }
}Response:
public class ShellExecuteResponse : ShellMessage
{
public string RequestId { get; set; }
public bool Success { get; set; }
public string Output { get; set; } // 標準出力
public string? Error { get; set; } // エラーメッセージ
public int ExitCode { get; set; }
public Dictionary<string, object?> Metadata { get; set; }
}ツールパッケージのメソッド呼び出し。
Request:
public class ToolInvokeRequest : ShellMessage
{
public string ToolName { get; set; } // ツール名
public string MethodName { get; set; } // メソッド名
public object?[] Arguments { get; set; } // 引数
}Response:
public class ToolInvokeResponse : ShellMessage
{
public string RequestId { get; set; }
public bool Success { get; set; }
public object? Result { get; set; } // 戻り値
public string? Error { get; set; }
}死活監視・レイテンシ測定。
Request:
public class ShellPingRequest : ShellMessage
{
public string Payload { get; set; } = "ping";
}Response:
public class ShellPingResponse : ShellMessage
{
public string Payload { get; set; } = "pong";
public long ProcessingTimeMs { get; set; } // 処理時間
}Shell プロセスのシャットダウン。
Request:
public class ShellShutdownRequest : ShellMessage
{
public bool Force { get; set; } // 強制終了フラグ
}Response:
public class ShellShutdownResponse : ShellMessage
{
public bool Success { get; set; }
}// Union 属性でポリモーフィック デシリアライズ
[MessagePackObject]
[Union(0, typeof(ShellExecuteRequest))]
[Union(1, typeof(ShellExecuteResponse))]
[Union(2, typeof(ShellInitializeRequest))]
// ...
public abstract class ShellMessage { ... }
// シリアライズ
var data = MessagePackSerializer.Serialize(request);
// デシリアライズ
var message = MessagePackSerializer.Deserialize<ShellMessage>(data);try
{
var response = await shellServer.ExecuteAsync(request);
if (!response.Success)
{
// コマンド実行失敗
Console.WriteLine($"Error: {response.Error}");
}
}
catch (TimeoutException)
{
// Shell からの応答なし
}
catch (InvalidOperationException)
{
// Shell に接続されていない
}var options = new ShellServerOptions
{
StartTimeoutMs = 10000, // 起動タイムアウト
CommunicationTimeoutMs = 30000, // 通信タイムアウト
Verbose = true // 詳細ログ
};外部MCPサーバーを追加して、そのツールをClawleash内で使用できます。
appsettings.json:
{
"Mcp": {
"Enabled": true,
"Servers": [
{
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"],
"enabled": true,
"timeoutMs": 30000,
"useSandbox": true
},
{
"name": "github",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"environment": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
},
"enabled": true
},
{
"name": "remote-server",
"transport": "sse",
"url": "https://api.example.com/mcp/sse",
"headers": {
"Authorization": "Bearer ${API_KEY}"
},
"enabled": true,
"timeoutMs": 60000
}
]
}
}MCP設定プロパティ:
| プロパティ | 説明 | 必須 |
|---|---|---|
name |
サーバー名(一意識別子) | ✅ |
transport |
stdio または sse |
✅ |
command |
実行コマンド(stdio用) | stdio時 |
args |
コマンド引数 | |
environment |
環境変数 | |
url |
サーバーURL(SSE用) | SSE時 |
headers |
HTTPヘッダー(SSE用) | |
enabled |
有効/無効 | |
timeoutMs |
タイムアウト(ミリ秒) | |
useSandbox |
サンドボックスで実行 |
使用可能なツールの確認:
ユーザー: MCPサーバーのツール一覧を表示して
AI: list_tools ツールを実行してツール一覧を表示
ネイティブなFunction CallingライブラリをZIPパッケージとして追加できます。
1. プロジェクト作成
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.*" />
</ItemGroup>
</Project>2. ツールクラスの実装
using Microsoft.SemanticKernel;
namespace MyTools;
public class WeatherTools
{
[KernelFunction("get_weather")]
[Description("指定した都市の天気を取得します")]
public async Task<string> GetWeatherAsync(
[Description("都市名")] string city,
[Description("単位(celsius/fahrenheit)")] string unit = "celsius")
{
// 天気取得ロジック
return $"{city}の天気: 晴れ, 気温: 25{unit}";
}
[KernelFunction("get_forecast")]
[Description("天気予報を取得します")]
public async Task<string> GetForecastAsync(
[Description("都市名")] string city,
[Description("予報日数(1-7)")] int days = 3)
{
return $"{city}の{days}日間予報: 晴れ→曇り→雨";
}
}3. マニフェスト作成(tool-manifest.json)
{
"name": "WeatherTools",
"version": "1.0.0",
"description": "天気情報ツール",
"mainAssembly": "MyTools.dll",
"dependencies": []
}4. パッケージ作成
# ZIPパッケージを作成
zip -r WeatherTools.zip MyTools.dll tool-manifest.json
# 配置
cp WeatherTools.zip "%LocalAppData%\Clawleash\Packages\"パッケージ構成:
WeatherTools.zip
├── tool-manifest.json # マニフェスト
├── MyTools.dll # メインアセンブリ
└── (依存DLL) # 必要に応じて
ホットリロード: PackagesディレクトリにZIPを配置すると自動的にロードされます。
| 項目 | ネイティブツールパッケージ | MCP |
|---|---|---|
| 実行環境 | サンドボックス内で直接実行 | 外部プロセス |
| アクセス制御 | AppContainer + フォルダーポリシー | MCPサーバー側で制御 |
| ネットワーク | ケーパビリティで制御 | MCPサーバー次第 |
| プロセス分離 | Shellプロセス内で分離 | 完全に別プロセス |
| 監査 | 詳細ログ可能 | MCPサーバー依存 |
| デプロイ | ZIPで簡単配置 | MCPサーバー構築必要 |
ネイティブツールパッケージが推奨されるケース:
- 社内ツール・機密データを扱うツール
- 厳密なアクセス制御が必要な場合
- 監査ログが必須な環境
- ネットワークアクセスを制限したい場合
MCPが推奨されるケース:
- 既存のMCPサーバーを利用したい場合
- 外部サービスとの連携
- コミュニティ提供のツールを使用したい場合
ツールパッケージとシェルコマンドは、サンドボックス環境内で安全に実行されます。
アーキテクチャ:
flowchart TB
subgraph Main["Clawleash (Main Process)"]
Kernel["Kernel<br/>(AI Agent)"]
ToolLoader["ToolLoader<br/>(ZIP/DLL)"]
ShellServer["ShellServer<br/>(ZeroMQ Router)"]
Proxy["ToolProxy<br/>(経由で呼出)"]
end
Kernel --> Proxy
Proxy --> ToolLoader
Proxy --> ShellServer
subgraph Shell["Clawleash.Shell (Sandboxed Process)"]
subgraph ALC["AssemblyLoadContext (分離ロード)"]
DLL1["Tool DLL<br/>(分離済み)"]
DLL2["Tool DLL<br/>(分離済み)"]
PS["PowerShell<br/>Constrained"]
end
subgraph Sandbox["AppContainer (Windows) / Bubblewrap (Linux)"]
ACL["- ファイルシステムアクセス制御"]
NET["- ネットワークアクセス制御"]
EXEC["- プロセス実行制御"]
POL["- フォルダーポリシー適用"]
end
end
ShellServer <-.->|IPC| ALC
実行フロー:
-
ツール呼び出し時:
- Kernel → ToolProxy → ShellServer (IPC)
- ShellServer → Shell (サンドボックス内)
- Shell → AssemblyLoadContext → Tool DLL
- 結果を逆順で返却
-
分離の仕組み:
- 各ツールパッケージは独立した
AssemblyLoadContextでロード - アンロード可能(
isCollectible: true) - ツール削除時にメモリ解放
- 各ツールパッケージは独立した
-
セキュリティ境界:
- プロセス分離: Main ↔ Shell は別プロセス
- OSレベル分離: AppContainer/Bubblewrap でリソース制限
- フォルダーポリシー: パスごとのアクセス制御
AppContainerケーパビリティ(Windows):
{
"Sandbox": {
"Type": "AppContainer",
"AppContainerName": "Clawleash.Sandbox",
"Capabilities": "InternetClient, PrivateNetworkClientServer"
}
}| ケーパビリティ | 許可される操作 |
|---|---|
InternetClient |
インターネットへの送信接続 |
PrivateNetworkClientServer |
プライベートネットワークへの接続 |
| なし | ネットワークアクセス禁止 |
フォルダーポリシーによる制御:
{
"Sandbox": {
"FolderPolicies": [
{
"Path": "C:\\Work",
"Access": "ReadWrite",
"Execute": "Deny",
"DeniedExtensions": [".exe", ".bat", ".ps1"]
}
]
}
}# ビルド
dotnet build
# テスト実行
dotnet test
# テスト詳細表示
dotnet test --verbosity normal- このリポジトリをフォーク
- フィーチャーブランチを作成 (
git checkout -b feature/amazing-feature) - 変更をコミット (
git commit -m 'Add amazing feature') - プルリクエストを作成
MIT License - LICENSE を参照
Made with ❤️ by actbit