Azure.AI.Agents.Persistent (.NET)
永続的な AI エージェント、スレッド、メッセージ、実行、ツールを作成および管理するための低レベル SDK です。
インストール
dotnet add package Azure.AI.Agents.Persistent --prerelease
dotnet add package Azure.Identity
現在のバージョン: 安定版 v1.1.0、プレビュー版 v1.2.0-beta.8
環境変数
PROJECT_ENDPOINT=https://<resource>.services.ai.azure.com/api/projects/<project>
MODEL_DEPLOYMENT_NAME=gpt-4o-mini
AZURE_BING_CONNECTION_ID=<bing-connection-resource-id>
AZURE_AI_SEARCH_CONNECTION_ID=<search-connection-resource-id>
AZURE_TOKEN_CREDENTIALS=prod
認証
using Azure.AI.Agents.Persistent;
using Azure.Identity;
var projectEndpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT");
var credential = new DefaultAzureCredential(
DefaultAzureCredential.DefaultEnvironmentVariableName
);
PersistentAgentsClient client = new(projectEndpoint, credential);
クライアント階層
PersistentAgentsClient
├── Administration → エージェントの CRUD 操作
├── Threads → スレッド管理
├── Messages → メッセージ操作
├── Runs → 実行の実行とストリーミング
├── Files → ファイルのアップロード/ダウンロード
└── VectorStores → ベクトルストア管理
コアワークフロー
1. エージェントの作成
var modelDeploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME");
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Math Tutor",
instructions: "あなたは個人的な数学のチューターです。数学の質問に答えるためにコードを書いて実行してください。",
tools: [new CodeInterpreterToolDefinition()]
);
2. スレッドとメッセージの作成
PersistentAgentThread thread = await client.Threads.CreateThreadAsync();
await client.Messages.CreateMessageAsync(
thread.Id,
MessageRole.User,
"方程式 `3x + 11 = 14` を解く必要があります。手伝ってくれますか?"
);
3. エージェントの実行 (ポーリング)
ThreadRun run = await client.Runs.CreateRunAsync(
thread.Id,
agent.Id,
additionalInstructions: "ユーザーを Jane Doe として扱ってください。"
);
do
{
await Task.Delay(TimeSpan.FromMilliseconds(500));
run = await client.Runs.GetRunAsync(thread.Id, run.Id);
}
while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress);
await foreach (PersistentThreadMessage message in client.Messages.GetMessagesAsync(
threadId: thread.Id,
order: ListSortOrder.Ascending))
{
Console.Write($"{message.Role}: ");
foreach (MessageContent content in message.ContentItems)
{
if (content is MessageTextContent textContent)
Console.WriteLine(textContent.Text);
}
}
4. ストリーミング応答
AsyncCollectionResult<StreamingUpdate> stream = client.Runs.CreateRunStreamingAsync(
thread.Id,
agent.Id
);
await foreach (StreamingUpdate update in stream)
{
if (update.UpdateKind == StreamingUpdateReason.RunCreated)
{
Console.WriteLine("--- 実行開始! ---");
}
else if (update is MessageContentUpdate contentUpdate)
{
Console.Write(contentUpdate.Text);
}
else if (update.UpdateKind == StreamingUpdateReason.RunCompleted)
{
Console.WriteLine("\n--- 実行完了! ---");
}
}
5. 関数呼び出し
FunctionToolDefinition weatherTool = new(
name: "getCurrentWeather",
description: "指定された場所の現在の天気を取得します。",
parameters: BinaryData.FromObjectAsJson(new
{
Type = "object",
Properties = new
{
Location = new { Type = "string", Description = "市と州 (例: San Francisco, CA)" },
Unit = new { Type = "string", Enum = new[] { "c", "f" } }
},
Required = new[] { "location" }
}, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })
);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Weather Bot",
instructions: "あなたは天気ボットです。",
tools: [weatherTool]
);
do
{
await Task.Delay(500);
run = await client.Runs.GetRunAsync(thread.Id, run.Id);
if (run.Status == RunStatus.RequiresAction
&& run.RequiredAction is SubmitToolOutputsAction submitAction)
{
List<ToolOutput> outputs = [];
foreach (RequiredToolCall toolCall in submitAction.ToolCalls)
{
if (toolCall is RequiredFunctionToolCall funcCall)
{
string result = ExecuteFunction(funcCall.Name, funcCall.Arguments);
outputs.Add(new ToolOutput(toolCall, result));
}
}
run = await client.Runs.SubmitToolOutputsToRunAsync(run, outputs, toolApprovals: null);
}
}
while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress);
6. ベクトルストアを使用したファイル検索
PersistentAgentFileInfo file = await client.Files.UploadFileAsync(
filePath: "document.txt",
purpose: PersistentAgentFilePurpose.Agents
);
PersistentAgentsVectorStore vectorStore = await client.VectorStores.CreateVectorStoreAsync(
fileIds: [file.Id],
name: "my_vector_store"
);
FileSearchToolResource fileSearchResource = new();
fileSearchResource.VectorStoreIds.Add(vectorStore.Id);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Document Assistant",
instructions: "あなたはユーザーがドキュメント内の情報を見つけるのを助けます。",
tools: [new FileSearchToolDefinition()],
toolResources: new ToolResources { FileSearch = fileSearchResource }
);
7. Bing グラウンディング
var bingConnectionId = Environment.GetEnvironmentVariable("AZURE_BING_CONNECTION_ID");
BingGroundingToolDefinition bingTool = new(
new BingGroundingSearchToolParameters(
[new BingGroundingSearchConfiguration(bingConnectionId)]
)
);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Search Agent",
instructions: "Bing を使用して現在のイベントに関する質問に答えてください。",
tools: [bingTool]
);
8. Azure AI Search
AzureAISearchToolResource searchResource = new(
connectionId: searchConnectionId,
indexName: "my_index",
topK: 5,
filter: "category eq 'documentation'",
queryType: AzureAISearchQueryType.Simple
);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Search Agent",
instructions: "ドキュメントインデックスを検索して質問に答えてください。",
tools: [new AzureAISearchToolDefinition()],
toolResources: new ToolResources { AzureAISearch = searchResource }
);
9. クリーンアップ
await client.Threads.DeleteThreadAsync(thread.Id);
await client.Administration.DeleteAgentAsync(agent.Id);
await client.VectorStores.DeleteVectorStoreAsync(vectorStore.Id);
await client.Files.DeleteFileAsync(file.Id);
利用可能なツール
| ツール | クラス | 目的 |
|---|
| コードインタプリタ | CodeInterpreterToolDefinition | Python コードの実行、可視化の生成 |
| ファイル検索 | FileSearchToolDefinition | ベクトルストアを介してアップロードされたファイルを検索 |
| 関数呼び出し | FunctionToolDefinition | カスタム関数の呼び出し |
| Bing グラウンディング | BingGroundingToolDefinition | Bing による Web 検索 |
| Azure AI Search | AzureAISearchToolDefinition | Azure AI Search インデックスの検索 |
| OpenAPI | OpenApiToolDefinition | OpenAPI 仕様による外部 API の呼び出し |
| Azure Functions | AzureFunctionToolDefinition | Azure Functions の呼び出し |
| MCP | MCPToolDefinition | Model Context Protocol ツール |
| SharePoint | SharepointToolDefinition | SharePoint コンテンツへのアクセス |
| Microsoft Fabric | MicrosoftFabricToolDefinition | Fabric データへのアクセス |
ストリーミング更新の種類
| 更新の種類 | 説明 |
|---|
StreamingUpdateReason.RunCreated | 実行が開始されました |
StreamingUpdateReason.RunInProgress | 実行が処理中です |
StreamingUpdateReason.RunCompleted | 実行が完了しました |
StreamingUpdateReason.RunFailed | 実行でエラーが発生しました |
MessageContentUpdate | テキストコンテンツのチャンク |
RunStepUpdate | ステップの状態変更 |
主要な型のリファレンス
| 型 | 目的 |
|---|
PersistentAgentsClient | メインのエントリポイント |
PersistentAgent | モデル、指示、ツールを持つエージェント |
PersistentAgentThread | 会話スレッド |
PersistentThreadMessage | スレッド内のメッセージ |
ThreadRun | スレッドに対するエージェントの実行 |
RunStatus | Queued、InProgress、RequiresAction、Completed、Failed |
ToolResources | ツールリソースの組み合わせ |
ToolOutput | 関数呼び出しの応答 |
ベストプラクティス
- 常にクライアントを破棄する —
using ステートメントまたは明示的な破棄を使用
- 適切な遅延でポーリングする — ステータスチェック間は 500ms を推奨
- リソースをクリーンアップする — 使用後はスレッドとエージェントを削除
- すべての実行ステータスを処理する —
RequiresAction、Failed、Cancelled をチェック
- リアルタイム UX にはストリーミングを使用する — ポーリングよりも優れたユーザー体験
- オブジェクトではなく ID を保存する — エージェント/スレッドは ID で参照
- 非同期メソッドを使用する — すべての操作は非同期で行うべき
エラーハンドリング
using Azure;
try
{
var agent = await client.Administration.CreateAgentAsync(...);
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
Console.WriteLine("リソースが見つかりません");
}
catch (RequestFailedException ex)
{
Console.WriteLine($"エラー: {ex.Status} - {ex.ErrorCode}: {ex.Message}");
}
関連 SDK
| SDK | 目的 | インストール |
|---|
Azure.AI.Agents.Persistent | 低レベルエージェント (この SDK) | dotnet add package Azure.AI.Agents.Persistent |
Azure.AI.Projects | 高レベルプロジェクトクライアント | dotnet add package Azure.AI.Projects |
参考リンク