Ir al contenido

React a Agente AG-UI

Nx Plugin for AWS proporciona un generador para conectar un sitio web React a un Strands Agent que expone el protocolo AG-UI. Configura CopilotKit con un HttpAgent de @ag-ui/client en tu sitio web, con soporte para autenticación AWS IAM y Cognito.

Antes de usar este generador, asegúrate de tener:

  1. Un sitio web React (generado usando el generador ts#react-website)
  2. Un Python Strands Agent con protocol=AG-UI (generado usando el generador py#strands-agent)
  3. Para agentes desplegados, Cognito Auth agregado a través del generador ts#react-website-auth
  1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
  2. Abra la consola Nx en VSCode
  3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
  4. Busque @aws/nx-plugin - connection
  5. Complete los parámetros requeridos
    • Haga clic en Generate

    Se te pedirá que selecciones tu sitio web React como proyecto de origen y el proyecto que contiene tu AG-UI Strands Agent como 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.

    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.

    El generador crea un componente AguiProvider único compartido, un hook por agente conectado, y un wrapper con tema para los componentes de chat de CopilotKit:

    • Directoriosrc
      • Directoriocomponents
        • AguiProvider.tsx Único CopilotKitProvider para cada agente AG-UI. Creado en la primera ejecución de connection y actualizado en ejecuciones posteriores para registrar cada nuevo agente.
        • Directoriocopilot
          • index.tsx Re-exporta CopilotChat, CopilotSidebar y CopilotPopup con valores predeterminados de slots que coinciden con el uxProvider de tu sitio web (Cloudscape, Shadcn, o sin tema).
          • ThemeComponents .tsx Componentes de tema por slot (por ejemplo, CloudscapeAssistantMessage.tsx, ShadcnChatInput.tsx). Solo se generan cuando uxProvider es Cloudscape o Shadcn.
      • Directoriohooks
        • useAgui<AgentName>.tsx Registra un agente AG-UI. Un archivo por ejecución de connection.
        • useSigV4.tsx Firma SigV4 (solo IAM)

    Ejecutar connection por 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 conserva. 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 — incluye CopilotKitProvider y componentes de chat (CopilotChat, CopilotSidebar, CopilotPopup)
    • @ag-ui/clientHttpAgent usado por los hooks generados
    • aws4fetch, oidc-client-ts, react-oidc-context, @aws-sdk/credential-providers — solo autenticación IAM
    • react-oidc-context — autenticación Cognito

    Cada hook useAgui<AgentName> lee el valor de tiempo de ejecución de su agente desde Runtime Configuration e instancia un HttpAgent de @ag-ui/client:

    • Desplegado: el valor de tiempo de ejecución 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: serve-local sobrescribe el valor a la URL local del agente (por ejemplo, http://localhost:8081)

    El AguiProvider compartido llama a cada hook generado y los distribuye en selfManagedAgents en un único CopilotKitProvider, que los expone todos a los componentes de 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 /> — ventana emergente de chat flotante

    Coloca cualquiera de estos en cualquier lugar dentro del wrapper <AguiProvider> (ya configurado en main.tsx para ti).

    El código generado maneja la autenticación según la configuración de tu agente:

    • IAM (predeterminado): usa solicitudes HTTP firmadas con AWS SigV4. Las credenciales se obtienen del Cognito Identity Pool configurado con la autenticación de tu sitio web.
    • Cognito: incrusta el token de acceso JWT en el encabezado Authorization como un token Bearer.

    Si tu agente utiliza autenticación IAM, el rol autenticado del Cognito Identity Pool debe tener permiso para invocar el agente.

    packages/infra/src/stacks/application-stack.ts
    const identity = new UserIdentity(this, 'Identity');
    const myAgent = new MyAgent(this, 'MyAgent');
    // Grant the authenticated Cognito role permission to invoke the agent
    myAgent.grantInvokeAccess(identity.identityPool.authenticatedRole);

    grantInvokeAccess configura todas las acciones de invocación de AgentCore (InvokeAgentRuntime, InvokeAgentRuntimeWithWebSocketStream) en el ARN de tiempo de ejecución del agente.

    Si tu agente utiliza autenticación Cognito, no necesitas definir ninguna infraestructura adicional para conectar tu sitio web a tu agente.

    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 py#strands-agent — y también puedes encontrarlo en el archivo de hook generado (por ejemplo, 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 uxProvider 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...',
    }}
    />
    );
    }

    Ejecuta el generador connection una vez por agente. Todos los agentes registrados a través del AguiProvider compartido son visibles desde cualquier lugar en 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 */}

    <CopilotChat /> (y <CopilotSidebar />, <CopilotPopup />) usan un sistema de slots recursivo — puedes sobrescribir cualquier subcomponente con una cadena de clase Tailwind, un objeto de propiedades o un componente React personalizado. Consulta la guía de slots de CopilotKit para el árbol completo de slots.

    El generador lee metadata.uxProvider de tu proyecto de sitio web React y genera un módulo wrapper con tema en src/components/copilot/index.tsx para que los componentes de chat coincidan con el resto de tu UI sin ninguna configuración adicional:

    uxProviderEstilizado aplicado a CopilotChat / CopilotSidebar / CopilotPopup
    CloudscapeLos mensajes se renderizan dentro de ChatBubbles de Cloudscape con Avatars gen-AI (coincidiendo con el patrón de chat de IA generativa de Cloudscape); el indicador de escritura se convierte en un LoadingBar y el input es un PromptInput. Construido con @cloudscape-design/components y @cloudscape-design/chat-components.
    ShadcnLos 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. El input es un Textarea redondeado + Button de enviar/detener en forma de píldora (Enter envía, Shift+Enter inserta saltos de línea). Usa primitivos de shadcn del paquete compartido common-shadcn.
    None (o cualquier otro)Sin tema — el módulo simplemente re-exporta los componentes predeterminados de CopilotKit.

    Importa los componentes con tema 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 slots, por lo que cualquier slot que pases explícitamente aún gana — mantienes el control total cuando necesitas una sobrescritura puntual.

    El tema generado vive completamente dentro de tu proyecto:

    • src/components/copilot/index.tsx — exporta los componentes con tema CopilotChat / CopilotSidebar / CopilotPopup y los objetos cloudscapeCopilotTheme / shadcnCopilotTheme. Edita este archivo para cambiar la configuración predeterminada de slots para cada chat en tu aplicación.
    • src/components/copilot/<ThemeComponent>.tsx — componentes de tema por slot (por ejemplo, CloudscapeAssistantMessage, ShadcnChatInput). Edita estos para ajustar la apariencia de un único slot sin reconfigurar el tema.

    Por ejemplo, para usar 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.

    Las sobrescrituras por chat aún funcionan junto con el tema — cualquier cosa que pases como prop de slot sobrescribe el predeterminado del tema:

    <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 recibir 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 — por ejemplo, reemplaza solo el botón de copiar en los mensajes del asistente:

    <CopilotChat
    agentId="agent"
    messageView={{
    assistantMessage: {
    copyButton: ({ onClick }) => <button onClick={onClick}>Copy</button>,
    },
    }}
    />

    El generador de conexión configura automáticamente la integración con serve-local:

    1. Ejecutar nx serve-local <website> también iniciará el servidor local del agente
    2. La configuración de tiempo de ejecución se sobrescribe para apuntar a la URL AG-UI local (por ejemplo, http://localhost:8081)
    3. Tanto el sitio web como el agente se recargan en caliente juntos
    Terminal window
    pnpm nx serve-local <WebsiteProject>