Azure AI Foundry 内で作成したエージェントをローカル環境やApp Serviceなどから呼び出す方法
はじめに
ChatGPTのWeb検索モードやM365コパイロットのWebモードなどは、最新のデータをインターネットから取得した上で適切な回答をしてくれるが、自分でも似たようなモデルを簡単に作れるものか試してみた。
以前は Bing Search API(既に廃止済み)というのを使い、タイトル・URL・スニペットなどを取得することができたが、現在は Grounding with Bing Search という後継サービスがあり、これをAzure内部のサービスと連携する使い方になるらしい。
Azure AI Foundry上で作成したエージェントのナレッジに、上記のBingリソースを連携すればエージェント自体はできるのだが、実はこれをプレイグラウンド以外から利用する際に少しハマってしまった。
時間が経ったら当時の引っ掛かりポイントを忘れてしまう気がしたので、ローカル環境やApp Service等から呼び出す方法についても触れたメモを残しておこうと思う。
本記事の流れ
- Bingリソースの作成
- Azure AI Foundry 上にエージェント作成
- ローカル環境からエージェントに質問を投げる
- App Service からプライベートエンドポイント経由でエージェントに質問を投げる
1.Bingリソースの作成
Bingリソース のサービスを開き、追加で Grounding with Bing Search 選択する。

入力項目はリソースグループ、リージョン、名前、価格レベル などの基本的な設定内容と、同意チェック(Bingに飛ばされたデータは、Microsoft製品のサービス向上等に使われるため、顧客情報を含むような機密性の高いデータを入れる際の責任はこちらが持てよ。という内容)のみなので、特に迷うところはなし。
※ 私の個人利用においては、価格レベルについて 『Grounding with Bing Search ($35 per 1K transactions)』の一択のみだったのでこれを選択。
2.Azure AI Foundry 上にエージェント作成
AI Foundryのリソースを作成
これについてもリソースグループやリージョン情報などの基本的な設定内容が主である。

※1).最初のプロジェクト名は決める必要があるが、これは任意の名称で構わないため特筆はなし。
※2).比較的新しいサービスのため、今回は東日本リージョンで作成している。
※3).ネットワークについて、リソース作成時に インターネット接続に制限をかけるとなぜかデプロイで失敗するエラーが発生 したため、作成時は一旦パブリックでリソース作成。(後から変更可)
エージェント作成(Bing検索機能付き)
作成したリソースから、『Azure AI Foundry ポータルに移動』をすると以下の様な画面に遷移するため、ここでエージェントの作成を行う。

モデルのデプロイが1つもされていない場合は、まずデプロイモデルを選択した上で、そのモデルを設定する

ナレッジとして先程作成したBingリソースを追加する

※ 更新間隔の入力形式が公式サイトのリファレンスと合っていないため、この記述の仕方で最新の更新情報にもアクセスできるのかは不明
プレイグラウンド上で動作確認をしてみる
以下の様に、その日の天気を聞いてみてちゃんと回答が返ってくればインターネットからの情報は取得できていそう。

3.ローカル環境からエージェントに質問を投げる
ここが今回の一番のハマりポイントになるのだが、AI Foundryのプロジェクト毎にAPIキーやエンドポイントの情報があるため、それを使ってエージェントを呼び出せないか色々と試していた。
しかし、結果的にはAPIキーを使ってエージェントを呼び出すところまではできなかった。
サービス参照先としてここが本当に相応しいのか少し疑念はあるが、自分の試してみた感じでもEntra ID認証を使わないと難しい気はした。(Python SDKを使い、APIキーで接続してエージェントを呼び出すのはリファレンスも見当たらなかった...)
結論としては認証にDefaultAzureCredential を使う必要がある。
これは実行環境に応じて、利用可能な資格情報を自動で探索して使用してくれる認証方法となる。
認証情報には探索順序(優先順位)があり、以下の様になっている。(順序の一部を抜粋)
環境変数 > Azure上のリソースのマネージドID(割り当てあれば) > ローカルでaz loginしている場合はその資格情報
開発用のローカルPCから接続する際は、例えば以下の手順により呼び出すことができる。
サービスプリンシパルを作成する
Entra IDのサービスを開く

