Agent Framework では、標準 API の背後にある ホスティング エージェントと、OpenAI と互換性のあるエンドポイントへの 接続 の両方に対して、OpenAI と互換性のあるプロトコルがサポートされています。
OpenAI プロトコルとは
2 つの OpenAI プロトコルがサポートされています。
- Chat Completions API — チャット操作用の標準ステートレス要求/応答形式
- Responses API — 会話、ストリーミング、実行時間の長いエージェント プロセスをサポートする高度な形式
OpenAI のドキュメントに従って、Responses API が既定で推奨されるアプローチになりました。 組み込みの会話管理、ストリーミング機能、実行時間の長いプロセスのサポートを使用して AI アプリケーションを構築するための、より包括的で機能豊富なインターフェイスを提供します。
Responses API は、次の場合に使用します。
- 新しいアプリケーションのビルド (推奨される既定)
- サーバー側の会話管理が必要です。 ただし、これは要件ではありません。応答 API はステートレス モードで引き続き使用できます。
- 永続的な会話履歴が必要
- 実行時間の長いエージェント プロセスを構築している
- 詳細なイベントの種類を備えた高度なストリーミング機能が必要です
- 個々の応答を追跡および管理する (ID による特定の応答の取得、状態の確認、実行中の応答のキャンセルなど)
チャット完了 APIは次のような場合に使用します。
- チャットの完了形式に依存する既存のアプリケーションの移行
- シンプルでステートレスな要求/応答のインタラクションが必要です
- 状態管理はクライアントによって完全に処理されます
- 既存のツールと統合しようとしており、それらはチャット補完のみをサポートしています。
- レガシ システムとの最大互換性が必要
OpenAI エンドポイントとしてのエージェントのホスティング (.NET)
Microsoft.Agents.AI.Hosting.OpenAI ライブラリを使用すると、OpenAI と互換性のある HTTP エンドポイントを介して AI エージェントを公開し、チャットの完了 API と応答 API の両方をサポートできます。 これにより、エージェントを OpenAI と互換性のある任意のクライアントまたはツールと統合できます。
NuGet パッケージ:
チャット入力候補 API
Chat Completions API は、標準の OpenAI チャット形式を使用してエージェントと対話するためのシンプルでステートレスなインターフェイスを提供します。
ChatCompletions 統合を使用した ASP.NET Core でのエージェントのセットアップ
Chat Completions API を使用してエージェントを公開する完全な例を次に示します。
[前提条件]
1. ASP.NET Core Web API プロジェクトを作成する
新しい ASP.NET Core Web API プロジェクトを作成するか、既存のプロジェクトを使用します。
2. 必要な依存関係をインストールする
次のパッケージをインストールします。
プロジェクト ディレクトリで次のコマンドを実行して、必要な NuGet パッケージをインストールします。
# Hosting.A2A.AspNetCore for OpenAI ChatCompletions/Responses protocol(s) integration
dotnet add package Microsoft.Agents.AI.Hosting.OpenAI --prerelease
# Libraries to connect to Azure OpenAI
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease
# Swagger to test app
dotnet add package Microsoft.AspNetCore.OpenApi
dotnet add package Swashbuckle.AspNetCore
3.Azure OpenAI 接続を構成する
アプリケーションには Azure OpenAI 接続が必要です。
dotnet user-secretsまたは環境変数を使用して、エンドポイントとデプロイ名を構成します。
appsettings.jsonを編集するだけでもかまいませんが、一部のデータはシークレットと見なすことができるため、運用環境にデプロイされたアプリには推奨されません。
dotnet user-secrets set "AZURE_OPENAI_ENDPOINT" "https://<your-openai-resource>.openai.azure.com/"
dotnet user-secrets set "AZURE_OPENAI_DEPLOYMENT_NAME" "gpt-4o-mini"
4. Program.csにコードを追加する
Program.cs の内容を次のコードに置き換えます。
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();
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.");
// Register the chat client
IChatClient chatClient = new AzureOpenAIClient(
new Uri(endpoint),
new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsIChatClient();
builder.Services.AddSingleton(chatClient);
builder.AddOpenAIChatCompletions();
// Register an agent
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");
var app = builder.Build();
app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();
// Expose the agent via OpenAI ChatCompletions protocol
app.MapOpenAIChatCompletions(pirateAgent);
app.Run();
チャット完了エンドポイントのテスト
アプリケーションが実行されたら、OpenAI SDK または HTTP 要求を使用してエージェントをテストできます。
HTTP 要求の使用
POST {{baseAddress}}/pirate/v1/chat/completions
Content-Type: application/json
{
"model": "pirate",
"stream": false,
"messages": [
{
"role": "user",
"content": "Hey mate!"
}
]
}
注: {{baseAddress}} をサーバー エンドポイントに置き換えます。
応答の例を次に示します。
{
"id": "chatcmpl-nxAZsM6SNI2BRPMbzgjFyvWWULTFr",
"object": "chat.completion",
"created": 1762280028,
"model": "gpt-5",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"message": {
"role": "assistant",
"content": "Ahoy there, matey! How be ye farin' on this fine day?"
}
}
],
"usage": {
"completion_tokens": 18,
"prompt_tokens": 22,
"total_tokens": 40,
"completion_tokens_details": {
"accepted_prediction_tokens": 0,
"audio_tokens": 0,
"reasoning_tokens": 0,
"rejected_prediction_tokens": 0
},
"prompt_tokens_details": {
"audio_tokens": 0,
"cached_tokens": 0
}
},
"service_tier": "default"
}
応答には、メッセージ ID、コンテンツ、使用状況の統計情報が含まれます。
チャットの完了は ストリーミングもサポートしています。このストリーミングでは、コンテンツが使用可能になるとすぐに出力がチャンクで返されます。
この機能により、出力を段階的に表示できます。 ストリーミングを有効にするには、 "stream": trueを指定します。
出力形式は、OpenAI チャット補完仕様で定義された Server-Sent イベント (SSE) チャンクで構成されています。
POST {{baseAddress}}/pirate/v1/chat/completions
Content-Type: application/json
{
"model": "pirate",
"stream": true,
"messages": [
{
"role": "user",
"content": "Hey mate!"
}
]
}
私たちが得る出力は、ChatCompletionsのチャンクセットです。
data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[],"object":"chat.completion.chunk","created":0,"model":"gpt-5"}
data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[{"index":0,"finish_reason":"stop","delta":{"content":"","role":"assistant"}}],"object":"chat.completion.chunk","created":0,"model":"gpt-5"}
...
data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[],"object":"chat.completion.chunk","created":0,"model":"gpt-5","usage":{"completion_tokens":34,"prompt_tokens":23,"total_tokens":57,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}}}
ストリーミング応答には同様の情報が含まれていますが、Server-Sent イベントとして配信されます。
レスポンス API
Responses API には、会話管理、ストリーミング、実行時間の長いエージェント プロセスのサポートなどの高度な機能が用意されています。
Responses API 統合を使用した ASP.NET Core でのエージェントのセットアップ
Responses API を使用した完全な例を次に示します。
[前提条件]
チャットの完了の例 (手順 1 から 3) と同じ前提条件に従います。
4. Program.csにコードを追加する
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();
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.");
// Register the chat client
IChatClient chatClient = new AzureOpenAIClient(
new Uri(endpoint),
new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsIChatClient();
builder.Services.AddSingleton(chatClient);
builder.AddOpenAIResponses();
builder.AddOpenAIConversations();
// Register an agent
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");
var app = builder.Build();
app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();
// Expose the agent via OpenAI Responses protocol
app.MapOpenAIResponses(pirateAgent);
app.MapOpenAIConversations();
app.Run();
Responses API のテスト
Responses API はチャットの完了に似ていますが、ステートフルであるため、 conversation パラメーターを渡すことができます。
チャットの完了と同様に、 stream パラメーターがサポートされます。これは、単一の JSON 応答またはイベントのストリームのどちらかの出力形式を制御します。
Responses API は、 response.created、 response.output_item.added、 response.output_item.done、 response.completedなど、独自のストリーミング イベントの種類を定義します。
会話と応答を作成する
応答要求を直接送信することも、Conversations API を使用して会話を作成してから、後続の要求をその会話にリンクすることもできます。
開始するには、新しい会話を作成します。
POST http://localhost:5209/v1/conversations
Content-Type: application/json
{
"items": [
{
"type": "message",
"role": "user",
"content": "Hello!"
}
]
}
応答には、会話 ID が含まれます。
{
"id": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
"object": "conversation",
"created_at": 1762881679,
"metadata": {}
}
次に、要求を送信し、会話パラメーターを指定します。
(応答をストリーミング イベントとして受信するには、要求で "stream": true を設定します)。
POST http://localhost:5209/pirate/v1/responses
Content-Type: application/json
{
"stream": false,
"conversation": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "are you a feminist?"
}
]
}
]
}
エージェントは応答を返し、後で取得できるように会話項目をストレージに保存します。
{
"id": "resp_FP01K4bnMsyQydQhUpovK6ysJJroZMs1pnYCUvEqCZqGCkac",
"conversation": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
"object": "response",
"created_at": 1762881518,
"status": "completed",
"incomplete_details": null,
"output": [
{
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "Arrr, matey! As a pirate, I be all about respect for the crew, no matter their gender! We sail these seas together, and every hand on deck be valuable. A true buccaneer knows that fairness and equality be what keeps the ship afloat. So, in me own way, I’d say I be supportin’ all hearty souls who seek what be right! What say ye?"
}
],
"type": "message",
"status": "completed",
"id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y"
}
],
"usage": {
"input_tokens": 26,
"input_tokens_details": {
"cached_tokens": 0
},
"output_tokens": 85,
"output_tokens_details": {
"reasoning_tokens": 0
},
"total_tokens": 111
},
"tool_choice": null,
"temperature": 1,
"top_p": 1
}
応答には、会話とメッセージの識別子、コンテンツ、使用状況の統計情報が含まれます。
会話アイテムを取得するには、次の要求を送信します。
GET http://localhost:5209/v1/conversations/conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y/items?include=string
これにより、入力メッセージと出力メッセージの両方を含む JSON 応答が返されます。
{
"object": "list",
"data": [
{
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "Arrr, matey! As a pirate, I be all about respect for the crew, no matter their gender! We sail these seas together, and every hand on deck be valuable. A true buccaneer knows that fairness and equality be what keeps the ship afloat. So, in me own way, I’d say I be supportin’ all hearty souls who seek what be right! What say ye?",
"annotations": [],
"logprobs": []
}
],
"type": "message",
"status": "completed",
"id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y"
},
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "are you a feminist?"
}
],
"type": "message",
"status": "completed",
"id": "msg_iLVtSEJL0Nd2b3ayr9sJWeV9VyEASMlilHhfCf02Yxyy9N2y"
}
],
"first_id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y",
"last_id": "msg_lUpquo0Hisvo6cLdFXMKdYACqFRWcFDrlHhfCf02Yxyy9N2y",
"has_more": false
}
複数のエージェントを公開する
両方のプロトコルを使用して、複数のエージェントを同時に公開できます。
var mathAgent = builder.AddAIAgent("math", instructions: "You are a math expert.");
var scienceAgent = builder.AddAIAgent("science", instructions: "You are a science expert.");
// Add both protocols
builder.AddOpenAIChatCompletions();
builder.AddOpenAIResponses();
var app = builder.Build();
// Expose both agents via Chat Completions
app.MapOpenAIChatCompletions(mathAgent);
app.MapOpenAIChatCompletions(scienceAgent);
// Expose both agents via Responses
app.MapOpenAIResponses(mathAgent);
app.MapOpenAIResponses(scienceAgent);
エージェントは、次の場合に使用できます。
- チャットの完了:
/math/v1/chat/completionsと/science/v1/chat/completions - 応答:
/math/v1/responsesと/science/v1/responses
カスタム エンドポイント
エンドポイント パスは次のようにカスタマイズできます。
// Custom path for Chat Completions
app.MapOpenAIChatCompletions(mathAgent, path: "/api/chat");
// Custom path for Responses
app.MapOpenAIResponses(scienceAgent, responsesPath: "/api/responses");
OpenAI-Compatible エンドポイントへの接続 (Python)
Python OpenAIChatClient と OpenAIResponsesClient はどちらも base_url パラメーターをサポートしているため、セルフホステッド エージェント、ローカル推論サーバー (Ollama、LM Studio、vLLM)、サードパーティの OpenAI 互換 API など 、OpenAI と互換性のあるエンドポイントに接続できます。
pip install agent-framework --pre
チャット補完クライアント
OpenAIChatClientとbase_urlを使用して、Chat Completionsに対応したサーバーを指定します。
import asyncio
from agent_framework import tool
from agent_framework.openai import OpenAIChatClient
@tool(approval_mode="never_require")
def get_weather(location: str) -> str:
"""Get the weather for a location."""
return f"Weather in {location}: sunny, 22°C"
async def main():
# Point to any OpenAI-compatible endpoint
agent = OpenAIChatClient(
base_url="http://localhost:11434/v1/", # e.g. Ollama
api_key="not-needed", # placeholder for local servers
model_id="llama3.2",
).as_agent(
name="WeatherAgent",
instructions="You are a helpful weather assistant.",
tools=get_weather,
)
response = await agent.run("What's the weather in Seattle?")
print(response)
asyncio.run(main())
応答クライアント
Responses API をサポートするエンドポイントでは、OpenAIResponsesClient と base_url を併用します。
import asyncio
from agent_framework.openai import OpenAIResponsesClient
async def main():
agent = OpenAIResponsesClient(
base_url="https://your-hosted-agent.example.com/v1/",
api_key="your-api-key",
model_id="gpt-4o-mini",
).as_agent(
name="Assistant",
instructions="You are a helpful assistant.",
)
# Non-streaming
response = await agent.run("Hello!")
print(response)
# Streaming
async for chunk in agent.run("Tell me a joke", stream=True):
if chunk.text:
print(chunk.text, end="", flush=True)
asyncio.run(main())
一般的な OpenAI-Compatible サーバー
base_urlアプローチは、OpenAI チャットの完了形式を公開する任意のサーバーで機能します。
| Server | 基準URL | 注記 |
|---|---|---|
| オラマ | http://localhost:11434/v1/ |
ローカル推論、API キーは必要ありません |
| LM Studio | http://localhost:1234/v1/ |
GUI を使用したローカル推論 |
| vLLM | http://localhost:8000/v1/ |
高スループットのサービス |
| Azure AI Foundry | デプロイ エンドポイント | Azure 資格情報を使用する |
| ホスト型エージェント フレームワーク | あなたのエージェントエンドポイント |
MapOpenAIChatCompletions を介して公開される .NET エージェント |
注
OPENAI_BASE_URLを直接渡す代わりに、base_url環境変数を設定することもできます。 クライアントによって自動的に使用されます。
Azure OpenAI クライアントの使用
Azure OpenAI バリアント (AzureOpenAIChatClient、 AzureOpenAIResponsesClient) は、Azure 資格情報を使用して Azure OpenAI エンドポイントに接続します。 base_url は必要ありません。
from agent_framework.azure import AzureOpenAIResponsesClient
agent = AzureOpenAIResponsesClient().as_agent(
name="Assistant",
instructions="You are a helpful assistant.",
)
環境変数を使用して構成する:
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME="gpt-4o-mini"