今回のMicrosoft developer platform documentation update(.NET: Support reasoning events in AGUI)で最も重要なのは、.NET版のMicrosoft Agent FrameworkとAG-UI連携で、LLMの推論情報をREASONING_*イベントとして扱えるようになったことです。AG-UIでAIエージェントの実行状況や推論サマリーをフロントエンドに表示している開発者、またはTextReasoningContentを含むマルチターン会話を扱う.NETアプリは、イベント名・メッセージ変換・暗号化された推論データの扱いを確認する必要があります。PR上では2026年5月5日にdotnet format対応などの更新があり、その後2026年5月7日にmainへマージされています。(GitHub)
2026年5月5日更新の要点:AG-UIのreasoningイベントを.NETで扱えるようにする変更
この更新は、Microsoft developer platform上でAIエージェントUIを構築している開発者向けの変更です。特に、Microsoft Agent Frameworkの.NET実装とAG-UIを組み合わせ、Server-Sent Events(SSE)でエージェントの応答をストリーミングしている構成に関係します。
Microsoft Learnでは、Agent FrameworkのAG-UI連携について、WebベースのAIエージェントアプリケーションでリアルタイムストリーミング、状態管理、インタラクティブUIを実現するための統合として説明されています。また、.NETではMapAGUI、AIAgent、IChatClient、プロトコルアダプターが主要な構成要素として示されています。(Microsoft Learn)
今回のPRでは、AG-UI仕様に基づくreasoning関連イベントが.NET側に追加されました。PRの説明では、従来のthinkingという表現は非推奨で、現在の慣例はreasoningであることも明記されています。(GitHub)
| 確認項目 | 内容 |
|---|---|
| 対象 | Microsoft Agent Frameworkの.NET AG-UI連携 |
| 変更の中心 | TextReasoningContentとAG-UIのREASONING_*イベントの相互変換 |
| 主な影響 | SSEストリーミング、マルチターン会話、フロントエンドのイベント処理、JSONシリアライズ |
| 対応優先度が高いケース | AG-UIで推論サマリーを表示する、role: "reasoning"を会話履歴に含める、暗号化された推論値を保持する |
| 注意点 | PRのマージとNuGetパッケージへの反映タイミングは別。利用中バージョンで実装済みか確認が必要 |
何が変わったのか
7種類のreasoningイベントが追加された
今回追加された中心的な変更は、AG-UIのreasoningライフサイクルを.NET側で表現できるようになったことです。PRでは、以下の7つのイベントモデルが新規追加されています。(GitHub)
| 追加イベント | 役割 |
|---|---|
ReasoningStartEvent | 推論フェーズの開始を示す |
ReasoningMessageStartEvent | 推論メッセージのストリーミング開始を示す |
ReasoningMessageContentEvent | 推論メッセージの差分テキストを送る |
ReasoningMessageEndEvent | 推論メッセージの終了を示す |
ReasoningEndEvent | 推論フェーズ全体の終了を示す |
ReasoningMessageChunkEvent | ライフサイクル管理を簡略化するチャンク形式のイベント |
ReasoningEncryptedValueEvent | 暗号化された推論値をメッセージやツール呼び出しに関連付ける |
AG-UIのドキュメントでも、reasoningイベントは推論メッセージのライフサイクルを管理するものとして説明されています。ReasoningEncryptedValueは、クライアントに平文の推論内容を保存させず、後続ターンで必要な推論状態を引き継ぐための仕組みとして位置づけられています。(AG-UI)
TextReasoningContentがAG-UIイベントに変換される
.NET側の送信経路では、IChatClientパイプラインから来るTextReasoningContentが、AG-UIの明示的なreasoningライフサイクルに変換されます。PRでは、AsAGUIEventStreamAsyncにより、次のような流れでイベントが出力されると説明されています。(GitHub)
REASONING_START
→ REASONING_MESSAGE_START
→ REASONING_MESSAGE_CONTENT
→ REASONING_MESSAGE_END
→ REASONING_END
これにより、フロントエンド側は通常の回答テキストとは別に、推論サマリーや推論中の状態をUIに出し分けやすくなります。
たとえば、チャットUIで次のような表示をしたい場合に有効です。
考えています...
要件を整理しています...
必要な設定を確認しています...
回答を生成しています...
ただし、推論内容をそのまま見せるべきかは別問題です。業務アプリでは、詳細な思考過程ではなく「処理状況」や「推論サマリー」だけを表示する設計が安全です。
暗号化された推論値も落とさず扱える
PRでは、ProtectedDataがある場合にREASONING_ENCRYPTED_VALUEとして出力されること、さらに可視テキストがなく暗号化データだけを持つcontentも破棄されないことが説明されています。(GitHub)
これは、マルチターン会話で重要です。AIエージェントが前回の推論状態を引き継ぐ必要がある一方で、クライアントには詳細な推論内容を平文で保持させたくないケースがあります。
AG-UIのreasoning仕様でも、encryptedValueはクライアントが不透明な値として受け取り、後続リクエストでエージェントへ返すことで、状態継続とプライバシー要件を両立する考え方が示されています。(AG-UI)
影響を受ける開発者
対応が必要な可能性が高いケース
次のいずれかに当てはまる場合は、今回の変更を確認する価値があります。
| 対象 | 確認すべき理由 |
|---|---|
| .NETでMicrosoft Agent Frameworkを使っている | 今回のPRは.NET側のAG-UI連携が対象 |
| AG-UIでSSEストリーミングを使っている | REASONING_*イベントがイベントストリームに追加される可能性がある |
| フロントエンドでイベントタイプを厳密に分岐している | 未対応のイベントを無視するか、表示に使うかを決める必要がある |
| 会話履歴をPOSTしてマルチターン会話を実装している | role: "reasoning"メッセージの扱いが変わる |
| Native AOTやsource-generated JSONを使っている | 新しいイベント・メッセージ型のシリアライズ対応を確認する必要がある |
THINKING_*イベントに依存している | AG-UI側ではTHINKING_*が非推奨で、REASONING_*への移行が推奨されている |
特に注意したいのは、フロントエンドのイベント処理を固定的に書いている場合です。たとえば、TEXT_MESSAGE_CONTENTとTOOL_CALL_*だけを想定してswitch文を書いている場合、REASONING_MESSAGE_CONTENTを表示しないだけなら大きな問題にならないかもしれません。しかし、未対応イベントで例外を投げる実装だと、ストリーミング全体が止まる可能性があります。
影響が小さいケース
一方で、以下のような構成では影響は限定的です。
| 構成 | 影響 |
|---|---|
| AG-UIを使っていない.NETアプリ | 今回の変更の直接影響は小さい |
| 推論サマリーを出力しないモデル設定 | TextReasoningContentが流れない場合、挙動差は出にくい |
| イベントタイプを柔軟に無視できるフロントエンド | 未対応イベントで壊れにくい |
| Python側のみを使っている | 今回のPR自体は.NET向け。ただし関連IssueにはPythonも含まれるため、今後の更新確認は必要 |
マルチターン会話で重要なrole: "reasoning"対応
今回の変更で実務上ありがたいのは、role: "reasoning"メッセージをPOST payloadとして扱えるようになった点です。
PRでは、新しいAGUIReasoningMessageが追加され、フロントエンドのPOST payloadに含まれるrole: "reasoning"メッセージを処理できるようになったと説明されています。これがなければ、reasoning有効時のマルチターン会話で2回目のリクエストが400 Bad Requestになる可能性があった、という背景も示されています。(GitHub)
典型的には、次のような流れです。
1回目のリクエスト
→ サーバーがreasoningイベントと通常回答を返す
→ クライアントがreasoningメッセージやencryptedValueを会話履歴に保持
2回目のリクエスト
→ クライアントが過去メッセージとしてrole: "reasoning"を含めてPOST
→ サーバー側でAGUIReasoningMessageとして受け取り、TextReasoningContentに変換
この流れが安定すると、フロントエンドは推論状態を保持しつつ、サーバー側のエージェントに必要な文脈を戻せます。
ただし、encryptedValueは「表示する値」ではありません。ログ出力、ブラウザの開発者向け表示、分析基盤への送信などで不用意に露出しないようにしてください。
移行時に確認すべきポイント
THINKING_*からREASONING_*への移行を確認する
AG-UIのドキュメントでは、THINKING_*イベントは非推奨で、今後の実装ではREASONING_*イベントを使うべきとされています。移行例として、THINKING_STARTはREASONING_START、THINKING_TEXT_MESSAGE_CONTENTはREASONING_MESSAGE_CONTENTに置き換える形が示されています。(AG-UI)
フロントエンドに次のような処理がある場合は見直しましょう。
switch (event.type) {
case "THINKING_TEXT_MESSAGE_CONTENT":
showThinking(event.delta);
break;
}
移行後は、少なくともREASONING_MESSAGE_CONTENTを扱えるようにします。
switch (event.type) {
case "REASONING_MESSAGE_CONTENT":
showReasoningSummary(event.delta);
break;
}
既存環境と新環境が混在する期間は、両方を受け付ける実装にしておくと安全です。
switch (event.type) {
case "REASONING_MESSAGE_CONTENT":
case "THINKING_TEXT_MESSAGE_CONTENT":
showReasoningSummary(event.delta);
break;
}
本番環境で段階的にロールアウトする場合、バックエンドのバージョンとフロントエンドのバージョンが一時的にずれることがあります。イベント名の互換対応は、その期間の障害を減らす実務的な対策です。
イベントの開始・終了ペアをテストする
PRでは、受信経路のAsChatResponseUpdatesAsyncにおいて、新しいReasoningMessageBuilderが明示的なライフサイクル形式とREASONING_MESSAGE_CHUNKの短縮形式を扱うと説明されています。また、重複開始や不一致の終了はInvalidOperationExceptionになるとされています。(GitHub)
つまり、次のようなイベント順序は避ける必要があります。
REASONING_MESSAGE_START
REASONING_MESSAGE_START
REASONING_MESSAGE_END
また、別のmessageIdで開始したメッセージを誤ったIDで終了するような実装も危険です。
確認すべきテストケースは次の通りです。
| テストケース | 期待する結果 |
|---|---|
| 通常のreasoning開始から終了まで | UIに推論サマリーが表示され、最後に状態が閉じる |
REASONING_MESSAGE_CHUNK形式 | チャンクが順番に結合される |
encryptedValueのみ | 可視テキストがなくても会話継続用データが保持される |
| 終了イベント欠落 | UIが無限に「考えています」状態にならない |
| 不正なイベント順序 | サーバーまたはテストで検出できる |
messageIdの扱いを固定前提にしない
PRのコメントでは、reasoningイベントのmessageIdはreasoningメッセージの一意識別子であるべきとされ、reasoning contentには新しいGUIDを作る実装が示されています。また、現時点の実装ではreasoningメッセージと通常のテキストメッセージの間に明示的なmessageIdリンクを作っていないことも説明されています。(GitHub)
そのため、フロントエンド側で次のような前提を置くのは避けるべきです。
reasoning-${assistantMessageId}
推論メッセージと通常回答をUI上で関連付けたい場合は、イベントの時系列、run ID、thread ID、独自の相関IDなど、アプリケーション側で管理しやすい設計を検討してください。
設定・実装確認チェックリスト
バックエンド側
| 確認項目 | 実務での見方 |
|---|---|
| 利用中パッケージに変更が含まれているか | PRがマージ済みでも、利用中のNuGetに反映済みとは限らない。リリースノートやパッケージバージョンを確認する |
TextReasoningContentを返すモデル設定か | 推論サマリーを有効化していない場合、イベントが出ない可能性がある |
AsAGUIEventStreamAsyncの出力を確認したか | SSEの実データでREASONING_*イベントが流れるか確認する |
AsChatResponseUpdatesAsyncの受信を確認したか | クライアントやテストからreasoningイベントを戻すケースを確認する |
AGUIReasoningMessageを含むPOSTを確認したか | 2ターン目以降のrole: "reasoning"で400にならないか確認する |
| AOT/JSON source generatorを使っているか | 新しいイベント・メッセージ型がシリアライズ対象に含まれるか確認する |
フロントエンド側
| 確認項目 | 実務での見方 |
|---|---|
REASONING_*をswitch文で処理できるか | 未知イベントで落ちる実装を避ける |
| 推論表示のUIをどう扱うか | 詳細な思考ではなく、要約や状態表示に留める方が安全 |
encryptedValueを保持できるか | 後続リクエストに戻す必要がある場合、破棄しない |
encryptedValueを表示していないか | UI、ログ、分析イベントに誤って出さない |
THINKING_*との互換期間を設けるか | 段階移行中は両方を受け付けると安全 |
| 終了イベント欠落時のUI制御 | タイムアウトや次イベント到着時に「考え中」を解除する |
実務での活用シーン
ユーザーに「処理中の理由」を自然に見せる
AIエージェントは、ツール呼び出しや複数ステップの判断を行うと、ユーザーから見ると「何をしているのか分からない」状態になりがちです。reasoningイベントを使えば、通常の回答とは別に処理状況を表示できます。
たとえば、社内ナレッジ検索エージェントなら次のような表示が考えられます。
関連する社内ドキュメントを検索しています
検索結果を比較しています
回答に使える情報を絞り込んでいます
このような表示は、ユーザーの待ち時間ストレスを下げます。一方で、モデルの内部思考をそのまま表示する必要はありません。業務システムでは、説明可能性を高めるための要約と、秘匿すべき推論の保護を分けて考えることが重要です。
ゼロデータ保持や機密情報を意識した会話継続
AG-UIのreasoning仕様では、暗号化された推論値をクライアントが不透明な値として受け取り、次のターンで返す設計が示されています。これにより、クライアントが復号できる平文の推論情報を持たずに、エージェント側の状態継続を支援できます。(AG-UI)
ただし、これは「何を保存しても安全」という意味ではありません。実装時は以下を確認してください。
| リスク | 対策 |
|---|---|
ブラウザログにencryptedValueが出る | デバッグログの出力対象から除外する |
| 分析ツールに送られる | イベントトラッキング対象から除外する |
| ローカルストレージに長期保存される | 保存期間を短くし、セッション単位で破棄する |
| 暗号化値をUIに表示してしまう | reasoning表示用テキストとencryptedValueを別フィールドとして扱う |
| 権限のないクライアントに渡る | thread/session単位の認可を確認する |
失敗しやすいポイント
「PRがマージされた=すぐ本番で使える」と考える
今回のPRは2026年5月7日にmainへマージされ、24件のチェックを通過したことがPR上で確認できます。(GitHub)
ただし、アプリで使えるかどうかは、利用しているNuGetパッケージやSDKバージョンに依存します。実務では、次の順序で確認してください。
1. 利用中のパッケージバージョンを確認
2. 対象PRが含まれるリリースを確認
3. 開発環境でSSEイベントを確認
4. フロントエンドのイベント処理を更新
5. マルチターン会話をテスト
6. 本番へ段階展開
reasoningイベントを通常メッセージとして混ぜてしまう
reasoningは、最終回答そのものではありません。AG-UIのドキュメントでも、reasoning messageはassistant messageとは分けられ、会話履歴を汚染しないように扱う考え方が示されています。(AG-UI)
UI上でも、通常回答と同じ吹き出しに混ぜるより、折りたたみ可能な「処理の概要」「推論サマリー」として扱う方が読みやすくなります。
回答:
この設定では、AG-UIのSSEイベントを確認してください。
処理の概要:
・入力内容を解析
・対象のAgent Framework設定を確認
・reasoningイベントの有無を確認
このように分けると、ユーザーは最終回答を読みやすく、必要な場合だけ処理過程を確認できます。
encryptedValueを「暗号化されているから安全」と過信する
encryptedValueは暗号化された値ですが、不要に長期保存したり、第三者サービスへ送ったりしてよいわけではありません。セキュリティレビューでは、平文か暗号文かだけでなく、誰がアクセスできるか、どこに保存されるか、いつ削除されるかが確認されます。
実装時は、少なくとも次のルールを決めておきましょう。
・encryptedValueはUIに表示しない
・通常ログに出力しない
・分析イベントに含めない
・保存期間を決める
・threadIdやsessionIdと紐づけて認可する
・エラー時にダンプしない
今すぐ取るべき対応
まずは、自社のアプリが今回の変更の影響を受けるかを切り分けてください。
AG-UIを使っていない場合、急いで対応する必要はありません。AG-UIを使っていても、推論サマリーやTextReasoningContentを使っていない場合は、影響は限定的です。
一方で、.NET版Microsoft Agent FrameworkでAG-UI連携を使い、SSEストリーミングやマルチターン会話を実装しているなら、次の確認を優先しましょう。
・利用中バージョンにPR #4953相当の変更が含まれるか
・SSEでREASONING_*イベントが流れるか
・フロントエンドが未知イベントで落ちないか
・THINKING_*依存が残っていないか
・role: "reasoning"を含む2回目以降のPOSTが成功するか
・encryptedValueを表示、ログ出力、外部送信していないか
今回の更新は、単なるイベント追加ではなく、AIエージェントの推論状態をUI、会話履歴、プライバシー設計の中でどう扱うかに関わる変更です。まず開発環境でイベントストリームとPOST payloadを確認し、フロントエンドのイベント処理とセキュリティ方針を合わせて見直すことが、最も安全な対応です。

コメント