- 左メニューから「管理 > アプリの登録」を選択し、「新規登録」をクリック。
-
名前・サポートされるアカウントの種類 を入力する

※ リダイレクトURI:空欄のままでOK(API用途なので不要)
サービスプリンシパルのクライアントシークレットを作成する
上記で作成したサービスプリンシパルを開き、「管理 > 証明書とシークレット」より『新しいクライアントシークレット』を作成する。

※ 作成時に表示される『値』は環境変数の設定に使うためコピーしておく。
開発用のローカルPCに環境変数を設定する
以下の環境変数を追加する。
- Azure_TENANT_ID(=サービスプリンシパルの概要に表示されている テナントID)
- Azure_CLIENT_ID(=サービスプリンシパルの概要に表示されている クライアントID)
- AZURE_CLIENT_SECRET(=証明書の作成でコピーした値)
AI Foundry のIAMに権限を追加
上記で作成したサービスプリンシパルに対して、Azure AI Userのロールを付けてあげる。
※ 割り当てメンバーは「ユーザー、グループ、またはサービス プリンシパル」を選択し、以下の様に検索すれば出てくる。(今回は先程作成した test-**** を検索している)

開発環境のPythonセットアップとサンプルコード
ローカルPCのベースのPython環境は Python 3.12.10 であるが、まずは必要なパッケージは入れる。(venvで作成した仮想環境上にインストール)
pip install azure-identity
pip install azure-ai-projects
サンプルコードは以下のものを使用
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.agents.models import ListSortOrder
### AI Foundry 上のプロジェクト・エージェントに接続するための情報
project_endpoint = <AI Foundryプロジェクトのエンドポイント>
agent_id = <作成したエージェントのID>
### AI Foundry 上のプロジェクトに接続
project_client = AIProjectClient(
endpoint=project_endpoint,
credential=DefaultAzureCredential()
)
### エージェントの取得
agent = project_client.agents.get_agent(agent_id)
### スレッドの作成
thread = project_client.agents.threads.create()
print(f"Created agent thread ID: {thread.id}")
### 質問を投げる
message = project_client.agents.messages.create(
thread_id = thread.id,
role="user",
content="本日の東京の天気を教えてください"
)
run = project_client.agents.runs.create_and_process(
thread_id = thread.id,
agent_id = agent_id
)
### 回答を受け取る
if run.status == "failed":
print(f"Run failed: {run.last_error}")
else:
messages = project_client.agents.messages.list(thread_id=thread.id, order=ListSortOrder.ASCENDING)
for message in messages:
if message.text_messages:
print(f"{message.role}: {message.text_messages[-1].text.value}")
4. App Service からプライベートエンドポイント経由でエージェントに質問を投げる
大まかには前節のローカルPCからの接続と同じ様なものだが、プライベートエンドポイントの作成だったりサービスプリンシパルを使わなかったり、細かな部分が少し異なるため、こちらの方法も簡単に流れを整理しておく。
※ この節では Azure環境からの閉域網接続をすることになるので、VNet や App Serviceを作成することになる。以前に Zenn上で書いた本がある(無料部分で読める)ので、細かな手順はそれを参照とする。
VNetの作成
プライベートエンドポイントを配置するためのサブネットと、App Service のVNet Integrationオプション用のサブネットを作っておく必要がある。1つ気を付ける事は、AI Foundryと同じリージョンにしておいた方が楽。(大したことは書いていないが、以下を参考に)
プライベートエンドポイントとDNSゾーンの作成
プライベートエンドポイントの設定は今回以下の様にしている。

※1).リソース種類は『Microsoft.CognitiveServices/accounts』を選択。
※2).リソースは先程作成したAI Foundryが候補に出てくるため、それを選択。
※3).プライベートIPはサブネットのCIDRに合わせて適当なアドレスを割り当てる。
※4).DNS設定はこのタイミングではせず、別途プライベートDNSゾーンの作成をする。
プライベートDNSゾーンの設定
上記エンドポイントの作成ではFQDNが3つ作られるため、本来であればそれぞれのDNSゾーンを設定する必要があるのだが、今回のエージェントを動かす程度であれば、以下の様にprivatelink.services.ai.azure.comのみ設定でも一応は動く。

