このチュートリアルでは、.NET または Python および Agent Framework で AG-UI プロトコルを使用して、サーバー アプリケーションとクライアント アプリケーションの両方を構築する方法について説明します。 AI エージェントをホストする AG-UI サーバーと、対話型の会話用に接続するクライアントを作成する方法について説明します。
あなたが構築するもの
このチュートリアルの最後には、次の内容が含まれます。
- HTTP 経由でアクセス可能な AI エージェントをホストする AG-UI サーバー
- サーバーに接続し、応答をストリームするクライアント アプリケーション
- AG-UI プロトコルが Agent Framework でどのように機能するかを理解する
[前提条件]
開始する前に、次のことを確認してください。
- .NET 8.0 以降
- Azure OpenAI サービスのエンドポイントとデプロイメントの構成
- Azure CLI のインストール と 認証
- ユーザーが Azure OpenAI リソースの
Cognitive Services OpenAI Contributorロールを持っている
注
これらのサンプルでは、Azure OpenAI モデルを使用します。 詳細については、 Azure AI Foundry を使用して Azure OpenAI モデルをデプロイする方法を参照してください。
注
これらのサンプルでは、認証に DefaultAzureCredential を使用します。 Azure で認証されていることを確認します (たとえば、 az login経由)。 詳細については、 Azure ID のドキュメントを参照してください。
Warnung
AG-UI プロトコルはまだ開発中であり、変更される可能性があります。 プロトコルの進化に伴い、これらのサンプルは更新された状態を維持します。
手順 1: AG-UI サーバーの作成
AG-UI サーバーは AI エージェントをホストし、ASP.NET Core を使用して HTTP エンドポイント経由で公開します。
注
サーバー プロジェクトには、 Microsoft.NET.Sdk.Web SDK が必要です。 新しいプロジェクトをゼロから作成する場合は、dotnet new webを使用するか、.csproj ファイルで<Project Sdk="Microsoft.NET.Sdk.Web">ではなくMicrosoft.NET.Sdkが使用されていることを確認します。
必要なパッケージをインストールする
サーバーに必要なパッケージをインストールします。
dotnet add package Microsoft.Agents.AI.Hosting.AGUI.AspNetCore --prerelease
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease
注
Microsoft.Extensions.AI.OpenAI パッケージは、OpenAI のAsIChatClient()をエージェント フレームワークで想定されるChatClient インターフェイスに変換するIChatClient拡張メソッドに必要です。
サーバー コード
Program.csという名前のファイルを作成します。
// Copyright (c) Microsoft. All rights reserved.
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore;
using Microsoft.Extensions.AI;
using OpenAI.Chat;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient().AddLogging();
builder.Services.AddAGUI();
WebApplication app = builder.Build();
string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");
// Create the AI agent
ChatClient chatClient = new AzureOpenAIClient(
new Uri(endpoint),
new DefaultAzureCredential())
.GetChatClient(deploymentName);
AIAgent agent = chatClient.AsIChatClient().CreateAIAgent(
name: "AGUIAssistant",
instructions: "You are a helpful assistant.");
// Map the AG-UI agent endpoint
app.MapAGUI("/", agent);
await app.RunAsync();
主要概念
-
AddAGUI: 依存関係注入コンテナーに AG-UI サービスを登録します -
MapAGUI: AG-UI エンドポイントを自動要求/応答処理と SSE ストリーミングに登録する拡張メソッド -
ChatClientとAsIChatClient():AzureOpenAIClient.GetChatClient()は OpenAI のChatClient型を返します。AsIChatClient()拡張メソッド (Microsoft.Extensions.AI.OpenAIから) は、エージェント フレームワークで必要なIChatClientインターフェイスに変換します -
CreateAIAgent:IChatClientからエージェントフレームワークのエージェントを作成する - ASP.NET コア統合: ストリーミング応答 ASP.NET Core のネイティブ非同期サポートを使用します
- 手順: エージェントは、クライアント メッセージによってオーバーライドできる既定の手順で作成されます
-
構成:
AzureOpenAIClientを使用してDefaultAzureCredential、セキュリティで保護された認証を提供します。
サーバーの構成と実行
必要な環境変数を設定します。
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"
サーバーを実行します。
dotnet run --urls http://localhost:8888
サーバーが http://localhost:8888でリッスンを開始します。
注
手順 2 でクライアントをセットアップして実行している間は、このサーバーを実行したままにします。 完全なシステムを機能させるには、サーバーとクライアントの両方を同時に実行する必要があります。
手順 2: AG-UI クライアントの作成
AG-UI クライアントはリモート サーバーに接続し、ストリーミング応答を表示します。
Important
クライアントを実行する前に、手順 1 の AG-UI サーバーが http://localhost:8888で実行されていることを確認します。
必要なパッケージをインストールする
AG-UI クライアント ライブラリをインストールします。
dotnet add package Microsoft.Agents.AI.AGUI --prerelease
dotnet add package Microsoft.Agents.AI --prerelease
注
Microsoft.Agents.AI パッケージは、CreateAIAgent()拡張メソッドを提供します。
クライアント コード
Program.csという名前のファイルを作成します。
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.AGUI;
using Microsoft.Extensions.AI;
string serverUrl = Environment.GetEnvironmentVariable("AGUI_SERVER_URL") ?? "http://localhost:8888";
Console.WriteLine($"Connecting to AG-UI server at: {serverUrl}\n");
// Create the AG-UI client agent
using HttpClient httpClient = new()
{
Timeout = TimeSpan.FromSeconds(60)
};
AGUIChatClient chatClient = new(httpClient, serverUrl);
AIAgent agent = chatClient.CreateAIAgent(
name: "agui-client",
description: "AG-UI Client Agent");
AgentThread thread = agent.GetNewThread();
List<ChatMessage> messages =
[
new(ChatRole.System, "You are a helpful assistant.")
];
try
{
while (true)
{
// Get user input
Console.Write("\nUser (:q or quit to exit): ");
string? message = Console.ReadLine();
if (string.IsNullOrWhiteSpace(message))
{
Console.WriteLine("Request cannot be empty.");
continue;
}
if (message is ":q" or "quit")
{
break;
}
messages.Add(new ChatMessage(ChatRole.User, message));
// Stream the response
bool isFirstUpdate = true;
string? threadId = null;
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(messages, thread))
{
ChatResponseUpdate chatUpdate = update.AsChatResponseUpdate();
// First update indicates run started
if (isFirstUpdate)
{
threadId = chatUpdate.ConversationId;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"\n[Run Started - Thread: {chatUpdate.ConversationId}, Run: {chatUpdate.ResponseId}]");
Console.ResetColor();
isFirstUpdate = false;
}
// Display streaming text content
foreach (AIContent content in update.Contents)
{
if (content is TextContent textContent)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write(textContent.Text);
Console.ResetColor();
}
else if (content is ErrorContent errorContent)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"\n[Error: {errorContent.Message}]");
Console.ResetColor();
}
}
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"\n[Run Finished - Thread: {threadId}]");
Console.ResetColor();
}
}
catch (Exception ex)
{
Console.WriteLine($"\nAn error occurred: {ex.Message}");
}
主要概念
- Server-Sent イベント (SSE):プロトコルは、ストリーミング応答に SSE を使用します
-
AGUIChatClient: AG-UI サーバーに接続して実装するクライアント クラス
IChatClient -
CreateAIAgent: クライアントからエージェントを作成するための
AGUIChatClientの拡張メソッド -
RunStreamingAsync: 応答を
AgentRunResponseUpdateオブジェクトとしてストリームします -
AsChatResponseUpdate:
ConversationIdや などのチャット固有のプロパティにアクセスするための拡張メソッドResponseId -
スレッド管理:
AgentThreadは要求間で会話コンテキストを維持します -
コンテンツ タイプ: 応答には、メッセージの
TextContentとエラーのErrorContentが含まれます
クライアントの構成と実行
必要に応じて、カスタム サーバー URL を設定します。
export AGUI_SERVER_URL="http://localhost:8888"
別のターミナルでクライアントを実行します (手順 1 のサーバーが実行されていることを確認します)。
dotnet run
手順 3: 完全なシステムのテスト
サーバーとクライアントの両方が実行されている状態で、システム全体をテストできるようになりました。
予期される出力
$ dotnet run
Connecting to AG-UI server at: http://localhost:8888
User (:q or quit to exit): What is 2 + 2?
[Run Started - Thread: thread_abc123, Run: run_xyz789]
2 + 2 equals 4.
[Run Finished - Thread: thread_abc123]
User (:q or quit to exit): Tell me a fun fact about space
[Run Started - Thread: thread_abc123, Run: run_def456]
Here's a fun fact: A day on Venus is longer than its year! Venus takes
about 243 Earth days to rotate once on its axis, but only about 225 Earth
days to orbit the Sun.
[Run Finished - Thread: thread_abc123]
User (:q or quit to exit): :q
色分けされた出力
クライアントは、異なる色を持つさまざまなコンテンツ タイプを表示します。
- 黄色: 開始された通知を実行する
- シアン: エージェントのテキスト応答 (リアルタイムでストリーミング)
- 緑: 実行完了通知
- 赤: エラー メッセージ
しくみ
サーバーサイドフロー
- クライアントがメッセージを含む HTTP POST 要求を送信する
- ASP.NET Core エンドポイントは、次の方法で要求を受信します。
MapAGUI - エージェントは、エージェント フレームワークを使用してメッセージを処理します
- 応答は AG-UI イベントに変換されます
- イベントは、Server-Sent イベント (SSE) としてストリーミングバックされます
- 実行が完了すると接続が閉じる
クライアントサイドフロー
-
AGUIChatClientHTTP POST 要求をサーバー エンドポイントに送信する - サーバーが SSE ストリームで応答する
- クライアントが受信イベントを
AgentRunResponseUpdateオブジェクトに解析する - 各更新プログラムは、そのコンテンツ タイプに基づいて表示されます
-
ConversationIdは、会話の継続性のためにキャプチャされます - 実行が完了するとストリームが完了する
プロトコルの詳細
AG-UI プロトコルでは、次のものが使用されます。
- 要求を送信するための HTTP POST
- ストリーミング応答用の Server-Sent イベント (SSE)
- イベントのシリアル化用の JSON
- 会話コンテキストを維持するためのスレッド ID (
ConversationId) - 個々の実行を追跡するための ID (
ResponseIdとして) を実行する
次のステップ
AG-UI の基本を理解したら、次のことができます。
- バックエンド ツールの追加: ドメインのカスタム関数ツールを作成する
その他のリソース
[前提条件]
開始する前に、次のことを確認してください。
- Python 3.10 以降
- Azure OpenAI サービスのエンドポイントとデプロイメントの構成
- Azure CLI のインストール と 認証
- ユーザーが Azure OpenAI リソースの
Cognitive Services OpenAI Contributorロールを持っている
注
これらのサンプルでは、Azure OpenAI モデルを使用します。 詳細については、 Azure AI Foundry を使用して Azure OpenAI モデルをデプロイする方法を参照してください。
注
これらのサンプルでは、認証に DefaultAzureCredential を使用します。 Azure で認証されていることを確認します (たとえば、 az login経由)。 詳細については、 Azure ID のドキュメントを参照してください。
Warnung
AG-UI プロトコルはまだ開発中であり、変更される可能性があります。 プロトコルの進化に伴い、これらのサンプルは更新された状態を維持します。
手順 1: AG-UI サーバーの作成
AG-UI サーバーは、AI エージェントをホストし、FastAPI を使用して HTTP エンドポイント経由で公開します。
必要なパッケージをインストールする
サーバーに必要なパッケージをインストールします。
pip install agent-framework-ag-ui --pre
または uv を使用します。
uv pip install agent-framework-ag-ui --prerelease=allow
これにより、依存関係として agent-framework-core、 fastapi、および uvicorn が自動的にインストールされます。
サーバー コード
server.pyという名前のファイルを作成します。
"""AG-UI server example."""
import os
from agent_framework import ChatAgent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework_ag_ui import add_agent_framework_fastapi_endpoint
from azure.identity import AzureCliCredential
from fastapi import FastAPI
# Read required configuration
endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT")
deployment_name = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME")
if not endpoint:
raise ValueError("AZURE_OPENAI_ENDPOINT environment variable is required")
if not deployment_name:
raise ValueError("AZURE_OPENAI_DEPLOYMENT_NAME environment variable is required")
chat_client = AzureOpenAIChatClient(
credential=AzureCliCredential(),
endpoint=endpoint,
deployment_name=deployment_name,
)
# Create the AI agent
agent = ChatAgent(
name="AGUIAssistant",
instructions="You are a helpful assistant.",
chat_client=chat_client,
)
# Create FastAPI app
app = FastAPI(title="AG-UI Server")
# Register the AG-UI endpoint
add_agent_framework_fastapi_endpoint(app, agent, "/")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8888)
主要概念
-
add_agent_framework_fastapi_endpoint: AG-UI エンドポイントを自動要求/応答処理と SSE ストリーミングに登録します。 -
ChatAgent: 着信要求を処理する Agent Framework エージェント - FastAPI 統合: ストリーミング応答に FastAPI のネイティブ非同期サポートを使用します
- 手順: エージェントは、クライアント メッセージによってオーバーライドできる既定の手順で作成されます
-
構成: 環境変数からの読み取り
AzureOpenAIChatClient、またはパラメーターを直接受け入れる
サーバーの構成と実行
必要な環境変数を設定します。
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"
サーバーを実行します。
python server.py
または、uvicorn を直接使用します。
uvicorn server:app --host 127.0.0.1 --port 8888
サーバーが http://127.0.0.1:8888でリッスンを開始します。
手順 2: AG-UI クライアントの作成
AG-UI クライアントはリモート サーバーに接続し、ストリーミング応答を表示します。
必要なパッケージをインストールする
AG-UI パッケージは既にインストールされています。これには、 AGUIChatClientが含まれています。
# Already installed with agent-framework-ag-ui
pip install agent-framework-ag-ui --pre
クライアント コード
client.pyという名前のファイルを作成します。
"""AG-UI client example."""
import asyncio
import os
from agent_framework import ChatAgent
from agent_framework_ag_ui import AGUIChatClient
async def main():
"""Main client loop."""
# Get server URL from environment or use default
server_url = os.environ.get("AGUI_SERVER_URL", "http://127.0.0.1:8888/")
print(f"Connecting to AG-UI server at: {server_url}\n")
# Create AG-UI chat client
chat_client = AGUIChatClient(server_url=server_url)
# Create agent with the chat client
agent = ChatAgent(
name="ClientAgent",
chat_client=chat_client,
instructions="You are a helpful assistant.",
)
# Get a thread for conversation continuity
thread = agent.get_new_thread()
try:
while True:
# Get user input
message = input("\nUser (:q or quit to exit): ")
if not message.strip():
print("Request cannot be empty.")
continue
if message.lower() in (":q", "quit"):
break
# Stream the agent response
print("\nAssistant: ", end="", flush=True)
async for update in agent.run_stream(message, thread=thread):
# Print text content as it streams
if update.text:
print(f"\033[96m{update.text}\033[0m", end="", flush=True)
print("\n")
except KeyboardInterrupt:
print("\n\nExiting...")
except Exception as e:
print(f"\n\033[91mAn error occurred: {e}\033[0m")
if __name__ == "__main__":
asyncio.run(main())
主要概念
-
Server-Sent イベント (SSE):プロトコルは SSE 形式 (
data: {json}\n\n) を使用します -
イベントの種類: さまざまなイベントがメタデータとコンテンツを提供します (大文字とアンダースコア)。
-
RUN_STARTED: エージェントが処理を開始しました -
TEXT_MESSAGE_START: エージェントからのテキスト メッセージの開始 -
TEXT_MESSAGE_CONTENT: エージェントからストリーミングされた増分テキスト (deltaフィールド付き) -
TEXT_MESSAGE_END: テキスト メッセージの末尾 -
RUN_FINISHED: 正常に完了しました -
RUN_ERROR: エラー情報
-
-
フィールドの名前付け: イベント フィールドは camelCase を使用します (例:
threadId、runId、messageId) -
スレッド管理:
threadIdは要求間で会話コンテキストを維持します - Client-Side 手順: システム メッセージはクライアントから送信されます
クライアントの構成と実行
必要に応じて、カスタム サーバー URL を設定します。
export AGUI_SERVER_URL="http://127.0.0.1:8888/"
(別のターミナルで) クライアントを実行します。
python client.py
手順 3: 完全なシステムのテスト
サーバーとクライアントの両方が実行されている状態で、システム全体をテストできるようになりました。
予期される出力
$ python client.py
Connecting to AG-UI server at: http://127.0.0.1:8888/
User (:q or quit to exit): What is 2 + 2?
[Run Started - Thread: abc123, Run: xyz789]
2 + 2 equals 4.
[Run Finished - Thread: abc123, Run: xyz789]
User (:q or quit to exit): Tell me a fun fact about space
[Run Started - Thread: abc123, Run: def456]
Here's a fun fact: A day on Venus is longer than its year! Venus takes
about 243 Earth days to rotate once on its axis, but only about 225 Earth
days to orbit the Sun.
[Run Finished - Thread: abc123, Run: def456]
User (:q or quit to exit): :q
色分けされた出力
クライアントは、異なる色を持つさまざまなコンテンツ タイプを表示します。
- 黄色: 開始された通知を実行する
- シアン: エージェントのテキスト応答 (リアルタイムでストリーミング)
- 緑: 実行完了通知
- 赤: エラー メッセージ
curl を使用したテスト (省略可能)
クライアントを実行する前に、curl を使用してサーバーを手動でテストできます。
curl -N http://127.0.0.1:8888/ \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"messages": [
{"role": "user", "content": "What is 2 + 2?"}
]
}'
Server-Sent イベントがストリーミングバックされていることがわかります。
data: {"type":"RUN_STARTED","threadId":"...","runId":"..."}
data: {"type":"TEXT_MESSAGE_START","messageId":"...","role":"assistant"}
data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"...","delta":"The"}
data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"...","delta":" answer"}
...
data: {"type":"TEXT_MESSAGE_END","messageId":"..."}
data: {"type":"RUN_FINISHED","threadId":"...","runId":"..."}
しくみ
サーバーサイドフロー
- クライアントがメッセージを含む HTTP POST 要求を送信する
- FastAPI エンドポイントが要求を受信する
-
AgentFrameworkAgentラッパーが実行を調整する - エージェントは、エージェント フレームワークを使用してメッセージを処理します
-
AgentFrameworkEventBridgeエージェントの更新を AG-UI イベントに変換する - 応答は、Server-Sent イベント (SSE) としてストリーミングバックされます
- 実行が完了すると接続が閉じる
クライアントサイドフロー
- クライアントが HTTP POST 要求をサーバー エンドポイントに送信する
- サーバーが SSE ストリームで応答する
- クライアントが受信
data:行を JSON イベントとして解析する - 各イベントは、その種類に基づいて表示されます
-
threadIdは、会話の継続性のためにキャプチャされます -
RUN_FINISHEDイベントが到着するとストリームが完了する
プロトコルの詳細
AG-UI プロトコルでは、次のものが使用されます。
- 要求を送信するための HTTP POST
- ストリーミング応答用の Server-Sent イベント (SSE)
- イベントのシリアル化用の JSON
- 会話コンテキストを維持するためのスレッド ID
- 個々の実行を追跡するための ID の実行
- イベントの種類の名前付け: アンダースコア付きの大文字 (例:
RUN_STARTED、TEXT_MESSAGE_CONTENT) - フィールドの名前付け: camelCase (例:
threadId、runId、messageId)
一般的なパターン
カスタム サーバー構成
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Add CORS for web clients
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
add_agent_framework_fastapi_endpoint(app, agent, "/agent")
複数のエージェント
app = FastAPI()
weather_agent = ChatAgent(name="weather", ...)
finance_agent = ChatAgent(name="finance", ...)
add_agent_framework_fastapi_endpoint(app, weather_agent, "/weather")
add_agent_framework_fastapi_endpoint(app, finance_agent, "/finance")
エラー処理
try:
async for event in client.send_message(message):
if event.get("type") == "RUN_ERROR":
error_msg = event.get("message", "Unknown error")
print(f"Error: {error_msg}")
# Handle error appropriately
except httpx.HTTPError as e:
print(f"HTTP error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
トラブルシューティング
接続が拒否されました
クライアントを起動する前に、サーバーが実行されていることを確認します。
# Terminal 1
python server.py
# Terminal 2 (after server starts)
python client.py
認証エラー
Azure で認証されていることを確認します。
az login
Azure OpenAI リソースに対する正しいロールの割り当てがあることを確認します。
ストリーミングが機能しない
クライアントのタイムアウトで十分であることを確認します。
httpx.AsyncClient(timeout=60.0) # 60 seconds should be enough
実行時間の長いエージェントの場合は、それに応じてタイムアウトを増やします。
スレッド コンテキストが失われた
クライアントは、スレッドの継続性を自動的に管理します。 コンテキストが失われた場合:
-
threadIdがイベントからキャプチャされていることを確認RUN_STARTED - メッセージ間で同じクライアント インスタンスが使用されていることを確認する
- サーバーが後続の要求で
thread_idを受信することを確認する
次のステップ
AG-UI の基本を理解したら、次のことができます。
- バックエンド ツールの追加: ドメインのカスタム関数ツールを作成する