Rimo Actionsを支える安全なタスク実行基盤

こんにちは、Rimoでソフトウェアエンジニアをしている守屋です。
現在、利用者の指示に応じてさまざまなタスクを実行する「Rimo Actions」を開発しています。
Rimo Actionsのようなエージェント型の機能では、できることを増やすだけでなく、その実行を安全に制御する仕組みも必要です。
今回は、Rimo Actionsのタスク実行基盤を紹介します。
はじめに
Rimo Actionsは、決められたAPIを一度呼ぶだけの機能ではありません。
実行中に情報を集め、計画を更新し、必要なツールを選びながら処理を続けます。
この自由度を業務で活用するには、モデルの判断だけに安全性を委ねるわけにはいきません。
実行環境、入出力、秘密情報、外部サービスの権限を、それぞれ異なる仕組みで制御する必要があります。
Rimo Actionsでは、次の四つを組み合わせています。
E2Bによる実行環境の分離
Google Cloud Model Armorによる入出力の検査
Claude ProxyによるAnthropic APIキーの分離
外部連携Proxyとツール単位の権限制御
Rimo Actionsの信頼境界
Rimo Actionsは、E2B上でClaude Codeを動かします。
E2BのSandboxは、エージェントがコマンドを実行し、ファイルを操作するための隔離されたLinux環境です。
タスクごとに実行環境を分けることで、Claude Codeが操作できるプロセスと一時ファイルをRimoのアプリケーション基盤から切り離せます。
ただし、「サンドボックス内で動かしているから、認証情報を自由に渡してよい」を意味するわけではありません。
E2B上のプログラムは外部ネットワークへアクセスできるため、長期間有効なAPIキーやOAuthトークンを置けば、その情報を利用できる状態になります。
そこで、E2Bを低信頼領域として扱います。
Claude Codeにはタスクの実行に必要な情報だけを渡し、外部サービスの実認証情報はRimoの管理領域に残します。
全体像
次の図は、現在構築している防御のうち、AnthropicとGmailに関係する流れを簡略化したものです。
公開向けに、内部のエンドポイントや認証方式などの詳細は省略しています。

Model Armorによる入出力の検査
利用者から受け取った指示を、そのままClaude Codeへ渡す構成にはしていません。
task-agentは実行前に指示をModel Armorへ送り、設定したポリシーに照らして検査します。
Google Cloud Model Armorは、LLMのプロンプトと応答を検査するためのサービスです。
Google Cloud以外のモデルにもREST API経由で適用できるため、Rimo ActionsではClaude Codeと組み合わせています。
Model Armorの公式ドキュメントでは、次の検査機能が提供されています。
プロンプトインジェクションとJailbreakの検出:モデルに本来の指示を無視させようとする入力を検査する
有害コンテンツの検出:危険、差別、嫌がらせなどのカテゴリを設定したしきい値で検査する
機密データの保護:個人情報、認証情報、組織固有の機密情報などを検出し、設定に応じて非識別化する
悪意あるURLの検出:プロンプトや応答に含まれる危険なURLを検査する
ファイルの検査:文書に含まれる不適切な内容、機密データ、マルウェアなどを検査する
検査結果に対しては、記録だけを行う方式と、該当したコンテンツをブロックする方式を選択できます。
テンプレートごとにフィルターとしきい値を設定できるため、業務や利用者に合わせたポリシーを構成できます。
Rimo Actionsでは、利用者の指示をClaude Codeへ渡す前と、Claude Codeが生成した表示テキストを利用者へ返す前に検査します。
入力だけを検査しても、外部データやツールの結果を受けたモデルが不適切な応答を生成する可能性は残るためです。
一方で、Model Armorは外部サービスの認可を代替しません。
コンテンツの検査を通過した指示であっても、Gmailからメールを取得できるか、メールを送信できるかは別の仕組みで判断します。
Anthropic APIキーをE2Bへ渡さない
Claude CodeがAnthropic APIを利用するには認証が必要です。
しかし、実際のAnthropic APIキーをE2Bへ渡すと、Claude Codeから参照できる秘密情報が増えます。
そこで、task-agent内にClaude Proxyを設けました。
Claude Codeには実APIキーの代わりに、実行ごとに発行する一時的な認証情報とProxyの接続先を渡します。
Claude Proxyは認証情報の有効期限、対象となる実行の状態、利用可能なAPIなどを検証してから、Rimoの管理領域にある実APIキーでAnthropicへ転送します。
タスクが終了すれば、Claude Codeに渡した認証情報も利用できなくなります。
E2B側から実APIキーを読み取る必要はありません。
この構成には、秘密情報の分離に加えて、モデルアクセスを一か所で制御できる利点があります。
将来、利用可能なAPIやモデル、利用量の制限を変更する場合も、E2Bの実行環境へ実APIキーを配布し直さずに対応できます。
Gmailをツール単位で許可する
外部サービスの連携では、「Gmailとの接続を許可した」という判断だけでは権限が広すぎます。
メールの検索と送信では、利用者や組織へ与える影響が異なります。
そのため、Rimo ActionsではGmailの操作をツール単位に分け、接続ごとに権限を設定します。
権限には、次の状態があります。
常に許可:条件を満たす実行からの操作を許可する
実行時に承認:操作内容を利用者へ提示し、承認後に実行する
拒否:操作を実行しない

たとえば、メールの検索と取得は常に許可し、下書きの作成や送信には承認を求める、といった設定ができます。
Claude CodeはGmailのOAuthトークンを直接使用しません。
ツール名と操作内容をtask-agentへ送り、Rimoの管理領域にある外部連携ProxyがGmail APIを呼び出します。
Proxyへ到達しただけでは操作は実行されません。
現在のタスクとの関係、利用者と組織の所有関係、連携状態、ツール権限、重複した要求でないことなどを検証します。
これにより、Claude Codeによる「このツールを使いたい」という判断と、Rimoによる「この操作を許可する」という判断を分離できます。
異なるリスクを異なる層で扱う
各仕組みが制御する対象は異なります。
層 | 制御する対象 |
|---|---|
E2B | コマンド、プロセス、一時ファイルの実行環境 |
Model Armor | 利用者の指示とモデルが生成した表示内容 |
Claude Proxy | Anthropic APIキーとモデルAPIへのアクセス |
外部連携Proxy | OAuthトークンと外部APIへのアクセス |
ツール権限 | 検索、取得、作成、送信などの操作単位の認可 |
実行コンテキストの検証 | 利用者、組織、会話、タスク、操作要求の対応関係 |
Model Armorが不適切な入力を検出しても、APIキーの管理までは行いません。
E2Bが実行環境を分離しても、Gmailの送信権限までは判断しません。
一つの防御ですべてを解決しようとせず、各層が担当する範囲を限定することで、task-agentの自由度を保ちながら制御を追加しています。
さいごに
task-agentの能力を高めるほど、実行できる操作も増えます。
Rimo Actionsでは、モデルの能力と認可の範囲を切り離し、各層が独立して検証できる実行基盤を整えていきます。