サンドボックスメソッドの詳細
サンドボックスメソッドは、Nekro AgentプラグインがAIに機能性と対話能力を提供する主要な方法です。AIがサンドボックス環境でコードを実行する際、これらのメソッドを呼び出して情報を取得し、操作を実行したり、さらなる処理を要求したりできます。サンドボックスメソッドのメカニズム、タイプ、記述仕様を理解することは、効果的なプラグインを開発する上で非常に重要です。
サンドボックスメソッドとは何ですか?
AIが自身の能力を超える操作(外部APIへのアクセス、ファイルの読み書き、複雑な計算の実行など)を実行する必要がある場合、通常はプラグインが提供する特定の関数を呼び出すコードを生成します。AIが呼び出すためにプラグインによって公開されているこれらの関数が、私たちが「サンドボックスメソッド」と呼ぶものです。
コア機能:RPC実行メカニズム
非常に重要な概念として、これらのメソッドはAIによって「サンドボックス」環境で呼び出されますが、実際の実行はNekro Agentのメインサービスプロセスで行われ、分離されたサンドボックス内ではありません。この通信はRPC(リモートプロシージャコール)を通じて実現されます。
- AIがサンドボックス内で呼び出しリクエストを開始します。
- Nekro Agentコアシステムがリクエストを受け取り、メインプロセスで対応するプラグインのサンドボックスメソッドを見つけて実行します。
- メソッドの実行結果はRPCを通じてサンドボックス環境に返され、AIによる後続の使用に供されます。
このメカニズムの利点は、プラグインメソッドがサンドボックス環境の分離とセキュリティを維持しながら、メインサービス環境のすべてのリソース(データベース接続、コアサービスAPIなど)にアクセスできることです。ただし、開発者は両者の環境の違いにも注意する必要があり、特にファイルパスなどの取り扱いにおいてです(詳細についてはファイルインタラクションの章を参照してください)。
サンドボックスメソッドの登録
サンドボックスメソッドは@plugin.mount_sandbox_method()デコレータを通じてプラグインインスタンスに登録されます。
from nekro_agent.api.plugin import SandboxMethodType
from nekro_agent.api.schemas import AgentCtx
@plugin.mount_sandbox_method(
method_type=SandboxMethodType.TOOL,
name="calculate_sum",
description="2つの数値の合計を計算します。"
)
async def my_sum_function(_ctx: AgentCtx, num1: int, num2: int) -> int:
"""2つの整数の合計を計算して返します。
Args:
num1 (int): 最初の加数。
num2 (int): 2番目の加数。
Returns:
int: 2つの数値の合計。
"""
return num1 + num2デコレータパラメータ:
method_type(SandboxMethodType): サンドボックスメソッドのタイプを指定し、AIがメソッドを使用する方法とフレームワークが戻り値を処理する方法を決定します。詳細については次のセクションを参照してください。name(str): フロントエンドでユーザーに表示されるメソッド名。命名は簡潔で、メソッドの機能を正確に記述する必要があります。Python関数名と同じである必要はありません。description(str): メソッドの詳細な説明で、フロントエンドでユーザーに表示されます。
サンドボックスメソッドのタイプ(SandboxMethodType)
SandboxMethodTypeは、サンドボックスメソッドの異なる動作パターンを定義する列挙型です。正しいタイプを選択することは、プラグインとAI間のスムーズな対話にとって非常に重要です。
1. SandboxMethodType.TOOL(ツールメソッド)
目的: 特定の、直接使用可能なツールまたは関数を提供します。AIがそれらを呼び出した後、戻り結果を直接利用して後続の思考や応答の生成を行うことができます。これらのメソッドは通常、計算、データ取得、単純な操作などを実行します。
戻り値: 組み込みのシリアル化可能なPython型(
str、int、float、bool、list、dictなど)、またはpickleでシリアル化可能なカスタムオブジェクトを指定できます。フレームワークは戻り値を直接、このメソッドを呼び出したサンドボックス内のコードに渡します。AIとの対話: AIが呼び出した後、メソッドの実行が完了するのを待って戻り値を取得し、その戻り値に基づいてタスクの実行を継続します。通常、新しいAI応答のラウンドを直接トリガーしません。
例: 数学計算、テキスト翻訳、単位変換、特定のデータソースからの構造化情報の取得、システム状態の確認など。
python@plugin.mount_sandbox_method(SandboxMethodType.TOOL, "get_current_time", "現在の日付と時刻を取得します。") async def get_time(_ctx: AgentCtx) -> str: import datetime return datetime.datetime.now().isoformat()
2. SandboxMethodType.AGENT(エージェントメソッド)
目的: AIによるさらなる処理や解釈を必要とする操作を実行したり、AIによる反復思考を必要とする情報を提供したりするために使用されます。これらのメソッドは通常、外部世界との能動的な対話(Web検索など)、複雑な情報の生成、またはAIが結果に基づいて新しい対話ラウンドを生成する必要があるシナリオを含みます。
戻り値: 文字列(
str)型である必要があります。この文字列は通常、実行された操作の結果の説明や、AIが理解してそれに基づいて応答を生成する必要がある情報です。AIとの対話: メソッドによって返された文字列は現在の対話コンテキストに追加され、AIに新しい思考と応答のラウンドを即座に実行させます。AIはこの返された文字列を新しい観測結果または情報入力として扱います。
例: Web検索を実行して要約を返す、外部ナレッジベースを呼び出す、AIが磨きをかけるための複雑なテキストコンテンツを生成する、さらなるユーザー確認を必要とする操作など。
python@plugin.mount_sandbox_method(SandboxMethodType.AGENT, "search_knowledge_base", "キーワードに基づいて内部ナレッジベースを検索し、関連情報を返します。") async def search_kb(_ctx: AgentCtx, query: str) -> str: # search_internal_dbは実際の検索を実行する関数と仮定 results = await search_internal_db(query) if not results: return f"'{query}'に関連する情報がナレッジベースで見つかりませんでした。" return f"'{query}'のナレッジベース検索結果は次のとおりです:\n{results}"
3. SandboxMethodType.BEHAVIOR(ビヘイビアメソッド)
目的: 特定の操作を実行したり、システム状態を変更したりするために使用されます。AIは操作の結果を知る必要がありますが、この結果自体は新しいAI応答のラウンドを直接トリガーすべきではありません。通常、いくつかの「副作用」操作を実行するために使用されます。
戻り値: 文字列(
str)型である必要があります。この文字列はビヘイビアの実行結果の説明です。AIとの対話: メソッドによって返された文字列は、AIとユーザーが参照するためのシステムメッセージとして現在のチャット記録に追加されます。ただし、
AGENTタイプとは異なり、新しいAI応答のラウンドを即座にトリガーしません。AIは後続の思考でこの情報を参照する場合があります。例: メッセージ/メールの送信(送信ステータスを返す)、タイマーの設定(成功メッセージを返す)、特定の設定項目の変更(変更結果を返す)、ユーザーが認知せず結果を記録するバックグラウンドタスクの実行。
pythonfrom nekro_agent.api import message @plugin.mount_sandbox_method(SandboxMethodType.BEHAVIOR, "send_channel_message", "現在のセッションにメッセージを送信します。") async def send_chat_message(_ctx: AgentCtx, text_to_send: str) -> str: try: await message.send_text(_ctx.from_chat_key, text_to_send, _ctx) return f"メッセージ '{text_to_send[:30]}...' が正常に送信されました。" except Exception as e: return f"メッセージの送信に失敗しました: {e}"
4. SandboxMethodType.MULTIMODAL_AGENT(マルチモーダルエージェントメソッド)
目的:
AGENTタイプと似ていますが、マルチモーダルコンテンツ(画像、音声など)を処理・返し、AIがこのマルチモーダルコンテンツを理解して応答する必要がある場合に特化しています。戻り値: 特定の構造に準拠したマルチモーダルメッセージセグメントである必要があります(通常、OpenAIで定義されたメッセージ形式など、画像URLやbase64データを含むメッセージオブジェクト)。
AIとの対話: 返されたマルチモーダルメッセージセグメントは現在の対話コンテキストに追加され、AIに新しい思考と応答のラウンドを即座に実行させます。AIはこのマルチモーダルコンテンツを処理して理解できる必要があります。
例: 画像を生成してAIに返す、テキストを音声に変換してAIに再生させる、ユーザーがアップロードした画像を分析し、テキストと画像を組み合わせたメッセージで分析結果を返す。
python# 疑似コード例、実際の構造はNekro Agentのマルチモーダルメッセージの処理に依存します @plugin.mount_sandbox_method(SandboxMethodType.MULTIMODAL_AGENT, "generate_image_and_comment", "特定のトピックに関する画像とコメントを生成します。") async def generate_image_with_comment(_ctx: AgentCtx, topic: str) -> List[Dict[str, Any]]: # 戻り値の型はdictかもしれません image_url = await generate_image_service(topic) # これは画像生成サービスであると仮定 comment = f"これは '{topic}' に関する画像です。" # OpenAIまたはNekro Agentの内部仕様に準拠したマルチモーダルメッセージ構造を返す return [ { "type": "text", "text": comment }, { "type": "image_url", "image_url": { "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..." # (画像のBase64エンコードされたデータ) } }, ]
適切なタイプの選択:
| 要件シナリオ | 推奨タイプ |
|---|---|
| AIがメソッドによって返されたデータを直接使用して後続処理を行う必要がある | TOOL |
| AIがメソッドのテキスト出力に基づいて新しい対話ラウンドを行う必要がある | AGENT |
| AIが操作を実行した後、結果のみを記録する必要があり、即座の対話は不要 | BEHAVIOR |
| AIがメソッドによって返されたマルチモーダルコンテンツに基づいて新しい対話ラウンドを行う必要がある | MULTIMODAL_AGENT |
サンドボックスメソッドの記述:仕様とベストプラクティス
AIがサンドボックスメソッドを正しく効率的に使用できるようにするために、これらの仕様に従ってください:
明確な関数シグネチャと型アノテーション:
- すべてのサンドボックスメソッドは非同期関数(
async def)である必要があります。 - 最初のパラメータは必ず
_ctx: AgentCtxであり、セッションコンテキスト情報を提供します。 - すべてのパラメータと戻り値に明確なPython型アノテーションを追加します。これはコードの保守に役立つだけでなく、AIがパラメータ型を理解するための重要な基礎でもあります。
- すべてのサンドボックスメソッドは非同期関数(
詳細で構造化されたドックストリング: これはAIがサンドボックスメソッドを理解して使用するための最も重要な情報源の一つです!ドックストリングは特定の形式(Googleスタイル、Numpyスタイルなど)に従い、少なくとも以下を含める必要があります:
- 簡潔な要約行: メソッドの機能を明確に説明します。
- 詳細な説明(オプション): 必要に応じて、メソッドの動作方法、制限、または注意点をさらに説明します。
Args:セクション: すべてのパラメータ(_ctxを除く)をリストし、各パラメータの名前、型、意味を説明します。Returns:セクション: 戻り値の型と意味を説明します。Example:セクション(強く推奨): AIが理解して模倣できる1つ以上のPython呼び出し例を提供します。これは特に複雑なメソッドに有用です。
python@plugin.mount_sandbox_method(SandboxMethodType.TOOL, "get_user_preference", "指定されたユーザーの特定の設定を取得します。") async def get_user_preference(_ctx: AgentCtx, user_id: str, preference_key: str) -> Optional[str]: """ユーザーの設定値を取得します。 ユーザーIDと設定キー名に基づいて、プラグインストレージから対応する設定値を取得します。 Args: user_id (str): ユーザーの一意の識別子。 preference_key (str): クエリする設定のキー名(例:「theme」、「language」)。 Returns: Optional[str]: 設定が見つかった場合はその文字列値を返します。見つからない場合はNoneを返します。 Example: ```python # ユーザー 'user_123' の 'theme' 設定を取得 theme = get_user_preference(user_id="user_123", preference_key="theme") if theme: print(f"ユーザーのテーマは: {theme}") else: print("ユーザーのテーマ設定が見つかりません。") ``` """ # ... 実装ロジック ... stored_value = await plugin.store.get(user_key=user_id, store_key=preference_key) return stored_value適切な命名:
- サンドボックスメソッドの
nameパラメータ(AIに公開される名前)は、AIの呼び出し習慣に合わせた明確で簡潔な命名規則を使用する必要があります(通常、AIの好みに応じてsnake_caseまたはcamelCaseですが、プラグイン内で一貫性を保ってください)。 - Python関数名はより説明的であっても構いません。
- サンドボックスメソッドの
エラーハンドリング:
- メソッド内で発生しうる例外(API呼び出しの失敗、ファイルが見つからない、データフォーマットエラーなど)を適切に処理します。
- キャッチされていない例外を直接AIにスローしないようにしてください。可能であれば、エラー情報を戻り値に(特に
TOOLタイプの場合)、または詳細な情報をログに記録します。 AGENTまたはBEHAVIORタイプの場合、深刻なエラーが発生した場合、返された説明文字列でエラー状況を説明できます。
戻り値の処理:
- 選択した
SandboxMethodTypeの戻り値の型要件を厳密に守ってください。 - 返されたデータがAIによって理解可能で処理可能であることを確認してください。
- 選択した
コンテキスト(
AgentCtx)の正しい使用:AgentCtxオブジェクト(_ctx)には、現在のセッションに関する重要な情報が含まれています。例えば、_ctx.from_chat_key(セッション識別子)、ctx.from_user_id(ユーザー識別子)などです。必要に応じてこの情報を使用してください。例えば、異なるセッションを区別するデータストレージ、メッセージ送信者の取得など。
これらの仕様に従うことで、AIが理解しやすく、使用する意欲が高く、エラーが発生しにくい強力なサンドボックスメソッドを作成できます。
