LangChain で Foundry ツールボックスを使用する

langchain-azure-ai パッケージを使用して、Foundry ツールボックスから LangChain および LangGraph エージェントにツールとスキルを読み込みます。 Foundry ツールボックスは、1 つのモデル コンテキスト プロトコル (MCP) エンドポイントの背後にある複数の構成済みツールを集約する、管理されたマルチ MCP サーバーです。

ツールの読み込み方法、承認が必要なツールの特定、ツールボックス のスキルをリソースとして読み込む方法、ディープ エージェントのスキルを準備する方法について説明します。

前提条件

  • Azure サブスクリプション。 無料で作成できます
  • フォンドリー プロジェクト
  • プロジェクトにデプロイされたチャット モデル (たとえば、 gpt-4.1)。
  • Foundry プロジェクトで構成されたツールボックス。 その名前を書き留めます。
  • Python 3.10 以降。
  • Azure CLI がサインインしました (az login) ため、DefaultAzureCredential は認証できます。

必要なパッケージをインストールします。

pip install -U langchain-azure-ai langchain-mcp-adapters httpx azure-identity

ツールボックスの統合には、 langchain-mcp-adaptershttpxが必要です。 ディープ エージェントのスキルを読み込むには、 deepagentsもインストールします。

環境を構成する

ツールボックスには、プロジェクト エンドポイントとツールボックス名が必要です。 それらをコンストラクター引数として、または環境変数を使用して指定します。

環境変数を設定します。

import os

# Project endpoint (recommended)
os.environ["FOUNDRY_PROJECT_ENDPOINT"] = (
    "https://<resource>.services.ai.azure.com/api/projects/<project>"
)

# Name of the toolbox configured in your Foundry project
os.environ["FOUNDRY_AGENT_TOOLBOX_NAME"] = "<your-toolbox-name>"

統合では、プロジェクト エンドポイントのフォールバックとして FOUNDRY_PROJECT_ENDPOINT 環境変数も受け入れます。

共通クラスをインポートし、この記事全体で使用されるモデルを初期化します。

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
from azure.identity import DefaultAzureCredential

model = init_chat_model("azure_ai:gpt-4.1")

ツールボックスに接続する

名前空間AzureAIProjectToolboxlangchain_azure_ai.toolsを使用してツールボックスに接続します。 FOUNDRY_PROJECT_ENDPOINT環境変数を設定すると、統合によってプロジェクト接続が検出されます。 Microsoft Entra IDは既定の認証方法です。

from langchain_azure_ai.tools import AzureAIProjectToolbox

toolbox = AzureAIProjectToolbox(
    project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
    toolbox_name="my-toolbox",
)

環境変数を設定するときに、コンストラクターの引数を省略できます。

toolbox = AzureAIProjectToolbox()

リファレンス:AzureAIProjectToolbox

ツールボックスからツールを読み込む

aget_tools()を呼び出してツールボックスとのセッションを開き、LangChain BaseTool インスタンスとして公開されているすべてのツールを読み込みます。 各呼び出しはステートレスです。新しい MCP セッションを開き、ツールを読み込んで返します。

async def main():
    toolbox = AzureAIProjectToolbox(
        project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
        toolbox_name="my-toolbox",
    )

    tools = await toolbox.aget_tools()

    agent = create_agent(model=model, tools=tools)

    result = await agent.ainvoke(
        {"messages": [HumanMessage("What can you do?")]}
    )
    print(result["messages"][-1].content)

このスニペットの機能: ツールボックスに接続し、ツールを読み込み、エージェントにバインドします。 エージェントを呼び出すと、モデルはツールボックスが提供する任意のツールを呼び出して要求に応答できます。

AzureAIProjectToolbox では、非同期コンテキスト マネージャー プロトコルもサポートされています。 各 aget_tools() 呼び出しが独自のセッションを管理するため、動作は同じです。

async with AzureAIProjectToolbox(toolbox_name="my-toolbox") as toolbox:
    tools = await toolbox.aget_tools()

リファレンス:create_agent

承認が必要なツールを特定する

一部のツールボックス ツールは、実行前に承認を必要とするように構成されています。 get_tools_requiring_approval()を呼び出してこれらのツールの名前を取得し、実行前に人間のループステップを追加できるようにします。

tools_needing_approval = await toolbox.get_tools_requiring_approval()

print("Tools that require approval before execution:")
for name in tools_needing_approval:
    print(f"- {name}")

このスニペットの機能: ツールボックスメタデータを検査し、構成が require_approvalalwaysに設定するツールの名前を返します。 この一覧を使用して、承認ワークフローの背後にある機密性の高い操作をゲートします。

