React a Agente AG-UI
Nx Plugin for AWS proporciona un generador para conectar un sitio web React a un Agente que expone el protocolo AG-UI. Conecta CopilotKit con un HttpAgent de @ag-ui/client en tu sitio web, con soporte para autenticación AWS IAM y Cognito.
Requisitos previos
Sección titulada «Requisitos previos»Antes de usar este generador, asegúrate de tener:
- Un sitio web React (generado usando el generador
ts#website) - Un Agente TypeScript o Python con
protocol=ag-ui(generado usando el generadorts#agentopy#agent) - Para agentes desplegados, autenticación Cognito agregada a través del generador
ts#website#auth
Ejecutar el generador
Sección titulada «Ejecutar el generador»pnpm nx g @aws/nx-plugin:connectionyarn nx g @aws/nx-plugin:connectionnpx nx g @aws/nx-plugin:connectionbunx nx g @aws/nx-plugin:connectionTambién puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:connection --dry-runyarn nx g @aws/nx-plugin:connection --dry-runnpx nx g @aws/nx-plugin:connection --dry-runbunx nx g @aws/nx-plugin:connection --dry-run- Instale el Nx Console VSCode Plugin si aún no lo ha hecho
- Abra la consola Nx en VSCode
- Haga clic en
Generate (UI)en la sección "Common Nx Commands" - Busque
@aws/nx-plugin - connection - Complete los parámetros requeridos
- Haga clic en
Generate
Se te pedirá que selecciones tu sitio web React como el proyecto de origen y el proyecto que contiene tu Agente AG-UI como el proyecto de destino. Si tu proyecto de destino contiene múltiples componentes (como múltiples agentes u otros tipos de componentes), se te pedirá que especifiques un targetComponent para desambiguar.
Opciones
Sección titulada «Opciones»| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
| sourceProject Requerido | string | - | El proyecto de origen |
| targetProject Requerido | string | - | El proyecto de destino al que conectar |
| sourceComponent | string | - | El componente de origen desde el que conectar (nombre del componente, ruta relativa a la raíz del proyecto de origen, o id del generador). Use '.' para seleccionar explícitamente el proyecto como origen. |
| targetComponent | string | - | El componente de destino al que conectar (nombre del componente, ruta relativa a la raíz del proyecto de destino, o id del generador). Use '.' para seleccionar explícitamente el proyecto como destino. |
| preferInstallDependencies | boolean | true | Si se prefiere instalar las dependencias después de que se ejecute el generador. Establecer en false para diferir la instalación al ejecutar múltiples generadores en lote (la instalación aún se ejecuta si es necesario para que los generadores subsiguientes puedan calcular el grafo de proyectos de Nx); instalar una vez al final. |
Salida del generador
Sección titulada «Salida del generador»El generador crea un componente AguiProvider compartido único, un hook por agente conectado, y un wrapper temático para los componentes de chat de CopilotKit:
Directoriosrc
Directoriocomponents
- AguiProvider.tsx
CopilotKitProviderúnico para cada agente AG-UI. Creado en la primera ejecución deconnectiony actualizado en ejecuciones posteriores para registrar cada nuevo agente. Directoriocopilot
- index.tsx Re-exporta
CopilotChat,CopilotSidebaryCopilotPopupcon valores predeterminados de slot que coinciden con eluxde tu sitio web (Cloudscape, Shadcn, o sin tema). - ThemeComponents .tsx Componentes de tema por slot (ej.
CloudscapeAssistantMessage.tsx,ShadcnChatInput.tsx). Solo se proporcionan cuandouxescloudscapeoshadcn.
- index.tsx Re-exporta
- AguiProvider.tsx
Directoriohooks
- useAgui<AgentName>.tsx Registra un agente AG-UI. Un archivo por ejecución de
connection. - useSigV4.tsx Firma SigV4 (solo IAM)
- useAgui<AgentName>.tsx Registra un agente AG-UI. Un archivo por ejecución de
Ejecutar connection una segunda vez para un agente diferente agrega un nuevo hook useAgui<AgentName>.tsx y actualiza AguiProvider.tsx para registrar ambos hooks — cualquier edición personalizada que hayas hecho al proveedor se preserva. main.tsx mantiene su único wrapper <AguiProvider> — nunca terminas con proveedores anidados.
Las siguientes dependencias se agregan al package.json raíz:
@copilotkit/react-core— incluyeCopilotKitProvidery componentes de chat (CopilotChat,CopilotSidebar,CopilotPopup)@ag-ui/client—HttpAgentusado por los hooks generadosaws4fetch,oidc-client-ts,react-oidc-context,@aws-sdk/credential-providers— solo autenticación IAMreact-oidc-context— autenticación Cognito
Cómo funciona
Sección titulada «Cómo funciona»Conexión AG-UI
Sección titulada «Conexión AG-UI»Cada hook useAgui<AgentName> lee el valor de runtime de su agente desde la Configuración de Runtime e instancia un HttpAgent de @ag-ui/client:
- Desplegado: el valor de runtime es un ARN de Bedrock AgentCore Runtime, que se convierte al endpoint HTTPS de AgentCore:
https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/invocations?qualifier=DEFAULT - Desarrollo local:
devsobrescribe el valor a la URL local del agente (ej.http://localhost:8081)
El AguiProvider compartido llama a cada hook generado y distribuye cada uno en selfManagedAgents en un único CopilotKitProvider, que los expone todos a los componentes de CopilotKit.
Integración con CopilotKit
Sección titulada «Integración con CopilotKit»CopilotKit es el cliente React de referencia de primera parte para el protocolo AG-UI e incluye componentes de chat listos para usar:
<CopilotChat />— interfaz de chat completa<CopilotSidebar />— chat en panel lateral fijo<CopilotPopup />— popup de chat flotante
Coloca cualquiera de estos en cualquier lugar dentro del wrapper <AguiProvider> (ya conectado en main.tsx para ti).
Autenticación
Sección titulada «Autenticación»El código generado maneja la autenticación dependiendo de la configuración de tu agente:
- IAM (predeterminado): usa solicitudes HTTP firmadas con AWS SigV4. Las credenciales se obtienen del Identity Pool de Cognito configurado con la autenticación de tu sitio web.
- Cognito: incrusta el token de acceso JWT en el encabezado
Authorizationcomo un token Bearer.
Sesiones e hilos
Sección titulada «Sesiones e hilos»AG-UI y AgentCore Runtime identifican una conversación de manera diferente, y el hook generado los vincula:
threadId— el identificador de conversación de AG-UI, enviado en el cuerpo de la solicitud. CopilotKit genera un UUID aleatorio por chat a menos que pases unthreadIdexplícito.- Session ID — la sesión de AgentCore Runtime, enviada en el encabezado
X-Amzn-Bedrock-AgentCore-Runtime-Session-Id. Selecciona la microVM que atiende la solicitud, y es en lo que elsession.ts/session.pyde tu agente basa el estado de la conversación.
El hook deriva el ID de sesión del ID de hilo, rellenándolo a la derecha hasta los 33 caracteres que requiere AgentCore Runtime:
function agentCoreSessionId(input: RunAgentInput): string { return (input.threadId ?? '').padEnd(33, '0');}Dejar threadId sin establecer es lo más simple — el UUID generado por CopilotKit ya tiene 36 caracteres. Si pasas uno explícitamente, hazlo de al menos 33 caracteres, ya que el relleno mapea IDs de hilo que difieren solo en caracteres finales a la misma sesión.
Tanto el Session ID como el Thread ID son proporcionados por el navegador. Para restringir a cada usuario a sus propias conversaciones, consulta la guía py#agent o ts#agent.
Infraestructura
Sección titulada «Infraestructura»Si tu agente utiliza autenticación IAM, el rol autenticado del Cognito Identity Pool debe tener permiso para invocar el agente.
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 conecta todas las acciones de invocación de AgentCore (InvokeAgentRuntime, InvokeAgentRuntimeWithWebSocketStream) en el ARN de runtime del agente.
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}Si tu agente utiliza autenticación Cognito, no necesitas definir ninguna infraestructura adicional para conectar tu sitio web a tu agente.
Usando el código generado
Sección titulada «Usando el código generado»Agregar una interfaz de chat
Sección titulada «Agregar una interfaz de chat»Instancia componentes de CopilotKit con agentId para seleccionar qué agente usar. El id es el nombre del agente — el mismo que elegiste cuando ejecutaste el generador ts#agent o py#agent — y también puedes encontrarlo en el archivo de hook generado (ej. la clave devuelta desde packages/web/src/hooks/useAgui<AgentName>.tsx).
Importa los componentes de chat desde el módulo generado ./components/copilot para que el tema que coincide con el ux de tu sitio web se aplique automáticamente:
import { CopilotChat } from './components/copilot';
function ChatPage() { return ( <CopilotChat agentId="agent" labels={{ welcomeMessageText: 'How can I help you today?', chatInputPlaceholder: 'Ask me anything...', }} /> );}Conectar múltiples agentes AG-UI
Sección titulada «Conectar múltiples agentes AG-UI»Ejecuta el generador connection una vez por agente. Cada agente registrado a través del AguiProvider compartido es visible desde cualquier lugar de la aplicación — instancia un componente de CopilotKit con un agentId diferente para enrutar cada chat al agente que desees:
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="story" /> {/* talks to StoryAgent */}<CopilotChat agentId="research" /> {/* talks to ResearchAgent */}Personalizar la apariencia
Sección titulada «Personalizar la apariencia»<CopilotChat /> (y <CopilotSidebar />, <CopilotPopup />) usan un sistema de slots recursivo — puedes sobrescribir cualquier subcomponente con una cadena de clase Tailwind, un objeto de props, o un componente React personalizado. Consulta la guía de slots de CopilotKit para el árbol completo de slots.
Temas integrados
Sección titulada «Temas integrados»El generador lee metadata.ux de tu proyecto de sitio web React y proporciona un módulo wrapper temático en src/components/copilot/index.tsx para que los componentes de chat coincidan con el resto de tu UI sin ninguna configuración adicional:
ux | Estilo aplicado a CopilotChat / CopilotSidebar / CopilotPopup |
|---|---|
cloudscape | Los mensajes se renderizan dentro de ChatBubbles de Cloudscape con Avatars de gen-AI (coincidiendo con el patrón de chat de IA generativa de Cloudscape); el indicador de escritura se convierte en un LoadingBar y la entrada es un PromptInput. Construido desde @cloudscape-design/components y @cloudscape-design/chat-components. |
shadcn | Los mensajes del asistente se renderizan en una burbuja bg-muted con un avatar Sparkles; los mensajes del usuario se renderizan alineados a la derecha en una burbuja bg-primary con un avatar User. La entrada es un Textarea redondeado + Button de envío/detención en forma de píldora (Enter envía, Shift+Enter nueva línea). Usa primitivas shadcn del paquete compartido common-shadcn. |
none (o cualquier otra cosa) | Sin tema — el módulo solo re-exporta los componentes predeterminados de CopilotKit. |
Importa los componentes temáticos desde el módulo de tema local (no directamente desde @copilotkit/react-core/v2) para que el tema se aplique automáticamente:
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="agent" />El tema se aplica como valores predeterminados de slot, por lo que cualquier slot que pases explícitamente aún gana — mantienes el control total cuando necesitas una sobrescritura puntual.
Personalizar el tema
Sección titulada «Personalizar el tema»El tema generado vive completamente dentro de tu proyecto:
src/components/copilot/index.tsx— exporta losCopilotChat/CopilotSidebar/CopilotPopuptemáticos y los objetoscloudscapeCopilotTheme/shadcnCopilotTheme. Edita este archivo para cambiar la conexión de slot predeterminada para cada chat en tu aplicación.src/components/copilot/<ThemeComponent>.tsx— componentes de tema por slot (ej.CloudscapeAssistantMessage,ShadcnChatInput). Edita estos para ajustar la apariencia de un solo slot sin reconfigurar el tema.
Por ejemplo, para insertar tu propio renderizador de mensajes de usuario mientras mantienes el resto del tema, edita el archivo relevante en src/components/copilot/ y re-expórtalo desde index.tsx.
Estilo Tailwind a través de slots
Sección titulada «Estilo Tailwind a través de slots»Las sobrescrituras por chat aún funcionan junto con el tema — cualquier cosa que pases como prop de slot sobrescribe el valor predeterminado temático:
<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', }}/>Reemplazar un slot con un componente personalizado
Sección titulada «Reemplazar un slot con un componente personalizado»Cualquier slot puede tomar un componente React en lugar de un className, por lo que puedes reemplazar completamente el predeterminado:
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 }}/>;Las sobrescrituras más profundas siguen la misma forma — ej. reemplaza solo el botón de copiar en los mensajes del asistente:
<CopilotChat agentId="agent" messageView={{ assistantMessage: { copyButton: ({ onClick }) => <button onClick={onClick}>Copy</button>, }, }}/>Desarrollo local
Sección titulada «Desarrollo local»El generador de conexión configura automáticamente la integración con dev:
- Ejecutar
nx dev <website>también iniciará el servidor local del agente - La configuración de runtime se sobrescribe para apuntar a la URL AG-UI local (ej.
http://localhost:8081) - Tanto el sitio web como el agente se recargan en caliente juntos
pnpm nx dev <WebsiteProject>yarn nx dev <WebsiteProject>npx nx dev <WebsiteProject>bunx nx dev <WebsiteProject>