React から AG-UI Agent へ
Nx Plugin for AWS は、AG-UI プロトコルを公開する Agent に React ウェブサイトを接続するためのジェネレーターを提供します。これは、AWS IAM および Cognito 認証サポートを備えた @ag-ui/client HttpAgent を使用して、ウェブサイト上で CopilotKit を配線します。
このジェネレーターを使用する前に、以下を確認してください:
- React ウェブサイト(
ts#websiteジェネレーターを使用して生成) protocol=ag-uiを持つ TypeScript または Python Agent(ts#agentまたはpy#agentジェネレーターを使用して生成)- デプロイされた Agent の場合、
ts#website#authジェネレーター経由で追加された Cognito Auth
ジェネレーターの実行
Section titled “ジェネレーターの実行”pnpm nx g @aws/nx-plugin:connectionyarn nx g @aws/nx-plugin:connectionnpx nx g @aws/nx-plugin:connectionbunx nx g @aws/nx-plugin:connection- インストール Nx Console VSCode Plugin まだインストールしていない場合
- VSCodeでNxコンソールを開く
- クリック
Generate (UI)"Common Nx Commands"セクションで - 検索
@aws/nx-plugin - connection - 必須パラメータを入力
- クリック
Generate
React ウェブサイトをソースプロジェクトとして、AG-UI Agent を含むプロジェクトをターゲットプロジェクトとして選択するよう求められます。ターゲットプロジェクトに複数のコンポーネント(複数の Agent や他のコンポーネントタイプなど)が含まれている場合は、曖昧さを解消するために targetComponent を指定するよう求められます。
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
| sourceProject 必須 | string | - | ソース プロジェクト |
| targetProject 必須 | string | - | 接続先のターゲット プロジェクト |
| sourceComponent | string | - | 接続元のソース コンポーネント (コンポーネント名、ソース プロジェクト ルートからの相対パス、またはジェネレーター ID)。プロジェクトをソースとして明示的に選択するには '.' を使用します。 |
| targetComponent | string | - | 接続先のターゲット コンポーネント (コンポーネント名、ターゲット プロジェクト ルートからの相対パス、またはジェネレーター ID)。プロジェクトをターゲットとして明示的に選択するには '.' を使用します。 |
| preferInstallDependencies | boolean | true | ジェネレーター実行後に依存関係のインストールを優先するかどうか。複数のジェネレーターをバッチ処理する際にインストールを延期する場合はfalseに設定します(後続のジェネレーターがNxプロジェクトグラフを計算できるよう、必要に応じてインストールは実行されます)。最後に一度だけインストールします。 |
ジェネレーターの出力
Section titled “ジェネレーターの出力”ジェネレーターは、単一の共有 AguiProvider コンポーネント、接続された Agent ごとに 1 つのフック、および CopilotKit チャットコンポーネント用のテーマ付きラッパーを作成します:
Directorysrc
Directorycomponents
- AguiProvider.tsx すべての AG-UI Agent 用の単一の
CopilotKitProvider。最初のconnection実行時に作成され、後続の実行で各新しい Agent を登録するために更新されます。 Directorycopilot
- index.tsx ウェブサイトの
ux(Cloudscape、Shadcn、またはテーマなし)に一致するスロットデフォルトを持つCopilotChat、CopilotSidebar、CopilotPopupを再エクスポートします。 - ThemeComponents .tsx スロットごとのテーマコンポーネント(例:
CloudscapeAssistantMessage.tsx、ShadcnChatInput.tsx)。uxがcloudscapeまたはshadcnの場合のみ提供されます。
- index.tsx ウェブサイトの
- AguiProvider.tsx すべての AG-UI Agent 用の単一の
Directoryhooks
- useAgui<AgentName>.tsx 1 つの AG-UI Agent を登録します。
connection実行ごとに 1 つのファイル。 - useSigV4.tsx SigV4 署名(IAM のみ)
- useAgui<AgentName>.tsx 1 つの AG-UI Agent を登録します。
異なる Agent に対して 2 回目の connection を実行すると、新しい useAgui<AgentName>.tsx フックが追加され、AguiProvider.tsx が更新されて両方のフックが登録されます — プロバイダーに加えたカスタム編集は保持されます。main.tsx は単一の <AguiProvider> ラッパーを保持します — ネストされたプロバイダーになることはありません。
以下の依存関係がルートの package.json に追加されます:
@copilotkit/react-core—CopilotKitProviderとチャットコンポーネント(CopilotChat、CopilotSidebar、CopilotPopup)を提供@ag-ui/client— 生成されたフックで使用されるHttpAgentaws4fetch、oidc-client-ts、react-oidc-context、@aws-sdk/credential-providers— IAM 認証のみreact-oidc-context— Cognito 認証
AG-UI 接続
Section titled “AG-UI 接続”各 useAgui<AgentName> フックは、ランタイム設定から Agent のランタイム値を読み取り、@ag-ui/client HttpAgent をインスタンス化します:
- デプロイ済み:ランタイム値は Bedrock AgentCore Runtime ARN であり、AgentCore HTTPS エンドポイントに変換されます:
https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/invocations?qualifier=DEFAULT - ローカル開発:
devは値を Agent のローカル URL(例:http://localhost:8081)にオーバーライドします
共有 AguiProvider はすべての生成されたフックを呼び出し、それぞれを単一の CopilotKitProvider の selfManagedAgents に展開し、すべてを CopilotKit コンポーネントに公開します。
CopilotKit 統合
Section titled “CopilotKit 統合”CopilotKit は AG-UI プロトコル用の第一級の参照 React クライアントであり、すぐに使えるチャットコンポーネントを提供します:
<CopilotChat />— 完全なチャットインターフェース<CopilotSidebar />— 固定サイドパネルチャット<CopilotPopup />— フローティングチャットポップアップ
これらのいずれかを <AguiProvider> ラッパー内の任意の場所に配置します(すでに main.tsx に配線されています)。
生成されたコードは、Agent の設定に応じて認証を処理します:
- IAM(デフォルト):AWS SigV4 署名付き HTTP リクエストを使用します。認証情報は、ウェブサイトの認証で設定された Cognito Identity Pool から取得されます。
- Cognito:JWT アクセストークンを Bearer トークンとして
Authorizationヘッダーに埋め込みます。
セッションとスレッド
Section titled “セッションとスレッド”AG-UI と AgentCore Runtime はそれぞれ異なる方法で会話を識別し、生成されたフックがそれらを結び付けます:
threadId— AG-UI の会話識別子で、リクエストボディで送信されます。CopilotKit は、明示的なthreadIdを渡さない限り、チャットごとにランダムな UUID を生成します。- Session ID — AgentCore Runtime のセッションで、
X-Amzn-Bedrock-AgentCore-Runtime-Session-Idヘッダーで送信されます。これはリクエストを処理する microVM を選択し、Agent のsession.ts/session.pyが会話状態をキーとするものです。
フックは、スレッド ID からセッション ID を導出し、AgentCore Runtime が必要とする 33 文字に右パディングします:
function agentCoreSessionId(input: RunAgentInput): string { return (input.threadId ?? '').padEnd(33, '0');}threadId を未設定のままにするのが最も簡単です — CopilotKit が生成する UUID はすでに 36 文字です。明示的に渡す場合は、少なくとも 33 文字にしてください。パディングにより、末尾の文字のみが異なるスレッド ID が同じセッションにマッピングされるためです。
Session ID と Thread ID の両方はブラウザーによって提供されます。各ユーザーを自分の会話に制限するには、py#agent または ts#agent ガイドを参照してください。
インフラストラクチャ
Section titled “インフラストラクチャ”エージェントが IAM 認証を使用する場合、Cognito Identity Pool の認証済みロールにエージェントを呼び出す権限を付与する必要があります。
const identity = new UserIdentity(this, 'Identity');const myAgent = new MyAgent(this, 'MyAgent');
// Grant the authenticated Cognito role permission to invoke the agentmyAgent.grantInvokeAccess(identity.identityPool.authenticatedRole);grantInvokeAccess は、エージェントのランタイム ARN 上のすべての AgentCore 呼び出しアクション(InvokeAgentRuntime、InvokeAgentRuntimeWithWebSocketStream)を接続します。
module "identity" { source = "../../common/terraform/src/core/user-identity"}
module "my_agent" { source = "../../common/terraform/src/app/agents/my-agent"
appconfig_application_id = module.runtime_config_appconfig.application_id appconfig_application_arn = module.runtime_config_appconfig.application_arn}
# Grant the authenticated Cognito role permission to invoke the agentresource "aws_iam_policy" "invoke_my_agent" { name = "InvokeMyAgentPolicy" policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = [ "bedrock-agentcore:InvokeAgentRuntime", "bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream", ] Resource = [ module.my_agent.agent_core_runtime_arn, "${module.my_agent.agent_core_runtime_arn}/*", ] }] })}
resource "aws_iam_role_policy_attachment" "invoke_my_agent" { role = module.identity.authenticated_role_name policy_arn = aws_iam_policy.invoke_my_agent.arn}エージェントが Cognito 認証を使用する場合、ウェブサイトをエージェントに接続するための追加のインフラストラクチャを定義する必要はありません。
生成されたコードの使用
Section titled “生成されたコードの使用”チャットインターフェースの追加
Section titled “チャットインターフェースの追加”使用する Agent を選択するために agentId を指定して CopilotKit コンポーネントをインスタンス化します。id は Agent の名前です — ts#agent または py#agent ジェネレーターを実行したときに選択したものと同じです — また、生成されたフックファイル(例:packages/web/src/hooks/useAgui<AgentName>.tsx から返されるキー)でも確認できます。
ウェブサイトの ux に一致するテーマが自動的に適用されるように、生成された ./components/copilot モジュールからチャットコンポーネントをインポートします:
import { CopilotChat } from './components/copilot';
function ChatPage() { return ( <CopilotChat agentId="agent" labels={{ welcomeMessageText: 'How can I help you today?', chatInputPlaceholder: 'Ask me anything...', }} /> );}複数の AG-UI Agent の接続
Section titled “複数の AG-UI Agent の接続”Agent ごとに 1 回 connection ジェネレーターを実行します。共有 AguiProvider 経由で登録されたすべての Agent は、アプリ内のどこからでも表示されます — 異なる agentId を持つ CopilotKit コンポーネントをインスタンス化して、各チャットを目的の Agent にルーティングします:
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="story" /> {/* talks to StoryAgent */}<CopilotChat agentId="research" /> {/* talks to ResearchAgent */}ルック&フィールのカスタマイズ
Section titled “ルック&フィールのカスタマイズ”<CopilotChat />(および <CopilotSidebar />、<CopilotPopup />)は再帰的なスロットシステムを使用します — 任意のサブコンポーネントを Tailwind クラス文字列、プロップオブジェクト、またはカスタム React コンポーネントでオーバーライドできます。完全なスロットツリーについては、CopilotKit スロットガイドを参照してください。
組み込みテーマ
Section titled “組み込みテーマ”ジェネレーターは React ウェブサイトプロジェクトから metadata.ux を読み取り、src/components/copilot/index.tsx にテーマ付きラッパーモジュールを提供するため、追加の設定なしでチャットコンポーネントが UI の残りの部分と一致します:
ux | CopilotChat / CopilotSidebar / CopilotPopup に適用されるスタイリング |
|---|---|
cloudscape | メッセージは Cloudscape ChatBubble 内に gen-AI Avatar とともにレンダリングされます(Cloudscape 生成 AI チャットパターンに一致);タイピングインジケーターは LoadingBar になり、入力は PromptInput になります。@cloudscape-design/components と @cloudscape-design/chat-components から構築されます。 |
shadcn | アシスタントメッセージは bg-muted バブル内に Sparkles アバターとともにレンダリングされます;ユーザーメッセージは bg-primary バブル内に User アバターとともに右揃えでレンダリングされます。入力は丸みを帯びた Textarea + ピル型の送信/停止 Button です(Enter で送信、Shift+Enter で改行)。共有 common-shadcn パッケージの shadcn プリミティブを使用します。 |
none(またはその他) | テーマなし — モジュールはデフォルトの CopilotKit コンポーネントを再エクスポートするだけです。 |
テーマが自動的に適用されるように、ローカルテーマモジュールからテーマ付きコンポーネントをインポートします(@copilotkit/react-core/v2 から直接ではなく):
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="agent" />テーマはスロットデフォルトとして適用されるため、明示的に渡すスロットは引き続き優先されます — 一回限りのオーバーライドが必要な場合でも、完全な制御を維持できます。
テーマのカスタマイズ
Section titled “テーマのカスタマイズ”生成されたテーマは完全にプロジェクト内に存在します:
src/components/copilot/index.tsx— テーマ付きCopilotChat/CopilotSidebar/CopilotPopupとcloudscapeCopilotTheme/shadcnCopilotThemeオブジェクトをエクスポートします。このファイルを編集して、アプリ内のすべてのチャットのデフォルトスロット配線を変更します。src/components/copilot/<ThemeComponent>.tsx— スロットごとのテーマコンポーネント(例:CloudscapeAssistantMessage、ShadcnChatInput)。テーマを再配線せずに単一のスロットの外観を調整するには、これらを編集します。
たとえば、テーマの残りの部分を維持しながら独自のユーザーメッセージレンダラーをドロップインするには、src/components/copilot/ 内の関連ファイルを編集し、index.tsx から再エクスポートします。
スロット経由の Tailwind スタイリング
Section titled “スロット経由の Tailwind スタイリング”チャットごとのオーバーライドは、テーマと並行して機能します — スロットプロップとして渡すものは、テーマのデフォルトをオーバーライドします:
<CopilotChat agentId="agent" // style the input and its children input={{ textArea: 'text-blue-600', sendButton: 'bg-blue-600 hover:bg-blue-700', }} // style nested message slots messageView={{ assistantMessage: 'bg-blue-50 rounded-xl p-2', userMessage: 'bg-blue-100 rounded-xl', }}/>カスタムコンポーネントでスロットを置き換える
Section titled “カスタムコンポーネントでスロットを置き換える”任意のスロットは className の代わりに React コンポーネントを取ることができるため、デフォルトを完全に置き換えることができます:
import { CopilotChat } from './components/copilot';
const MySendButton: React.FC<{ onClick: () => void }> = ({ onClick }) => ( <button onClick={onClick} className="my-send-btn"> Send </button>);
<CopilotChat agentId="agent" input={{ sendButton: MySendButton }}/>;より深いオーバーライドも同じ形状に従います — 例えば、アシスタントメッセージのコピーボタンだけを置き換える:
<CopilotChat agentId="agent" messageView={{ assistantMessage: { copyButton: ({ onClick }) => <button onClick={onClick}>Copy</button>, }, }}/>ローカル開発
Section titled “ローカル開発”接続ジェネレーターは自動的に dev 統合を設定します:
nx dev <website>を実行すると、Agent のローカルサーバーも起動します- ランタイム設定はローカル AG-UI URL(例:
http://localhost:8081)を指すようにオーバーライドされます - ウェブサイトと Agent の両方が一緒にホットリロードされます
pnpm nx dev <WebsiteProject>yarn nx dev <WebsiteProject>npx nx dev <WebsiteProject>bunx nx dev <WebsiteProject>