Azure FunctionsでAzure AI AgentとBing検索を連携する方法【初心者向けコード例付き】

目次
はじめに
MS開発部の松坂です。
Azure FunctionsとAzure AI Agentを使って、Bing検索(Grounding)を活用する方法をご紹介します。Azure AI Foundryの登場により、クラウド上の知識検索をエージェントに簡単に統合できるようになりました。
本記事では、以下の構成で実際に動作する環境を構築し、Azure FunctionsからBing検索を行うまでをステップバイステップで解説します。
前提条件
本記事では、以下のリソースが作成済みであることを前提としています:
-
Azure AI Project
-
Azure AI Hub
-
Azure AI Service
- Azure Function(この記事ではC#を利用しており、その場合はランタイムスタック「.net」)
-
Bing Grounding(Bing Search連携用のGroundingリソース)
これらが未作成の場合は、Azureポータルから事前に準備しておきましょう。
また、アクセス制御の設定を行うので、Azure AI ProjectのリソースにてMicrosoft.Authorization/roleAssignments/write
の権限を持つ必要があります。
ステップ1:AI FoundryでBingと連携
-
Azureポータルにアクセスし、Azure AI Hubを開きます。Azure AI Hubのリソースページから「Launch Azure AI Foundry」をクリックしてAzure AI Foundryを開きます。
-
Azure AI Hubの概要ページが表示されるので、左メニューよりConnected Resourcesを選択します。
-
表示されたページの「新しい接続」を押下、その後「ナレッジ」の項目にある「Bing 検索を使用したグラウンド」を選択してBingのリソースと紐づけを行います。
-
作成したリソースが別サブスクの場合は一覧に表示されないため、「その他のリソースの種類」より「APIキー」を選択して、APIキー及びエンドポイントをBing Searchリソースから取得して設定。
✅ ポイント: この操作で、Azure AI AgentがBing検索を内部的に利用できるようになります。
ステップ2:AIエージェントにBing Groundingをアタッチ
-
Azure AI Foundryのページにて左上のロゴをクリックしてトップページに遷移します。
- トップページより、先ほど紐づけたHubと同列にあるプロジェクトを選択して、Azure AI Projectのページに遷移します。
-
左メニューより「ビルドとカスタマイズ」の「エージェント」を選択
- エージェントページにて新規エージェントの作成及び既存エージェントのナレッジの追加を選択
- データソースにてBingを選択し、Hubにて紐づけたBingとエージェントを紐づけます。
これで、エージェントがBing検索を通じて外部情報へアクセスできるようになります。こちらのエージェントを使ってプレイグラウンド上から確認することも可能です。
ステップ3:Azure Functionにアクセス権を付与
-
Azure Functionの「ID」設定を オン にします(マネージドIDを有効化)。
-
Azure AI Projectの「アクセス制御(IAM)」で、Azyre FunctionのIDに 「Azure AI Developer」 のロールを追加。
🔐 ヒント: このステップにより、FunctionがAIリソースに安全にアクセス可能になります。
ステップ4:Azure Functionからエージェントを呼び出すコード(C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Azure.AI.Projects; using Azure.Identity; using System.Collections.Generic; using Newtonsoft.Json; using System.IO; namespace AzureAIAgentFunction { public static class Function1 { [FunctionName("Function1")] public static async Task Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { string connectionString = Environment.GetEnvironmentVariable("AZURE_AI_AGENT_CONNECTION_STRING"); string agentId = Environment.GetEnvironmentVariable("AZURE_AI_AGENT_ID"); string threadId = Environment.GetEnvironmentVariable("AZURE_AI_THREAD_ID"); if (string.IsNullOrEmpty(connectionString) || string.IsNullOrEmpty(agentId) || string.IsNullOrEmpty(threadId)) { log.LogError("環境変数が設定されていません。"); return new StatusCodeResult(StatusCodes.Status500InternalServerError); } string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody); string userMessage = data?.message; if (string.IsNullOrWhiteSpace(userMessage)) { return new BadRequestObjectResult("メッセージが空です。JSONで { \"message\": \"こんにちは\" } のように送ってください。"); } try { var client = new AgentsClient(connectionString, new DefaultAzureCredential()); var agentResponse = await client.GetAgentAsync(agentId); var agent = agentResponse.Value; var threadResponse = await client.GetThreadAsync(threadId); // スレッドを動的に利用する場合は以下を使用 //var threadResponse = await client.CreateThread(); var thread = threadResponse.Value; var messageResponse = await client.CreateMessageAsync(thread.Id, MessageRole.User, userMessage); var message = messageResponse.Value; var runResponse = await client.CreateRunAsync(thread.Id, agent.Id); var run = runResponse.Value; // Poll until the run is complete while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress) { await Task.Delay(500); runResponse = await client.GetRunAsync(thread.Id, run.Id); run = runResponse.Value; } var messagesResponse = await client.GetMessagesAsync(thread.Id); var messages = messagesResponse.Value.Data; var messageLog = new List(); foreach (var threadMessage in messages) { foreach (var contentItem in threadMessage.ContentItems) { if (contentItem is MessageTextContent textItem) { messageLog.Add($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role}: {textItem.Text}"); } } } // スレッドを動的に利用する場合は以下を使用 //await client.DeleteThreadAsync(threadId); return new OkObjectResult(string.Join("\n", messageLog)); } catch (Exception ex) { log.LogError($"エラーが発生しました: {ex.Message}"); return new StatusCodeResult(StatusCodes.Status500InternalServerError); } } } } |
🧠 解説:
-
DefaultAzureCredential
を使うことで、認証がスムーズに行えます。 -
エージェントにアタッチされたBing Groundingを使い、最新情報を取得しています。
ステップ5:Functionをデプロイして動作確認
-
デプロイはAzure CLIまたはVisual Studioから実行可能
-
エンドポイントにリクエストを送信し、Bing検索を含むレスポンスを確認
-
上記関数をそのままFunctionに発行する場合は、AzureFunctionの環境変数を設定しておく
- 「AZURE_AI_AGENT_CONNECTION_STRING」:AzureAIProjectの接続文字列
- 「AZURE_AI_AGENT_ID」:エージェントID
- 「AZURE_AI_THREAD_ID」:スレッドID
結果
最新情報を取得するチャットを行えることが確認しました。
まとめ
Azure Functions × Azure AI Agent × Bing Groundingの連携により、クラウドファンクションからリアルタイムな情報を扱うAIアプリケーションが簡単に構築できます。
主なポイント
-
Bing Groundingの紐づけとエージェントへのアタッチが鍵
-
FunctionのID権限設定と
DefaultAzureCredential
の活用で安全にアクセス -
リアルタイムな検索回答を含んだAIチャットが構築可能に
以上、最後までご愛読いただき
ありがとうございました。
お問い合わせは、
以下のフォームへご連絡ください。