Salta ai contenuti

React ad Agente AG-UI

Nx Plugin for AWS fornisce un generatore per connettere un sito web React a un Strands Agent che espone il protocollo AG-UI. Collega CopilotKit con un HttpAgent @ag-ui/client sul tuo sito web, con supporto per l’autenticazione AWS IAM e Cognito.

Prima di utilizzare questo generatore, assicurati di avere:

  1. Un sito web React (generato utilizzando il generatore ts#react-website)
  2. Un Python Strands Agent con protocol=AG-UI (generato utilizzando il generatore py#strands-agent)
  3. Per gli agenti distribuiti, Cognito Auth aggiunto tramite il generatore ts#react-website-auth
  1. Installa il Nx Console VSCode Plugin se non l'hai già fatto
  2. Apri la console Nx in VSCode
  3. Clicca su Generate (UI) nella sezione "Common Nx Commands"
  4. Cerca @aws/nx-plugin - connection
  5. Compila i parametri richiesti
    • Clicca su Generate

    Ti verrà richiesto di selezionare il tuo sito web React come progetto sorgente e il progetto contenente il tuo AG-UI Strands Agent come progetto di destinazione. Se il tuo progetto di destinazione contiene più componenti (come più agenti o altri tipi di componenti), ti verrà richiesto di specificare un targetComponent per disambiguare.

    Parametro Tipo Predefinito Descrizione
    sourceProject Obbligatorio string - Il progetto sorgente
    targetProject Obbligatorio string - Il progetto di destinazione a cui connettersi
    sourceComponent string - Il componente sorgente da cui connettersi (nome del componente, percorso relativo alla radice del progetto sorgente, o id del generatore). Usare '.' per selezionare esplicitamente il progetto come sorgente.
    targetComponent string - Il componente di destinazione a cui connettersi (nome del componente, percorso relativo alla radice del progetto di destinazione, o id del generatore). Usare '.' per selezionare esplicitamente il progetto come destinazione.

    Il generatore crea un singolo componente condiviso AguiProvider, un hook per ogni agente connesso e un wrapper tematizzato per i componenti chat di CopilotKit:

    • Directorysrc
      • Directorycomponents
        • AguiProvider.tsx Singolo CopilotKitProvider per ogni agente AG-UI. Creato alla prima esecuzione di connection e aggiornato nelle esecuzioni successive per registrare ogni nuovo agente.
        • Directorycopilot
          • index.tsx Ri-esporta CopilotChat, CopilotSidebar e CopilotPopup con valori predefiniti di slot che corrispondono al uxProvider del tuo sito web (Cloudscape, Shadcn, o nessun tema).
          • ThemeComponents .tsx Componenti tema per-slot (es. CloudscapeAssistantMessage.tsx, ShadcnChatInput.tsx). Forniti solo quando uxProvider è Cloudscape o Shadcn.
      • Directoryhooks
        • useAgui<AgentName>.tsx Registra un agente AG-UI. Un file per ogni esecuzione di connection.
        • useSigV4.tsx Firma SigV4 (solo IAM)

    Eseguire connection una seconda volta per un agente diverso aggiunge un nuovo hook useAgui<AgentName>.tsx e aggiorna AguiProvider.tsx per registrare entrambi gli hook — eventuali modifiche personalizzate apportate al provider vengono preservate. main.tsx mantiene il suo singolo wrapper <AguiProvider> — non ti ritroverai mai con provider annidati.

    Le seguenti dipendenze vengono aggiunte al package.json radice:

    • @copilotkit/react-core — include CopilotKitProvider e componenti chat (CopilotChat, CopilotSidebar, CopilotPopup)
    • @ag-ui/clientHttpAgent utilizzato dagli hook generati
    • aws4fetch, oidc-client-ts, react-oidc-context, @aws-sdk/credential-providers — solo autenticazione IAM
    • react-oidc-context — autenticazione Cognito

    Ogni hook useAgui<AgentName> legge il valore runtime del suo agente dalla Configurazione Runtime e istanzia un HttpAgent @ag-ui/client:

    • Distribuito: il valore runtime è un Bedrock AgentCore Runtime ARN, che viene convertito nell’endpoint HTTPS AgentCore: https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/invocations?qualifier=DEFAULT
    • Sviluppo locale: serve-local sovrascrive il valore con l’URL locale dell’agente (es. http://localhost:8081)

    L’AguiProvider condiviso chiama ogni hook generato e distribuisce ciascuno in selfManagedAgents su un singolo CopilotKitProvider, che li espone tutti ai componenti CopilotKit.

    CopilotKit è il client React di riferimento di prima parte per il protocollo AG-UI e include componenti chat già pronti:

    • <CopilotChat /> — interfaccia chat completa
    • <CopilotSidebar /> — chat a pannello laterale fisso
    • <CopilotPopup /> — popup chat fluttuante

    Posiziona uno qualsiasi di questi ovunque all’interno del wrapper <AguiProvider> (già collegato in main.tsx per te).

    Il codice generato gestisce l’autenticazione a seconda della configurazione del tuo agente:

    • IAM (predefinito): utilizza richieste HTTP firmate con AWS SigV4. Le credenziali vengono ottenute dal Cognito Identity Pool configurato con l’autenticazione del tuo sito web.
    • Cognito: incorpora il token di accesso JWT nell’header Authorization come Bearer token.

    Se il tuo agente utilizza l’autenticazione IAM, il ruolo autenticato del Cognito Identity Pool deve avere il permesso di invocare l’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 collega tutte le azioni di invocazione di AgentCore (InvokeAgentRuntime, InvokeAgentRuntimeWithWebSocketStream) sull’ARN di runtime dell’agente.

    Se il tuo agente utilizza l’autenticazione Cognito, non è necessario definire alcuna infrastruttura aggiuntiva per collegare il tuo sito web all’agente.

    Istanzia i componenti CopilotKit con agentId per selezionare quale agente utilizzare. L’id è il nome dell’agente — lo stesso che hai scelto quando hai eseguito il generatore py#strands-agent — e puoi anche trovarlo nel file hook generato (es. la chiave restituita da packages/web/src/hooks/useAgui<AgentName>.tsx).

    Importa i componenti chat dal modulo generato ./components/copilot in modo che il tema corrispondente al uxProvider del tuo sito web venga applicato automaticamente:

    import { CopilotChat } from './components/copilot';
    function ChatPage() {
    return (
    <CopilotChat
    agentId="agent"
    labels={{
    welcomeMessageText: 'How can I help you today?',
    chatInputPlaceholder: 'Ask me anything...',
    }}
    />
    );
    }

    Esegui il generatore connection una volta per agente. Ogni agente registrato tramite l’AguiProvider condiviso è visibile da qualsiasi punto dell’app — istanzia un componente CopilotKit con un agentId diverso per indirizzare ogni chat all’agente desiderato:

    import { CopilotChat } from './components/copilot';
    <CopilotChat agentId="story" /> {/* talks to StoryAgent */}
    <CopilotChat agentId="research" /> {/* talks to ResearchAgent */}

    <CopilotChat /> (e <CopilotSidebar />, <CopilotPopup />) utilizzano un sistema di slot ricorsivo — puoi sovrascrivere qualsiasi sotto-componente con una stringa di classe Tailwind, un oggetto prop o un componente React personalizzato. Consulta la guida agli slot di CopilotKit per l’albero completo degli slot.

    Il generatore legge metadata.uxProvider dal tuo progetto sito web React e fornisce un modulo wrapper tematizzato in src/components/copilot/index.tsx in modo che i componenti chat corrispondano al resto della tua UI senza alcuna configurazione aggiuntiva:

    uxProviderStilizzazione applicata a CopilotChat / CopilotSidebar / CopilotPopup
    CloudscapeI messaggi vengono renderizzati all’interno di Cloudscape ChatBubble con Avatar gen-AI (corrispondenti al pattern di chat AI generativa Cloudscape); l’indicatore di digitazione diventa una LoadingBar e l’input è un PromptInput. Costruito da @cloudscape-design/components e @cloudscape-design/chat-components.
    ShadcnI messaggi dell’assistente vengono renderizzati in una bolla bg-muted con un avatar Sparkles; i messaggi dell’utente vengono renderizzati allineati a destra in una bolla bg-primary con un avatar User. L’input è una Textarea arrotondata + Button di invio/arresto a forma di pillola (Enter invia, Shift+Enter nuova riga). Utilizza primitive shadcn dal pacchetto condiviso common-shadcn.
    None (o qualsiasi altro valore)Nessun tema — il modulo semplicemente ri-esporta i componenti CopilotKit predefiniti.

    Importa i componenti tematizzati dal modulo tema locale (non direttamente da @copilotkit/react-core/v2) in modo che il tema venga applicato automaticamente:

    import { CopilotChat } from './components/copilot';
    <CopilotChat agentId="agent" />

    Il tema viene applicato come valori predefiniti degli slot, quindi qualsiasi slot che passi esplicitamente ha comunque la precedenza — mantieni il pieno controllo ogni volta che hai bisogno di una sovrascrittura occasionale.

    Il tema generato risiede interamente all’interno del tuo progetto:

    • src/components/copilot/index.tsx — esporta i CopilotChat / CopilotSidebar / CopilotPopup tematizzati e gli oggetti cloudscapeCopilotTheme / shadcnCopilotTheme. Modifica questo file per cambiare il collegamento predefinito degli slot per ogni chat nella tua app.
    • src/components/copilot/<ThemeComponent>.tsx — componenti tema per-slot (es. CloudscapeAssistantMessage, ShadcnChatInput). Modificali per regolare l’aspetto di un singolo slot senza ricablare il tema.

    Ad esempio, per inserire il tuo renderer di messaggi utente personalizzato mantenendo il resto del tema, modifica il file pertinente in src/components/copilot/ e ri-esportalo da index.tsx.

    Le sovrascritture per-chat funzionano ancora insieme al tema — qualsiasi cosa passi come prop slot sovrascrive il valore predefinito tematizzato:

    <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',
    }}
    />

    Sostituire uno slot con un componente personalizzato

    Sezione intitolata “Sostituire uno slot con un componente personalizzato”

    Qualsiasi slot può accettare un componente React invece di un className, quindi puoi sostituire completamente il predefinito:

    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 }}
    />;

    Le sostituzioni più profonde seguono la stessa forma — es. sostituisci solo il pulsante copia sui messaggi dell’assistente:

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

    Il generatore di connessione configura automaticamente l’integrazione serve-local:

    1. Eseguire nx serve-local <website> avvierà anche il server locale dell’agente
    2. La configurazione runtime viene sovrascritta per puntare all’URL AG-UI locale (es. http://localhost:8081)
    3. Sia il sito web che l’agente si ricaricano automaticamente insieme
    Terminal window
    pnpm nx serve-local <WebsiteProject>