問題
LLMはコンテキストに対して2つの通貨で支払います:トークンとアテンション。システムプロンプトに注入されたすべてのツール定義は両方のコストがかかります。単一のMCPサーバーは90以上のツールを公開できます。20個のアクションを持つ5つのAPIコネクタは100個のツール定義を生成します。30個のテーブルを持つ3つのデータベースコネクタはさらに90個のスキーマ説明を生成します。ユーザーが一言も入力する前に、システムプロンプトは50~100KBのコンテキストを消費できます。これは128Kモデルの予算の半分です。 コストはトークンだけではありません。研究と実践は一貫してLLMの精度は無関係なコンテキストが増えるにつれて低下することを示しています。システムプロンプトに80個のツール定義を持つエージェントは、6個のツール定義を持つエージェントよりもツール選択で測定可能に悪いパフォーマンスを示します。モデルは決して使用しないツールスキーマにアテンションを費やし、重要なツールと指示への焦点を薄めます。 素朴なソリューション――すべてを注入し、モデルに整理させる――はスケールしません。FIM Oneは反対のアプローチを採用しています:LLMが決定を下すために必要な最小限を表示し、必要に応じてより多くをリクエストさせる。パターン
プログレッシブディスクロージャーは、すべてのリソースタイプ全体で2層アーキテクチャに従います:- Tier 1 — システムプロンプト内のスタブ。 軽量なサマリー:名前、短い説明、およびLLMが詳細が必要かどうかを判断するのに十分なメタデータ(アクション数、テーブル数、ツール数)。
- Tier 2 — オンデマンドの完全な詳細。 LLMがメタツールを呼び出して、完全なスキーマ、パラメータ、および実行機能を取得します。完全な詳細は、ツール結果メッセージとして会話に入ります — システムプロンプトに永続的に占有されるのではなく、そのターンにスコープされます。
5つの開示メカニズム
FIM Oneは、5つのリソースタイプ全体に段階的な開示を均一に適用します。各リソースは同じ2層パターンを使用しますが、メタツールはそのセマンティクスに合わせてカスタマイズされています。| リソース | メタツール | スタブの表示内容 | オンデマンド返却内容 | 設定変数 | デフォルト |
|---|---|---|---|---|---|
| スキル | read_skill | 名前 + 説明(120文字) | 完全なSOP内容 + 埋め込みスクリプト | SKILL_TOOL_MODE | progressive |
| APIコネクタ | connector | コネクタ名 + アクション一覧 | パラメータ付きの完全なアクションスキーマ | CONNECTOR_TOOL_MODE | progressive |
| データベースコネクタ | database | DB名 + テーブル名 + カウント | カラムスキーマ、SQLクエリ実行 | DATABASE_TOOL_MODE | progressive |
| MCPサーバー | mcp | サーバー名 + ツール一覧 | 完全なツールスキーマ + 呼び出し | MCP_TOOL_MODE | progressive |
| 組み込みツール | request_tools | コンパクトカタログ(名前 + 80文字説明) | セッションに注入された完全なツールスキーマ | (自動) | ツール数 >12 時に自動 |
スキル — read_skill
LLMが最初に見るもの:
read_skill("Customer Complaint SOP")を呼び出し、完全なSOP テキスト — ステップバイステップの指示、決定木、埋め込みスクリプトの数千トークンの可能性がある内容を受け取ります。このコンテンツはシステムプロンプトテキストではなくツール結果として入力されるため、後続のターンで通常のコンテキスト管理(要約、切り詰め)の対象となります。
レガシーモード: SKILL_TOOL_MODE=inlineは完全なスキルコンテンツをシステムプロンプトに直接埋め込みます。スキルが少なく、小さい場合に適しています — ただしスケーリングが悪くなります。
コンテキスト削減: 平均2,000トークンの10個のスキルを持つデプロイメントは、プログレッシブモード(スタブのみ)で約300トークン対インラインモードで約20,000トークンを消費します。これは永続的なコンテキストコストの98%削減です。
APIコネクタ — connector
LLMが最初に見るもの:
connector("discover", "salesforce") はHTTPメソッド、URLパス、パラメータJSONスキーマ、リクエストボディテンプレートを含む完全なアクションスキーマを返します。connector("execute", "salesforce", "get_contacts", {"limit": 10}) は完全な認証注入と監査ログを備えた ConnectorToolAdapter を通じて実行をプロキシします。
レガシーモード: CONNECTOR_TOOL_MODE=legacy は各アクションを個別のツール(salesforce__get_contacts、salesforce__create_lead など)として登録します。20個のアクションを持つコネクタはシステムプロンプト内の20個のツール定義になります。
コンテキスト節約: 15個のアクションを持つコネクタはスタブで約50トークン対完全スキーマで約3,000トークンを生成します。5つのコネクタ:段階的に約250トークン対レガシーで約15,000トークン。
データベースコネクタ — database
LLMが最初に見るもの:
database("list_tables", "hr_postgres")— すべてのテーブル名、説明、列数を返します。database("discover", "hr_postgres", table="employees")— 完全な列スキーマ(名前、型、null許容、主キー、説明)を返します。database("query", "hr_postgres", sql="SELECT ...")— 検証済みのSQLクエリを安全性チェックと行制限で実行します。
DATABASE_TOOL_MODE=legacyは、データベースごとに3つのツール({db}__list_tables、{db}__describe_table、{db}__query)を登録します。5つのデータベースコネクタがある場合、1つではなく15個のツール定義になります。
コンテキスト削減: 30個のテーブルと200列を持つデータベースは、スタブで約80トークン対フルスキーマで約5,000トークンを生成します。複数のデータベースがある場合、削減効果は複合します。
MCP サーバー — mcp
LLM が最初に見るもの:
mcp("discover", "github") は完全なツールカタログとパラメータスキーマを返します。mcp("call", "github", "create_issue", {"title": "Bug report", "body": "..."}) は保存された MCPToolAdapter に委譲され、MCP サーバープロセスと通信します。
レガシーモード: MCP_TOOL_MODE=legacy は各 MCP ツールを個別のツール (github__create_issue、github__list_repos など) として登録します。これにより、ツール選択の閾値を簡単に超過し、不要な選択フェーズをトリガーする可能性があります。
コンテキスト削減: ここでの削減は極めて大きいです。GitHub MCP サーバーの 35 個のツールは 10,000 トークン以上のスキーマを消費する可能性があります。段階的モードでは、スタブは約 100 トークンのコストがかかります。ユーザーがそのコンバーセーション内で GitHub を必要としない場合、これらの 10,000 トークンは決して使用されません。
組み込みツール — request_tools
5番目のメカニズムは、他の4つとは異なるアーキテクチャです。リソースタイプをメタツールの背後に統合するのではなく、ツール選択のボトルネックに対処します — エージェントが12以上のツールを利用可能な場合に何が起こるかです。
動作方法: ツールの総数がREACT_TOOL_SELECTION_THRESHOLD(デフォルト:12)を超える場合、ReActエンジンは軽量なLLM呼び出しを実行して、現在のクエリに最も関連性の高い上位6つのツールを選択します。残りのツールは完全なレジストリに保存されます。request_toolsメタツールが自動的に登録され、すべての未ロードツールをコンパクトなカタログ(名前 + 80文字の説明)としてリストアップします。
LLMが最初に見るもの:
request_tools(tool_names=["web_search", "email_send"])は、これらのツールを完全なレジストリからアクティブなレジストリにコピーします。次のイテレーションでシステムプロンプトが再構築されるため、LLMは完全なスキーマを見ることができます。これは副作用です — ツールは会話の途中でアクティブなツールセットを変更します。
環境変数なし: このメカニズムはツール選択がセットをフィルタリングするときに自動的にアクティベートされます。REQUEST_TOOLS_MODE環境変数はありません。ツール選択を完全に無効にしたい場合は、REACT_TOOL_SELECTION_THRESHOLDを非常に大きな数に設定してください。
コンテキストの節約: 節約は、利用可能なツールの数と選択が選ぶツールの数によって異なります。30個のツールを持つエージェントが、アクティブなスキーマ6個 + request_toolsカタログのみを見る場合、ツールスキーマコンテキストの約60~70%を節約できます。
ツールアセンブリパイプラインへの適合方法
System Overviewでは、リクエストごとの8ステップツールアセンブリパイプラインについて説明しています。段階的開示は複数のポイントで機能します:| パイプラインステップ | 段階的開示の役割 |
|---|---|
| 1. ベース検出 | 効果なし — 組み込みツールは通常通りロードされます |
| 2. エージェントカテゴリフィルタ | 効果なし — カテゴリフィルタリングはモードに関わらず適用されます |
| 3. KB注入 | 効果なし — KBツールは本質的に軽量です(1~2ツール) |
| 4. コネクタロード | ConnectorMetaToolはすべてのAPIコネクタを統合します;DatabaseMetaToolはすべてのDBコネクタを統合します |
| 5. MCPロード | MCPServerMetaToolはすべてのMCPサーバーを1つのツールに統合します |
| 6. スキル注入 | ReadSkillToolはシステムプロンプト内の完全なコンテンツをコンパクトなスタブに置き換えます |
| 7. CallAgent登録 | 効果なし — call_agentは既に単一ツールでカタログを持っています |
| 8. ランタイム選択 | 選択フェーズがセットをフィルタリングするときにrequest_toolsメタツールが登録されます |
設定
4つの環境変数がリソースタイプごとに段階的な開示を制御します:| 変数 | 値 | デフォルト | 効果 |
|---|---|---|---|
SKILL_TOOL_MODE | progressive / inline | progressive | スキル:スタブ + read_skill vs. システムプロンプト内の完全なコンテンツ |
CONNECTOR_TOOL_MODE | progressive / legacy | progressive | APIコネクタ:単一の connector メタツール vs. 個別のアクションツール |
DATABASE_TOOL_MODE | progressive / legacy | progressive | DBコネクタ:単一の database メタツール vs. データベースあたり3つのツール |
MCP_TOOL_MODE | progressive / legacy | progressive | MCPサーバー:単一の mcp メタツール vs. 個別のサーバーツール |
model_config_json フィールドを介してエージェントごとにオーバーライドできます:
progressive を実行し(デフォルト)、特定のエージェントに対して選択的にオーバーライドできます。単一の小さなスキルを持つエージェントは inline モードを使用する場合があります。LLMがすべてのコネクタアクションを事前に確認する必要があるエージェント(例えば、メタツールを確実に呼び出さない微調整されたモデル)は legacy モードを使用する場合があります。
request_tools に設定はありません。 ツール選択がフィルタされたサブセットを生成する場合、自動的にアクティブになります。閾値は REACT_TOOL_SELECTION_THRESHOLD(デフォルト:12)で制御され、最大選択数は REACT_TOOL_SELECTION_MAX(デフォルト:6)で制御されます。
デザイン上の決定
なぜ明示的(LLM駆動)ではなく暗黙的(フレームワーク駆動)なのか?
別の設計アプローチとしては、フレームワークがヒューリスティックに基づいてツールスキーマを自動的に展開する方法が考えられます。例えば、ユーザーのクエリがどのコネクターに関するものかを検出し、LLMがプロンプトを見る前にそのスキーマを注入するといったものです。FIM Oneは3つの理由から、LLM駆動のアプローチを意図的に選択しました:- LLMはヒューリスティックよりも意図検出に優れている。 「顧客がオープンなチケットを持っているか確認して、プロフィールを更新する」というようなクエリは2つのコネクターを含みます。キーワードのヒューリスティックマッチングは脆弱ですが、LLMは自然に両方を識別します。
-
透明性。 LLMが
connector("discover", "jira")を呼び出すと、そのアクションはツールトレースに表示されます。ユーザー(およびデバッグしている開発者)は、どのスキーマがいつ読み込まれたかを正確に確認できます。暗黙的な展開は見えません。 - コンテキスト効率。 フレームワークはLLMがコネクター内のどのアクションを必要とするかを知ることができません。コネクターのすべてのアクションを展開すると、無関係なものにトークンを浪費します。LLMはまずアクション名を(スタブ経由で)確認してから、特定のアクションのスキーマのみをリクエストします。これは純粋な2段階開示です。
なぜ単一の汎用ツールではなくリソースごとのメタツールなのか?
単一のdiscover_resource(type, name) ツールはシンプルに実装できますが、LLMにとっては劣っています。リソースごとのメタツールは以下を提供します:
- 型付きパラメータ。
connectorにはsubcommand、connector、action、parametersがあります。databaseにはsubcommand、database、table、sqlがあります。パラメータスキーマはLLMに正確に何が期待されているかを伝えます。 - 列挙制約。 各メタツールはスキーマ内の列挙値として有効な名前(コネクタ名、データベース名、サーバー名)をリストアップします。LLMはコネクタ名を幻想することはできません。
- カテゴリセマンティクス。
connectorツールはカテゴリconnectorを持ち、databaseはカテゴリdatabaseを持ち、mcpはカテゴリmcpを持ちます。これはエージェントカテゴリフィルタリングに組み込まれます。connectorカテゴリのみで設定されたエージェントはdatabaseまたはmcpメタツールを見ることができません。