Claude Media
Managed AgentsをChat SDK/assistant-ui/CopilotKitと組み合わせる実装ガイド

Managed AgentsをChat SDK/assistant-ui/CopilotKitと組み合わせる実装ガイド

Managed Agentsを人気のチャットフレームワーク3種と組み合わせて動くアプリにする公式クイックスタートを比較します。セッションとフロントエンドの役割分担、ツール確認ゲートの実装ポイントを比較します。

Managed Agentsは単体でAPIを叩くだけでも動きますが、公式クイックスタートはVercelのChat SDK・assistant-ui・CopilotKit(AG-UI)という3つのチャットフレームワークとペアにして、完結して動くアプリとして配布しています。いずれの組み合わせも役割分担は同じで、フレームワークがチャット画面を描画し、マネージドセッションがサーバー側でエージェントループを回します。この記事では3つの実装を比較し、どの場面でどれを選ぶかを比較します。

3つのクイックスタートに共通する役割分担

Managed Agentsとチャットフレームワークを組み合わせるとき、責務は次のように分かれます。

  • セッション(サーバー側): 会話の全履歴(トランスクリプト)を保持し、サンドボックスでツールを実行し、進捗をイベントとしてストリーミングする
  • フロントエンド(チャットフレームワーク側): セッションが流すイベントを受け取り、メッセージ・ツール呼び出しカード・チャートなどの画面部品に変換して描画する

この分担が効いているのは、Managed Agentsの設計思想で扱ったハーネスとサンドボックスの分離が、そのままフロントエンドとの分離にも及んでいるからです。セッションがエージェントの実行状態を丸ごと持つので、フロントエンド側は「イベントをどう見せるか」だけに専念できます。逆に言えば、どのチャットフレームワークを選んでも裏側のエージェントループを書き直す必要はなく、アダプター層を差し替えるだけで済みます。

通信はイベントベースで、ユーザーの発言をuser.messageイベントとして送り、進捗やツール呼び出しはagent.*イベントとしてサーバー送信イベント(SSE)で返ってきます。イベント履歴はサーバー側に永続化されるため、フロントエンドが再接続してもこれまでの経緯を丸ごと取得し直せます。チャットフレームワーク側が実装するのは、このイベントストリームを購読し、種類ごとに対応する画面部品へマッピングするアダプター層だけです。

3つの実装を比較する

公式クイックスタートが示す3つの実装は、想定シナリオも画面の作り込み方もそれぞれ違います。

フレームワーク想定アプリセッションとの対応特徴的な実装ポイント
Chat SDK(Vercel)想定アプリブラウザーチャットで動くリサーチアナリストセッションとの対応会話1件が永続セッション1件に対応し、返信をストリーミングしながらツール呼び出しをライブフィードで表示する特徴的な実装ポイントChat SDKのアダプターを差し替えるだけで、同じハンドラーをSlack・Teams・Discord・WhatsAppに移植できる
assistant-ui想定アプリスプレッドシート分析チャットセッションとの対応セッション一覧がそのままスレッドリストになり、1つのreducerがセッションのイベントログをメッセージとツールカードに変換する特徴的な実装ポイントBashコマンドを実行する前に、インラインのAllow/Denyゲートを描画してから実行を許可する
CopilotKit(AG-UI)想定アプリ家計アシスタントセッションとの対応チャットスレッド1件がマネージドセッション1件に対応する特徴的な実装ポイントAG-UIアダプターが返信をトークン単位でストリーミングし、カスタムツールが会話内にインラインでチャートを描画する

3つとも「セッション = 会話の単位」という対応関係は共通していますが、ツール呼び出しの見せ方に違いが出ています。Chat SDKはライブフィードとして流し込むだけなのに対し、assistant-uiは実行前に人間の承認を挟むゲートを画面に持たせています。危険度の高い操作(ファイル削除やコード実行)を扱うアプリを作るなら、assistant-uiの承認ゲートの実装は流用価値が高い部分です。

3つのアプリの題材そのものにも意味があります。Chat SDKのリサーチアナリストはWeb検索とコード実行を組み合わせて調査結果をまとめる用途、assistant-uiのスプレッドシート分析はサンドボックス内でPythonを動かしてデータを処理する用途、CopilotKitの家計アシスタントはユーザーの入力を解釈して可視化を返す用途と、それぞれ想定するツール構成が異なります。どれも「長時間かかる可能性がある処理をサーバー側に任せつつ、進捗をリアルタイムでユーザーに見せる」という同じ課題への解答ですが、題材が違うことで各フレームワークの得意分野が浮かび上がる構成になっています。

ツール確認ゲートの裏側にあるイベントフロー

assistant-uiのAllow/Denyゲートは、Managed AgentsのAPIが標準で提供しているtool confirmationという仕組みの上に成り立っています。権限ポリシーがツール実行前の確認を要求している場合、フローは次の順序で進みます。

  1. セッションがagent.tool_useまたはagent.mcp_tool_useイベントを発行する
  2. セッションはstop_reason: requires_actionを含むsession.status_idleイベントとともに一時停止する。ブロックしているイベントIDはstop_reason.event_idsの配列に入っている
  3. 各イベントIDに対してuser.tool_confirmationイベントを送る。resultallowdenyを指定し、拒否する場合はdeny_messageで理由を添えられる
  4. ブロックしていたイベントがすべて解決すると、セッションはrunning状態に戻る
with client.beta.sessions.events.stream(session.id) as stream:
    for event in stream:
        if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
            if stop_reason.type == "requires_action":
                for event_id in stop_reason.event_ids:
                    client.beta.sessions.events.send(
                        session.id,
                        events=[{
                            "type": "user.tool_confirmation",
                            "tool_use_id": event_id,
                            "result": "allow",
                        }],
                    )

