【ITニュース解説】One Event Stream, Two UI Protocols: Wiring Solon AI to Any Frontend
2026年10月06日に「Dev.to」が公開したITニュース「One Event Stream, Two UI Protocols: Wiring Solon AI to Any Frontend」について初心者にもわかりやすく解説しています。
ITニュース概要
Solon AIは、AIエージェントの出力(テキスト、ツール利用状況など)をWeb画面に正しく表示する「翻訳役」モジュール `solon-ai-ui` を提供。AIとUI間の複雑なデータ連携を簡単に行い、UIの不具合や無駄なコスト発生を防ぐ。Vercel AI SDKなど主要なUIフレームワークに対応し、安定した動作を実現する。
ITニュース解説
システム開発において、人工知能(AI)を活用した機能、特にユーザーとの対話を行うチャットボットのような機能をフロントエンド(ユーザーインターフェース、UI)に組み込む際、AIエージェントとUIの間でどのようにデータをやり取りするかが重要な課題となる。AIエージェントが生成する情報は、通常、テキストの断片や推論の過程、ツール呼び出しの結果など、多様な要素がバラバラに、かつ継続的に(ストリームとして)送られてくる。一方、UIはこれらの断片的な情報を受け取り、ユーザーにとって分かりやすい一つのメッセージや視覚的な要素として再構築する必要がある。
このAIエージェントとUIの間で、データの形式を変換し、やり取りを円滑にするための仕組みは「翻訳レイヤー」と呼ばれる。この翻訳レイヤーを自前で実装しようとすると、非常に複雑で手間がかかり、しかもバグが発生しやすいという問題が指摘されている。例えば、テキストの更新、AIの思考プロセス、外部ツールを呼び出す際の引数、そのツールの実行結果、参考情報、さらにはエラーや処理の中止といった、実に多くの種類の情報が同時に、かつ非同期で流れてくる。これらを単一の通信経路(Server-Sent Events: SSEなど)で送受信し、それぞれがどの部分に対応する情報であるかをUIが正確に識別し、組み合わせるためには、安定したID管理が不可欠となる。もしこのID管理を間違えれば、同時に実行されている複数のツール呼び出しの結果が混ざってしまったり、AIの処理中にエラーが発生してもUIが永遠に次の情報を待ち続けて固まってしまったりする事態も起こりうる。また、ユーザーが途中で処理をキャンセルしたにもかかわらず、バックエンドのAIが処理を続行し、無駄なコストが発生するといった問題も生じる可能性がある。
このような複雑で困難な翻訳レイヤーの実装を専門に行うのが、Solon AIが提供するsolon-ai-uiというモジュールである。このモジュールは、AIエージェントの内部的なイベントストリームを、様々なUIプロトコルが理解できる形式に変換するためのアダプターを提供する。
現在、solon-ai-uiには二つの主要なアダプターが用意されている。一つは「solon-ai-ui-aisdk」で、これはVercel AI SDKが採用している「UI Message Stream Protocol v1」に対応している。このプロトコルは、@ai-sdk/reactや@ai-sdk/vueといった人気の高いUIライブラリのuseChatフックと連携するのに最適だ。もう一つは「solon-ai-ui-agui」で、こちらはAG-UIという別のUIフレームワークが求めるプロトコルに対応している。どちらのアダプターも、Solon AIのコアから出力されるFlux<ChatEvent>というイベントストリームを、それぞれのフロントエンドが期待するイベントストリームに変換する役割を果たす。
これらのアダプターの設計において特に注目すべき点は、「アダプターはエージェントが何であるかを知らない」という厳格なルールである。通常、アダプターはAIエージェントの内部構造を直接参照してイベントを変換すると考えがちだが、これではエージェントの仕様変更がアダプターに大きな影響を与え、保守が困難になる。Solon AIのアダプターは、solon-ai-coreという中核モジュールのみに依存し、エージェント固有のイベントはObject型として受け取り、リフレクション(プログラムの実行中にその構造を検査・変更する機能)を使って動的に解釈する。これにより、アダプターはAIエージェントの実装詳細から完全に独立し、非常に薄く、変更に強い構造を保っている。認識できないイベントもただ捨てるのではなく、カスタムデータとして扱われ、情報の欠落を防ぐ設計になっている。
Vercel AI SDKアダプターは、チャットモデルが生成するストリームを、約20種類の「パーツモデル」と呼ばれる小さなJSON形式のフレーム群に変換する。これには、処理開始、推論の開始と内容、ツール呼び出しの入力と出力、テキストの開始と内容、そして処理終了といった一連のイベントが、特定の順序で含まれる。例えば、AIがツールを呼び出して複数のステップで応答を生成する場合でも、start-stepとfinish-stepのペアによって、useChatは正しくメッセージを再構築できる。
一方、AG-UIアダプターはRUN_STARTED、TEXT_MESSAGE_CONTENT、TOOL_CALL_ARGSといった、AG-UI独自のイベント語彙に対応する。このアダプターでは、Solon AIコアがTHINKING_*と呼ぶ推論イベントを、AG-UIの新しい語彙であるREASONING_*に自動的に変換するといった細かな対応も行われている。また、ユーザーが処理を中断した場合、それをエラーではなく「中断」という一つの正常な結果として報告するように設計されており、UIは適切にユーザーの操作を反映できる。AG-UIが標準で扱えないようなイベント(サーバーサイドのツール情報、メディア、利用状況など)は、CUSTOMイベントとして保持され、情報が失われることなくクライアントに伝達される。さらに、RFC 6902 JSON Patch形式の操作を伝えるStateDeltaEventを介した、UIの状態同期もサポートしている。
このような翻訳レイヤーがプロダクション環境で安定して機能するためには、プロトコル変換以外にも、いくつかの重要な詳細が考慮されている。
第一に、データの断片(デルタ)間で安定したID管理が必須である。ストリームで送られてくる情報が細かく分断されていても、UIがそれらを元のメッセージに正しく結合できるように、各ブロックには開始、途中、終了のすべてのフレームで再利用される一意のIDが割り当てられる。これにより、複数のツール呼び出しや推論プロセスが同時に実行されても、IDが混同されることなく、それぞれが独立した情報として扱われる。
第二に、キャンセル処理が上流に適切に伝播すること。ユーザーがブラウザでAIの応答を待っている途中で接続を切断したり、キャンセルボタンを押したりした場合、バックエンドのAIモデルに対する処理も即座に停止する必要がある。solon-ai-uiのアダプターは、UI側からのキャンセルイベントをAIエージェントのストリーム購読解除に結びつけ、無駄なリソース消費や課金を防ぐ。
第三に、失敗を成功として見せかけないこと。もしデータストリームの途中でエラーが発生した場合、アダプターはまず、まだ閉じられていないテキストや推論のブロックを強制的に終了させる。これは、UIが永遠に終了を待ち続けるのを防ぐためだ。その後、finishReasonをerrorに設定したエラー情報がUIに送信される。これにより、UIはエラーが発生したことをユーザーに明確に伝え、適切な処理を行うことができる。
第四に、孤立したツール出力が発生しないこと。一部のAIプロバイダは、ツールの入力に関する情報を送らずに、いきなりツールの結果(出力)だけを送ってくる場合がある。しかし、厳密なUIクライアントは、入力情報なしで出力だけが来てもそれを破棄してしまう可能性がある。この問題を防ぐため、アダプターは、ツール出力が来た際に、もし対応する入力フレームがまだ送信されていなければ、自動的に不足しているtool-input-startやtool-input-availableのフレームを補完してから、ツールの結果を送信する。
第五に、ユーザーに見せるべきではない内部的なコンテンツが、答えのように見えてしまわないこと。複数のAIエージェントが連携して動作するような複雑なシナリオでは、監督役のエージェントが内部的なルーティングに関する情報をストリームに流すことがある。これらの内部的な議論は、ユーザーに表示されるべき「答え」ではない。solon-ai-uiのアダプターは、このような内部的なイベントを、アシスタントのテキストや推論のチャネルではなく、customやdata-*といった専用のバケットに強制的に振り分けることで、ユーザーに不要な情報が漏洩するのを防ぐ。
solon-ai-uiモジュールは、このようにAIエージェントとUI間の複雑な連携における多岐にわたる課題を解決するために設計されている。これにより、システムエンジニアは、AI機能の核となるロジックの実装に集中でき、UIとの連携部分で発生しがちなバグやメンテナンスの負担から解放される。結果として、より堅牢で、ユーザー体験に優れたAIアプリケーションを効率的に開発できる基盤が提供されることになる。