ホストされるエージェントは、Microsoft Foundry プラットフォームとの特定のランタイム コントラクトを満たすコンテナーです。 このリファレンスでは、プラットフォームがコンテナーに期待する内容と、SDK アダプター パッケージがこれらの要件を満たすのにどのように役立つかについて説明します。
SDK アダプター パッケージは、コントラクト全体を実装します。
azure-ai-agentserver-responsesまたはazure-ai-agentserver-invocationsを使用する場合は、ハンドラー ロジックのみを実装します。
GitHub Copilotなどのコーディング エージェントを使用してホストされたエージェント コンテナーを実装または確認する場合、Microsoft Foundry Skill は、ランタイム コントラクト、アダプターの使用状況、デプロイの前提条件を確認するのに役立ちます。
契約要件
コンテナーでは、次の手順を実行する必要があります。
| Requirement | Detail |
|---|---|
| ポート 8088 でリッスンする | HTTP/1.1、プレーン HTTP。 プラットフォームは TLS を終了します。 |
| 正常性プローブを提供する |
200 OKからGET /readinessを返します。 |
| プロトコル エンドポイントを実装する |
POST /responsesまたはPOST /invocationsの少なくとも 1 つを提供します。 |
| プラットフォーム環境変数を使用する | 起動時にプラットフォームによって挿入される変数を読み取ります。 |
| 正常にシャットダウンする |
SIGTERMで書き込みをフラッシュし、接続を閉じます。 |
プロトコル エンドポイント
プロトコルは、Foundry とエージェント コンテナーの間の HTTP コントラクトを定義します。 コンテナーには、少なくとも 1 つのプロトコル エンドポイントが実装されています。
応答プロトコル
応答プロトコルは、OpenAI Responses API を実装します。 プラットフォームは POST /responses に要求を送信し、JSON 応答または Server-Sent イベント (SSE) ストリームを受け取ります。
| 特徴 | Detail |
|---|---|
| エンドポイント | POST /responses |
| 入力 | OpenAI Responses API 要求 (input、 model、 streamなど) |
| アウトプット | JSON 応答オブジェクトまたは応答イベントの SSE ストリーム |
| 会話履歴 |
conversation.idが存在する場合に SDK アダプターによって自動的にハイドレートされる |
| ストリーミング |
text/event-stream コンテンツ タイプの SSE |
標準の選択肢として応答プロトコルを使用します。 OpenAI API エコシステムと互換性があります。
呼び出しプロトコル
呼び出しプロトコルは、最小限のパススルー プロトコルです。 ペイロード構造を定義すると、プラットフォームは解釈なしでそれを通過します。
| 特徴 | Detail |
|---|---|
| エンドポイント | POST /invocations |
| 入力 | ハンドラーが必要とするすべての JSON ペイロード |
| アウトプット | 任意の JSON 応答または SSE ストリーム |
| 会話履歴 | 管理されていません。 必要に応じて、コードによって状態が処理されます。 |
| ストリーミング | オプション(SSE を使用) |
要求と応答のペイロードを完全に制御する必要がある場合は、呼び出しプロトコルを使用します。
SDK アダプター パッケージ
アダプター パッケージはプロトコル固有であり、フレームワークに依存しません。 これらは、Microsoft Agent Framework、LangGraph、カスタム コードなど、任意のエージェント フレームワークで動作します。
| プロトコル | Python パッケージ | .NET パッケージ |
|---|---|---|
| Responses | azure-ai-agentserver-responses |
Azure.AI.AgentServer.Responses |
| 呼び出し | azure-ai-agentserver-invocations |
Azure.AI.AgentServer.Invocations |
アダプターは、コントラクトの次の部分を自動的に処理します。
- ポート 8088 での HTTP サーバーのセットアップ。
- 正常性プローブ エンドポイント (
GET /readiness)。 - プロトコル固有の要求の解析と応答の書式設定。
- 会話履歴ハイドレーション (応答プロトコル)。
- SSE ストリーミング インフラストラクチャ。
- OpenTelemetry インストルメンテーション。
-
SIGTERMでのグレースフル シャットダウン。 - プラットフォーム環境変数の使用。
解析された要求を受け取り、応答を返すハンドラー関数を実装します。
実行時間が長く回復力のある実行 (プレビュー)
プロトコル アダプターは、回復性のあるタスクとストリーミング プリミティブを AgentServer Core の依存関係で構成します。 これらのプリミティブは、処理がプロセスの中断後も存続する必要がある場合、またはクライアントが再生された出力に再接続する必要がある場合に使用します。
応答アダプターは、格納されているバックグラウンド応答の回復性のある実行を管理できます。 サーバーは回復性のあるバックグラウンド処理を選択し、ハンドラーは永続的なチェックポイントを安全に再実行または再開します。 フォアグラウンド応答は、プロセスの停止後に再呼び出されません。
呼び出しアダプターは、状態またはポーリング コントラクトを規定しません。 永続的な実行のための回復性のあるタスクを登録し、クライアントに進行状況を公開する応答、ポーリング、またはストリーム エンドポイントを定義します。
実行モデル、チェックポイント戦略、およびクライアントの再生動作については、 実行時間の長いホステッド エージェントの回復性に関するページを参照してください。
ハンドラーの例
両方のプロトコルと両方の言語の完全な Bring Your Own サンプルは、 foundry-samples リポジトリにあります。
応答プロトコルの例
この最小ハンドラーは、ユーザー入力を Foundry モデル カタログから Responses API を介してモデルに転送します。 SDK アダプターは、context.get_history() (Python) またはcontext.GetHistoryAsync() (C#) を介して会話履歴を自動的にハイドレートするため、エージェントは複数のターンにわたってコンテキストを維持します。
bring-your-own/responses/hello-world/main.py から:
import asyncio
import os
from azure.ai.agentserver.responses import (
CreateResponse,
ResponseContext,
ResponsesAgentServerHost,
ResponsesServerOptions,
TextResponse,
)
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
# FOUNDRY_PROJECT_ENDPOINT is auto-injected in hosted Foundry containers and
# set by 'azd ai agent run' for local development.
_endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
_model = os.environ["FOUNDRY_MODEL_NAME"]
_project_client = AIProjectClient(
endpoint=_endpoint, credential=DefaultAzureCredential()
)
_responses_client = _project_client.get_openai_client().responses
app = ResponsesAgentServerHost(
options=ResponsesServerOptions(default_fetch_history_count=20),
)
@app.response_handler
async def handler(
request: CreateResponse,
context: ResponseContext,
_cancellation_signal: asyncio.Event,
):
user_input = await context.get_input_text() or "Hello!"
history = await context.get_history()
# Build the model input from prior conversation turns + the current message.
input_items = []
for item in history:
# Map history items to {"role": ..., "content": ...} dicts; see the
# full sample for the unpacking helper.
...
input_items.append({"role": "user", "content": user_input})
response = await asyncio.get_running_loop().run_in_executor(
None,
lambda: _responses_client.create(
model=_model,
instructions="You are a helpful AI assistant.",
input=input_items,
store=False, # platform manages history; don't store at model level
),
)
return TextResponse(context, request, text=response.output_text)
app.run()
リファレンス: ResponsesAgentServerHost、 AIProjectClient、 DefaultAzureCredential
呼び出しプロトコルの例
呼び出しプロトコルを使用すると、ハンドラーは呼び出し元が投稿した JSON を受け取り、コードが選択した JSON を返します。 組み込みの会話履歴はありません。
bring-your-own/invocations/hello-worldからのパターン:
from starlette.requests import Request
from starlette.responses import JSONResponse, Response
from azure.ai.agentserver.invocations import InvocationAgentServerHost
app = InvocationAgentServerHost()
@app.invoke_handler
async def handle_invoke(request: Request) -> Response:
data = await request.json()
message = data.get("message", "Hello!")
return JSONResponse({"echo": message})
if __name__ == "__main__":
app.run()
完全なサンプルには、会話履歴ハイドレーション、エラー処理、テレメトリ、ツールボックス統合、Dockerfile と azure.yaml セットアップも含まれます。
ヘルスプローブ
プラットフォームは GET /readiness を送信して、コンテナーがトラフィックを処理する準備ができているかどうかを判断します。 コンテナーの準備ができたら 200 OK 返すか、プラットフォームがインスタンスを再起動する必要があることを通知する 200 以外の状態を返します。 SDK アダプターは、このエンドポイントを自動的に登録します。
ネットワークとトランスポート
| 財産 | 価値 |
|---|---|
| プロトコル | HTTP/1.1 |
| 既定のポート | 8088 ( PORT 環境変数でオーバーライド) |
| バインド アドレス |
0.0.0.0 (すべてのインターフェイス) |
| TLS | プラットフォームによって終了されます。 コンテナーはプレーン HTTP を提供します。 |
グレースフル シャットダウン
プラットフォームが SIGTERMを送信すると、コンテナーは新しい要求の受け入れを停止し、実行中の要求を完了し、保留中の書き込みを $HOME (セッション ファイルシステム) にフラッシュして、正常に終了します。 SDK アダプターは、このシーケンスを自動的に処理します。
プラットフォーム環境変数
プラットフォームは、起動時に環境変数をコンテナーに挿入します。 コードでは、次の主要な変数を読み取ることができます。
| Variable | Purpose |
|---|---|
FOUNDRY_PROJECT_ENDPOINT |
API 呼び出し用の Foundry プロジェクト エンドポイント |
FOUNDRY_AGENT_ID |
エージェントの安定した識別子 (GUID)。 エージェントごとのルーティング、テレメトリ、またはストレージのパーティション分割に使用します。 |
FOUNDRY_AGENT_NAME |
エージェントの名前 |
FOUNDRY_AGENT_VERSION |
エージェントのバージョン |
FOUNDRY_AGENT_SESSION_ID |
現在のセッション ID |
プラットフォーム要求ヘッダー (コンテナー プロトコル 2.0.0)
これらのヘッダーは、コンテナー プロトコル バージョン 2.0.0 でホストされているエージェントにのみ適用されます。 プロトコル 2.0.0 では、プラットフォームは、応答プロトコルと呼び出しプロトコルの両方について、プロトコル エンドポイントに対するすべての要求に対してそれらを挿入します。 正常性プローブなどのインフラストラクチャ エンドポイントには送信されません。 値を不透明として扱い、読み取りますが、オーバーライドしないでください。
| Header | Purpose |
|---|---|
x-agent-user-id |
現在の呼び出し元のグローバルユーザーごとの識別子。 コンテナーが格納するユーザーごとのデータのプライマリ パーティション キーとして使用します。これはコンテナー独自の用途であり、送信方向には転送されません。 同じユーザーがエージェント間で同じ値を生成します。 |
x-agent-foundry-call-id |
要求ごとの識別子。 Foundry サービス (Storage、Toolbox、およびその他のエージェント) への発信呼び出しでは変更されずに転送されます。プラットフォームは、そこから呼び出し元の ID を解決します。 公式の SDK アダプターは、クライアントを介してこれらのサービスを呼び出すと自動的に転送されます。 |
どちらのヘッダーも信頼できます。プラットフォームは検証済み ID からそれらを生成します。ローカルで実行してもどちらも保証されないため、欠損値を適切に処理します。
AgentServer SDK では、これらをPlatformHeadersの定数として公開し、.NETのFoundryAgentRequestContext.CurrentまたはPythonのget_request_context()を通じて読み取ります。
x-agent-session-id、x-platform-server、x-platform-error-sourceなど、ランタイムによって追加される応答ヘッダーを含む、完全なプラットフォーム ヘッダーの一覧については、Azure AI Agent Server Core ライブラリリファレンスを参照してください。
プロトコル 2.0.0 が ID 伝達を変更する方法については、 ホストされているエージェントの移行に関するページを参照してください。
例: セッションごとに格納されたデータをパーティション分割する
コンテナーがユーザー所有のデータを保持する場合は、ある呼び出し元が別の呼び出し元のデータを読み取れないように、セッション (および共有セッションの場合はユーザー) によってキーを設定します。
メモを取るエージェント のサンプルでは、セッション ファイルのパスを $HOME の下に派生させてこれを行います。このパスでは、セッション ファイル API を介してファイルにも到達できます。
# note_store.py - one JSONL file per session, stored under $HOME.
def _get_file_path(session_id: str) -> str:
safe_id = "".join(c if c.isalnum() or c in "-_" else "_" for c in session_id)
base_dir = os.environ.get("HOME", os.getcwd())
return os.path.join(base_dir, f"notes_{safe_id}.jsonl")
複数のユーザーがセッションを共有できる場合は、キーに x-agent-user-id を追加します。
1 つのホストされたエージェント セッションで複数のユーザーを多重化するを参照してください。
カスタム要求ヘッダーをコンテナーに転送する
前のセクションでは、 プラットフォーム が挿入するヘッダーについて説明しました。 個別に、ゲートウェイは 、呼び出し元が指定した 要求ヘッダーの固定セットのみをコンテナーに転送します。 設定の外部にある呼び出し元ヘッダーは、要求がコンテナーに到達する前にゲートウェイで削除されます。既定では、資格情報と内部ヘッダーはコンテナーから保持されます。
独自のコンテキスト データをコンテナーに渡すには、パススルー クライアント ヘッダー プレフィックス ( x-client-) を使用します。 プラットフォームは、 x-client- で始まるすべてのヘッダーを変更せずに転送するため、要求本文を変更せずにテナント ID や機能フラグなどの値を送信し、他の要求ヘッダーと同様にハンドラーで読み取ることができます。 AgentServer SDK では、このプレフィックスをPlatformHeaders.ClientHeaderPrefixとして定義します。プラットフォーム ヘッダーの完全な一覧については、Azure AI Agent Server Core ライブラリ リファレンスを参照してください。
ゲートウェイは、次の呼び出し元ヘッダーを応答および呼び出しプロトコル エンドポイントに転送します。
| ヘッダーまたはプレフィックス | Purpose |
|---|---|
x-client-* |
x-client-でプレフィックスを付けます。 このプレフィックスを使用して、テナント、機能フラグ、関連付けトークンなどの独自のコンテキスト値をコンテナーに渡します。 |
accept、 accept-encoding、 accept-language、 content-type、 content-length、 content-encoding |
要求を解析するために必要な標準のコンテンツ ネゴシエーションヘッダーと本文ヘッダー。 |
traceparent、 tracestate、 baggage、 x-ms-client-request-id、 x-request-id、 request-id、 correlation-context、 request-context、 ms-cv |
分散トレース ID と関連付け ID。そのため、コンテナーのログは元の要求にリンクされます。 |
user-agent |
診断のために、呼び出し元の SDK またはクライアントを識別します。 |
ゲートウェイは、 Authorization、 Host、 Cookie、 x-forwarded-*などの資格情報ヘッダーを転送しません。 許可リストと一致しないヘッダーはすべて削除されるため、コンテナーに到達する x-client-* プレフィックスの外側にあるカスタム ヘッダーに依存しないでください。