はじめに
Azure AI Foundry の Voice Live API は、音声認識(STT)+ 生成AI(LLM)+ 音声合成(TTS)を統合したリアルタイム音声対話APIです。2025年11月にGA(正式版 2025-10-01)となり、2026年1月にプレビュー版 2026-01-01-preview がリリースされました。
本記事では、プレビュー版で追加された 3つの新機能 を、C#のサンプルアプリケーションを使って解説します。
Voice Live APIは過去にも以下の記事で解説しています。本記事はその続編的な位置づけです。
Azure AI Foundry Voice Live APIをAIAgentで使う実装解説
新機能の概要
| 機能 | 概要 | ユースケース |
|---|---|---|
| Foundry Agent Tool | AIモデルがFoundry Agent Serviceのエージェントをツールとして呼び出す | 基本対話はリアルタイム処理、複雑タスクはFoundryエージェントに委任 |
| Filler Response | 遅延時やツール呼び出し待機中に自動で応答フレーズを生成 | 「少々お待ちください」的な応答で無音を回避 |
| Echo Cancellation | サーバーサイドでスピーカー音声のエコーを除去 | スピーカー再生音がマイクに入っても対話が途切れない |
正規版との大きな違い:「1対1」から「チャットスーパーバイザー」へ
正規版では、Voice Live APIは 1つのモデル または 1つのエージェント との対話が基本でした。
プレビュー版では、リアルタイム対話を担当するAIモデルが Foundry Agentを「ツール」として呼び出す「チャットスーパーバイザーパターン」が可能になりました。
これにより、日常的な対話はリアルタイムモデルが即座に応答し、専門的な処理(RAG検索・外部API連携等)はFoundry Agentに委任するという柔軟な構成が実現できます。
前提条件・開発環境
必要なもの
- .NET 8.0 SDK
- Azure AI Foundry プロジェクト(エンドポイント・APIキーを取得済み)
- Foundry Agent(Foundry Agent Toolを使う場合のみ)
- FFmpeg(Avatar モードを使用する場合のみ)
- マイク&スピーカー
サンプルリポジトリ
git clone https://github.com/TakahiroMiyaura/VoiceLiveAPISamples.git
cd VoiceLiveAPISamples
git checkout 2026-01-01-preview
本記事では VoiceLiveConsoleApp(カスタムWebSocket実装版)を使用します。
User Secrets の設定
cd src/VoiceLiveConsoleApp
# 共通設定
dotnet user-secrets set "VoiceLiveAPI:AzureEndpoint" "<エンドポイントURL>"
dotnet user-secrets set "AzureAIFoundry:ApiKey" "<APIキー>"
# Foundry Agent Tool を使う場合
dotnet user-secrets set "AzureAIFoundry:AgentId" "<エージェントID>"
dotnet user-secrets set "AzureAIFoundry:AgentProjectName" "<プロジェクト名>"
新機能1: Foundry Agent Tool
概念
従来のFunction Calling(type: "function")と同じ仕組みで、Foundry Agent Serviceのエージェントを ツール として定義します。リアルタイムのAIモデルがユーザーの意図を判断し、必要に応じてFoundry Agentを呼び出します。
| 従来 | プレビュー版 |
|---|---|
| AIモデルモード:1つのモデルと対話 | 同左 + Foundry Agentをツールとして呼び出し可能 |
| AIエージェントモード:1つのエージェントと対話 | 同左 |
| Function Calling: 関数をツールとして定義 | 同左 + foundry_agent タイプが追加 |
FoundryAgentTool の定義
サンプルでは FoundryAgentTool クラスを使ってツールを定義します。
var foundryTool = new FoundryAgentTool
{
AgentName = foundryAgentName, // Foundry Agent の名前
ProjectName = agentProjectName, // Foundry プロジェクト名
Description = foundryAgentDescription // ツールの説明(任意)
};
// バージョン指定(任意)
if (!string.IsNullOrEmpty(foundryAgentVersion))
foundryTool.AgentVersion = foundryAgentVersion;
// セッションオプションにツールとして設定
options.Tools = new RealtimeTool[] { foundryTool };
options.ToolChoice = "auto"; // AIモデルが自動判断
JSONとしてサーバーに送信される構造は以下の通りです:
{
"type": "foundry_agent",
"agent_name": "my-rag-agent",
"project_name": "my-foundry-project",
"description": "社内ナレッジベースを検索するエージェント"
}
FoundryAgentTool の主なプロパティ
| プロパティ | 型 | 必須 | 説明 |
|---|---|---|---|
agent_name |
string | 必須 | 呼び出す Foundry エージェントの名前 |
project_name |
string | 必須 | エージェントを含む Foundry プロジェクトの名前 |
agent_version |
string | 任意 | エージェントのバージョン |
description |
string | 任意 | ツールの説明(指定時はFoundryポータルの説明を上書き) |
agent_context_type |
string | 任意 |
no_context(現在の入力のみ)/ agent_context(スレッド保持、既定) |
return_agent_response_directly |
bool | 任意 |
true(既定): エージェント応答をそのまま返す / false: チャットモデルが言い換え |
APIバージョンの切り替え
Foundry Agent Tool を使用する場合、APIバージョンをプレビュー版に切り替える必要があります。
// Foundry Agent Tool 使用時はプレビュー版APIを使用
if (!string.IsNullOrEmpty(foundryAgentName))
{
clientOptions = new VoiceLiveClientOptions
{
ApiVersion = VoiceLiveClientOptions.PreviewApiVersion // "2026-01-01-preview"
};
}
サーバーイベントのハンドリング
Foundry Agent の呼び出しは非同期で行われ、以下の5つのサーバーイベントで進捗を追跡できます。
// 引数のストリーミング(delta)
serverManager.OnFoundryAgentCallArgumentsDeltaReceived += delta =>
{
Console.Write(delta.Delta); // 引数が部分的に届く
};
// 引数のストリーミング完了
serverManager.OnFoundryAgentCallArgumentsDoneReceived += done =>
{
Console.WriteLine($"引数確定: {done.Arguments}");
};
// エージェント処理開始
serverManager.OnFoundryAgentCallInProgressReceived += inProgress =>
{
Console.WriteLine($"Foundry Agent 処理中... (ResponseId: {inProgress.AgentResponseId})");
};
// エージェント処理完了
serverManager.OnFoundryAgentCallCompletedReceived += completed =>
{
Console.WriteLine($"Foundry Agent 完了 (ResponseId: {completed.AgentResponseId})");
};
// エージェント呼び出し失敗
serverManager.OnFoundryAgentCallFailedReceived += failed =>
{
Console.WriteLine($"Foundry Agent 失敗: ItemId={failed.ItemId}");
};
イベントフロー
| 順序 | イベント | 説明 |
|---|---|---|
| 1 | response.foundry_agent_call_arguments.delta |
引数のストリーミング(複数回発生) |
| 2 | response.foundry_agent_call_arguments.done |
引数確定 |
| 3 | response.foundry_agent_call.in_progress |
エージェント処理開始 |
| 4a | response.foundry_agent_call.completed |
エージェント処理完了(成功時) |
| 4b | response.foundry_agent_call.failed |
エージェント処理失敗(失敗時) |
新機能2: Filler Response(フィラー応答)
課題:待機中の沈黙
Foundry Agent Tool のようなツール呼び出しが発生すると、エージェントの処理完了まで ユーザーは無音の待機 を強いられます。これはUX上の大きな課題です。
Filler Responseは、この無音区間を 自動的なつなぎ応答 で埋める機能です。
2つのモード
静的フィラー(Static Filler)
事前に用意したテキストリストからランダムに選択して読み上げます。
options.FillerResponse = new BasicFillerResponseConfig
{
Texts = new[]
{
"少々お待ちください。",
"確認しますね。",
"ちょっと調べますね。",
"はい、少しお待ちくださいね。"
},
Triggers = new[] { "latency", "tool" },
LatencyThresholdMs = 2000 // 2秒以上の遅延でトリガー
};
| プロパティ | 型 | 説明 | 既定値 |
|---|---|---|---|
type |
string | "static_filler" |
- |
texts |
string[] | ランダム選択するテキスト一覧 | - |
triggers |
string[] | トリガー条件("latency" / "tool") |
["latency"] |
latency_threshold_ms |
int | トリガーまでの閾値(ミリ秒) | 2000 |
LLMフィラー(LLM Filler)
LLMがコンテキストに応じた応答を 動的に生成 します。より自然な応答が可能です。
options.FillerResponse = new LlmFillerResponseConfig
{
Model = "gpt-4.1-mini",
Instructions = "ユーザーを待たせている間の短いつなぎ言葉を日本語で生成してください。",
MaxCompletionTokens = 50,
Triggers = new[] { "latency", "tool" },
LatencyThresholdMs = 2000
};
| プロパティ | 型 | 説明 | 既定値 |
|---|---|---|---|
type |
string | "llm_filler" |
- |
model |
string | フィラー生成に使用するモデル | gpt-4.1-mini |
instructions |
string | フィラー生成用のカスタム指示 | - |
max_completion_tokens |
int | 最大トークン数 | 50 |
triggers |
string[] | トリガー条件 | ["latency"] |
latency_threshold_ms |
int | トリガーまでの閾値(ミリ秒) | 2000 |
トリガー条件
| トリガー | 説明 |
|---|---|
latency |
応答生成の待機時間が閾値(latency_threshold_ms)を超えた場合 |
tool |
ツール呼び出し(Function Calling / Foundry Agent Tool)の実行中 |
トリガーはOR条件で評価されます。どちらかの条件に合致すればフィラー応答が発生します。
新機能3: Echo Cancellation & Noise Reduction
Echo Cancellation(エコーキャンセル)
Voice Live APIがスピーカーから再生されている AIの応答音声 をマイク入力から除去します。これにより、クライアント側でのエコーキャンセル処理が不要になります。
従来の課題: スピーカーから再生されるAIの音声をマイクが拾い、AIが「自分の声」に反応して対話が中断される。
options.InputAudioEchoCancellation = new AudioInputEchoCancellationSettings();
JSONでは以下のように送信されます:
{
"input_audio_echo_cancellation": {
"type": "server_echo_cancellation"
}
}
サーバーサイドエコーキャンセルは、クライアントが受信した音声を 即座に再生する ことを前提としています。再生が2秒以上遅延すると、エコーキャンセルの品質が低下します。
Noise Reduction(ノイズ抑制)
環境ノイズを抑制し、音声入力の品質を向上させます。VAD(Voice Activity Detection)やターン検出の精度向上にも寄与します。
options.InputAudioNoiseReduction = new AudioInputAudioNoiseReductionSettings
{
Type = "azure_deep_noise_suppression"
};
セッション設定のまとめ
Echo CancellationとNoise Reductionは組み合わせて使用できます。
{
"input_audio_sampling_rate": 24000,
"input_audio_noise_reduction": {
"type": "azure_deep_noise_suppression"
},
"input_audio_echo_cancellation": {
"type": "server_echo_cancellation"
}
}
サンプルアプリの実行
接続モードの選択
サンプルアプリでは起動時に接続モードを選択します。Foundry Agent Tool を使う場合は AIModelWithFoundryAgent を選択します。
public enum ConnectionMode
{
AIModel, // AIモデル直接接続
AIModelWithFoundryAgent, // AIモデル + Foundry Agent Tool(プレビュー)
AIAgent, // Foundry Agent 直接接続
Avatar // Avatar モード(WebRTC映像付き)
}
実行手順
- User Secrets を設定(前述)
- プロジェクトをビルド・実行
cd src/VoiceLiveConsoleApp
dotnet run
- 接続モードを選択
- マイクに話しかける
Foundry Agent Tool の動作確認
AIModelWithFoundryAgent モードを選択すると、以下のような対話が可能です:
- 基本的な質問(例:「こんにちは」)→ リアルタイムモデルが即座に応答
-
専門的な質問(例:「社内の勤怠規定を教えて」)→ AIモデルがFoundry Agentをツール呼び出し
- フィラー応答が流れる(「確認しますね。」等)
- Foundry Agent がRAG検索等を実行
- 結果をAIモデルが音声で回答
まとめ
Voice Live API 2026-01-01-preview で追加された機能によって、音声エージェントの表現力と実用性が大きく向上する印象です。
特に Foundry Agent Tool は、Voice Live API が単なる「音声I/O」から エージェントオーケストレーション基盤 といってもいい形に進化しそうですね。リアルタイム対話の即応性を維持しつつ、Foundry Agent Serviceの高度な機能(RAG、外部API連携等)を組み合わせることで、実用的な音声エージェントの構築が可能になります。
サンプルリポジトリ