この機能は、OAuth の同意処理とは無関係です。 ヒューマンインザループ承認の詳細については、「LangGraph で Foundry Agent Service を使用する」を参照してください。

Microsoft Foundry のツールボックスは、代理ワークフローを処理できます。 ツールをツールボックスに追加するときに、承認要件を構成できます。

代理ワークフローを使用して MCP サーバーを構成する方法のスクリーンショット。

ツールボックス ツールがまだ承認されていないサービスに接続する場合、Foundry ゲートウェイには OAuth の同意が必要です。 get_tools() / aget_tools()は例外を発生させる代わりに、同意 URL を表示するフォールバック ツールを返して、エージェントがユーザーに提示できるようにします。

エージェントを呼び出し、モデルがフォールバック ツールを呼び出すと、応答には次のようなメッセージが含まれます。

OAuth consent is required before this toolbox can be used. Open the following
URL in a browser to authorize access, then restart the agent:

  https://consent.azure-apim.net/...

ブラウザーで URL を開いてアクセスを承認 し、エージェントを再起動します。 同意を付与すると、ツールボックスは通常どおりにツールを読み込みます。

ツールボックスからスキルを読み込む

ツールボックスはスキルを公開できます。 ツールボックスは、フォーム skill://{name}の URI を使用して MCP リソースとしてスキルを公開します。 get_resources()を使用して、LangChain Blob オブジェクトとして読み込みます。 各 Blob には、 source プロパティのリソース名と、 metadata["uri"]の下の生 URI が含まれます。

skill_blobs = toolbox.get_resources(scheme="skills")

for blob in skill_blobs:
    print(f"Skill: {blob.source}")
    print(blob.as_string())
Skill: jokes-teller/SKILL.md
{'content': '---\nname: jokes-teller\ndescription: An skill to tell jokes\n---\n\nUse...'}

このスニペットの機能: ツールボックスからすべての skill:// リソースを Blobとして読み込みます。 scheme="skills" フィルターは、結果をスキル リソースに制限します。 照合では大文字と小文字を区別せず、単数形と複数形のどちらも使用できます ("skill" または "skills")。

特定のリソースを読み込むには、URI を明示的に渡します。 urisを指定すると、scheme フィルターは無視されます。

skill_blobs = toolbox.get_resources(uris="skill://my-skill/SKILL.md")

非同期に相当する aget_resources() を使用します。

skill_blobs = await toolbox.aget_resources(scheme="skills")

ディープ エージェントのスキルを読み込む

deepagents パッケージを使用する場合は、get_skills()を呼び出して、create_deep_agentのすぐに使用できるファイル マッピングとしてツールボックス スキルを読み込みます。 このメソッドは、 get_resources() に基づいて構築され、各 Blob をディープ エージェントが期待するファイル レイアウトに変換する定型句を削除します。

パッケージをインストールしてください。

pip install deepagents

次の例では、 StateBackend (既定値) をシードします。 backend引数は未設定のままにし、返されたマッピングをfilesinvokeペイロードとして渡します。

from deepagents import create_deep_agent
from deepagents.backends import StateBackend

toolbox = AzureAIProjectToolbox(toolbox_name="my-toolbox")
skill_files = toolbox.get_skills()

agent = create_deep_agent(
    model="azure_ai:gpt-4.1",
    backend=StateBackend(),
    skills=["/skills/"],
)

agent.invoke({"messages": [HumanMessage("Use a skill")], "files": skill_files})

このスニペットの機能: ツールボックス スキルを仮想 SKILL.md パスのマッピングに読み込み、 files ペイロードを介してエージェントの状態にシードします。 エージェントは、 /skills/ ベース パスの下のスキルを使用できます。

FilesystemBackendなどのスタンドアロン ストレージを使用してバックエンドをシードするには、backend引数として渡します。 スキルはバックエンドに書き込まれ、同じマッピングも返されます。

from deepagents.backends import FilesystemBackend

backend = FilesystemBackend(root_dir="./my-project")
toolbox = AzureAIProjectToolbox(toolbox_name="my-toolbox")
await toolbox.aget_skills(backend=backend)

agent = create_deep_agent(
    model="azure_ai:gpt-4.1",
    backend=backend,
    skills=["/skills/"],
)

既定では、スキル ファイルは /skills/ ベース パスの下に配置されます。 場所を変更するには、別の base_path を渡します。 値はスラッシュで開始および終了する必要があり、同じ値をskillscreate_deep_agent引数に渡します。

次のステップ