この作成したプライベートDNSゾーンの『DNS管理』、Aレコードの追加(AI Foundry のプロジェクト名.privatelink.services.ai.azure.com)と 仮想ネットワークリンクの指定をすればOK。
※ Storage Acccountのリソースにはなるが、プライベートエンドポイントやプライベートDNSゾーンの作成方法はこちらを参考に。
App Service を作成する
VNet-Integration を使いたい場合は価格プランに制約があったかもしれないが、特別気を付けることはなし。(同じく参考に)
マネージドIDの有効化
作成したApp Serviceのリソースに入り、「設定 > ID」よりマネージドIDを『オン』にする。

※ ここで作成されたマネージドIDは、Microsoft Entra IDの「管理 > エンタープライズアプリケーション」から確認できる。
AI Foundry のIAMに権限を追加
ローカルPCからサービスプリンシパルを使い接続する時と同様に、上記で有効化したマネージドIDに対して Azure AI Userのロールを付けてあげる。
※ 割り当てメンバーは「マネージドID」を選択すれば、候補としてすぐ見つかるはず。

App Serviceから質問を投げる
ローカルPCの時と同様にまずは必要なパッケージを入れる。(今回はWebSSH接続で直接入り、インストールを実行)
pip install azure-identity
pip install azure-ai-projects
サンプル用の実行コードは先程のローカルPCからの接続と同じものを使用。
サンプルコード
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.agents.models import ListSortOrder
### AI Foundry 上のプロジェクト・エージェントに接続するための情報
project_endpoint = <AI Foundryプロジェクトのエンドポイント>
agent_id = <作成したエージェントのID>
### AI Foundry 上のプロジェクトに接続
project_client = AIProjectClient(
endpoint=project_endpoint,
credential=DefaultAzureCredential()
)
### エージェントの取得
agent = project_client.agents.get_agent(agent_id)
### スレッドの作成
thread = project_client.agents.threads.create()
print(f"Created agent thread ID: {thread.id}")
### 質問を投げる
message = project_client.agents.messages.create(
thread_id = thread.id,
role="user",
content="本日の東京の天気を教えてください"
)
run = project_client.agents.runs.create_and_process(
thread_id = thread.id,
agent_id = agent_id
)
### 回答を受け取る
if run.status == "failed":
print(f"Run failed: {run.last_error}")
else:
messages = project_client.agents.messages.list(thread_id=thread.id, order=ListSortOrder.ASCENDING)
for message in messages:
if message.text_messages:
print(f"{message.role}: {message.text_messages[-1].text.value}")
問題なく応答できてれば、通信自体は通っていそうなので一旦OK。
AI Foundry への外部接続は閉じる
AI Foundry側のネットワーク設定により、外部接続を『無効』にする。

無効にするとAzureポータルからエージェントの編集ができなくなるが、この状態の時にApp Serviceからエージェントへの問い合わせができるか確認してみる。
問題なく応答が返ってくれば、閉域網における接続ができたと見なす。
※1). 直後だと裏側の設定が反映しきれていない可能性があるため、少し待ってから試した方が良いかも。
※2). あくまでも App Service → AI Foundryの通信が閉域網なだけで、AI Foundry → Bingインデックス はインターネットを経由しているはず。
追伸
久しぶりにAzureのFoundryポータルを開いたら、『新しいFoundry』 というのが使える様になっていた。
未だ色々と挙動が怪しい部分もあったが、プライベートエンドポイント経由でエージェントを呼び出す事できているため、ある程度同じように使える事は確認できた。
ただ、gpt-5.1×Bing Search は新しいFoundry でしか使えなかったり、アプリからの呼び出しにはPythonパッケージのazure-ai-projectsのメインバージョンを変更したりする必要があるため、旧Foundryのものを単純に移植する考えは少し危険かも!
Discussion