この仕組み自体はManaged AgentsのAPI共通の機能で、フレームワークごとの独自実装ではありません。assistant-uiのクイックスタートは、これをチャットUI上の「実行前に確認する」ボタンとして描画しているだけです。つまり、Chat SDKやCopilotKitで同じ承認フローを実装したい場合も、stop_reason.type === "requires_action"を監視してuser.tool_confirmationを送り返す処理を足せば、同じ仕組みをそのまま使い回せます。フレームワークが変わってもセッション側のイベント契約は変わらない、という設計がセッションを状態を持たない再開可能な単位として扱う発想と一致しています。

サンドボックス実行のツールとカスタムツールを分けて考える

3つの実装を横断して見えてくるもう1つの観点は、ツールがどこで実行されるかです。Managed Agentsのツール呼び出しには2系統あります。

  • サンドボックス実行のツール(Bash・ファイル操作など): agent.tool_useイベントで通知され、サンドボックス内で完結して結果が返る。フロントエンドは進捗を表示するだけで実行そのものには関与しない
  • カスタムツール: agent.custom_tool_useイベントで通知され、セッションはsession.status_idle(stop_reason: requires_action)で一時停止する。実行するのはアプリ側のコードで、結果をuser.custom_tool_resultイベントとして送り返すまでセッションは再開しない

CopilotKit(AG-UI)の実装が「カスタムツールが会話内にインラインでチャートを描画する」という形を取れるのは、この2系統目の仕組みを使っているためです。チャートの描画はサンドボックスの中では起きません。エージェントが「このデータでチャートを描画して」とカスタムツールを呼び出し、セッションが一時停止し、フロントエンド側のReactコンポーネントが実際の描画を行い、その結果(または成功のacknowledge)をセッションに送り返す、という流れになります。

この区別は実装方針を決めるときに効きます。サンドボックス内で完結する処理(コード実行やファイル生成)はサンドボックス実行のツールに任せ、アプリのUIそのものを操作する処理(チャートの描画、フォームの表示、通知の送信など)はカスタムツールに任せる、という切り分けが自然です。assistant-uiのAllow/Denyゲートは前者(サンドボックス実行のツール)に対する確認フローで、CopilotKitのチャート描画は後者(カスタムツール)の実行結果そのものという違いがあります。

自社でチャットアプリを設計するときも、この2系統をどちらに寄せるかで実装量が変わります。既存のUIコンポーネント資産が豊富なチームは、描画をカスタムツールに任せて既存コンポーネントをそのまま呼び出す設計にすれば、サンドボックス側の実装を増やさずに済みます。逆に自社UIをまだ持たないなら、まずはサンドボックス実行のツールだけで動かし始め、画面が固まってきた段階でカスタムツールを足していく順序のほうが手戻りが少なくなります。

どのフレームワークを選ぶか

3つのクイックスタートは技術的な優劣ではなく、作りたいアプリの性格に応じた選択肢です。

こう作りたい向くフレームワーク理由
汎用チャットとして作り、後でSlackやDiscordにも配りたい向くフレームワークChat SDK理由アダプター層が複数のメッセージングサーフェスに対応している
ツール実行の可否をユーザーに確認させたい業務系アプリ向くフレームワークassistant-ui理由Allow/Denyゲートが標準のUIコンポーネントとして用意されている
既存のCopilotKit UIやAG-UI準拠のフロントエンドに載せたい向くフレームワークCopilotKit(AG-UI)理由AG-UIプロトコル準拠のアダプターで既存資産をそのまま活かせる

いずれもGitHub上でソース一式が公開されているクイックスタートなので、まず動かしてイベントの流れを目で追い、その後で自社のUIコンポーネントに合わせて置き換えていくのが実装の近道です。3つともClaude Coworkのような完成済みUIを提供する製品とは違い、UI自体は開発者が持ち込む前提になっています。裏側のセッション管理をAnthropic側に任せつつ、画面は自社ブランドで作りたい、という要件に向いた構成です。

いずれのクイックスタートも、最初から自社の全要件を満たすようには作られていません。3つとも「1つの会話 = 1つのマネージドセッション」という最小構成の実装例で、公式ページはセッションとフロントエンドの配線を示す構成として紹介しており、認証やマルチテナント対応の作り込みには触れていません。そこから先の運用面の作り込みは自社のアプリケーション基盤に合わせて追加する前提で読むと期待値がずれません。

フレームワークを選んだあとの実装順序も3つで共通しています。まずクイックスタートをそのまま動かしてセッション作成からイベントストリーミングまでの一連の流れを体感し、次にシステムプロンプトやツール構成を自社のユースケースに差し替え、最後にUIコンポーネントをブランドに合わせて置き換える、という3段階です。裏側のセッション管理の仕組みを変えずに済むため、UIの作り込みだけに集中できるのがこの構成の利点です。

まとめ

  • Managed Agentsとチャットフレームワークの組み合わせは、セッションがサーバー側でエージェントループとツール実行を担い、フレームワークは画面描画に専念するという役割分担で統一されている
  • Chat SDKはメッセージングサーフェスへの横展開のしやすさ、assistant-uiはツール実行前の承認ゲート、CopilotKit(AG-UI)は既存のAG-UI資産との親和性がそれぞれの強み
  • ツール確認ゲートはsession.status_idlestop_reason: requires_actionuser.tool_confirmationイベントというAPI共通の仕組みで動いており、フレームワークを問わず同じ実装パターンを流用できる
  • どれを選ぶかはアプリの性格(汎用チャットか、承認が要る業務アプリか、既存UI資産があるか)で決まる
この記事を共有:XはてブLinkedIn