Pular para o conteúdo

React para Agente AG-UI

Nx Plugin for AWS fornece um gerador para conectar um site React a um Agente que expõe o protocolo AG-UI. Ele configura o CopilotKit com um HttpAgent @ag-ui/client no seu site, com suporte para autenticação AWS IAM e Cognito.

Antes de usar este gerador, certifique-se de ter:

  1. Um site React (gerado usando o gerador ts#website)
  2. Um Agente TypeScript ou Python com protocol=ag-ui (gerado usando o gerador ts#agent ou py#agent)
  3. Para agentes implantados, Cognito Auth adicionado via gerador ts#website#auth
Terminal window
pnpm nx g @aws/nx-plugin:connection
Você também pode realizar uma execução simulada para ver quais arquivos seriam alterados
Terminal window
pnpm nx g @aws/nx-plugin:connection --dry-run

Você será solicitado a selecionar seu site React como o projeto de origem e o projeto contendo seu Agente AG-UI como o projeto de destino. Se o seu projeto de destino contiver múltiplos componentes (como múltiplos agentes ou outros tipos de componentes), você será solicitado a especificar um targetComponent para desambiguar.

ParâmetroTipoPadrãoDescrição
sourceProject Obrigatóriostring-O projeto de origem
targetProject Obrigatóriostring-O projeto de destino para conectar
sourceComponent string-O componente de origem para conectar (nome do componente, caminho relativo à raiz do projeto de origem, ou id do gerador). Use '.' para selecionar explicitamente o projeto como origem.
targetComponent string-O componente de destino para conectar (nome do componente, caminho relativo à raiz do projeto de destino, ou id do gerador). Use '.' para selecionar explicitamente o projeto como destino.
preferInstallDependencies booleantrueSe deve preferir instalar dependências após a execução do gerador. Defina como false para adiar a instalação ao executar múltiplos geradores em lote (uma instalação ainda é executada se necessário para que os geradores subsequentes possam calcular o grafo de projetos Nx); instale uma vez no final.

O gerador cria um componente AguiProvider único compartilhado, um hook por agente conectado e um wrapper temático para os componentes de chat do CopilotKit:

  • Directorysrc
    • Directorycomponents
      • AguiProvider.tsx CopilotKitProvider único para cada agente AG-UI. Criado na primeira execução de connection e atualizado em execuções subsequentes para registrar cada novo agente.
      • Directorycopilot
        • index.tsx Re-exporta CopilotChat, CopilotSidebar e CopilotPopup com padrões de slot que correspondem ao ux do seu site (Cloudscape, Shadcn, ou nenhum tema).
        • ThemeComponents .tsx Componentes de tema por slot (por exemplo, CloudscapeAssistantMessage.tsx, ShadcnChatInput.tsx). Fornecidos apenas quando ux é cloudscape ou shadcn.
    • Directoryhooks
      • useAgui<AgentName>.tsx Registra um agente AG-UI. Um arquivo por execução de connection.
      • useSigV4.tsx Assinatura SigV4 (apenas IAM)

Executar connection uma segunda vez para um agente diferente adiciona um novo hook useAgui<AgentName>.tsx e atualiza AguiProvider.tsx para registrar ambos os hooks — quaisquer edições personalizadas que você tenha feito no provider são preservadas. main.tsx mantém seu único wrapper <AguiProvider> — você nunca acaba com providers aninhados.

As seguintes dependências são adicionadas ao package.json raiz:

  • @copilotkit/react-core — fornece CopilotKitProvider e componentes de chat (CopilotChat, CopilotSidebar, CopilotPopup)
  • @ag-ui/clientHttpAgent usado pelos hooks gerados
  • aws4fetch, oidc-client-ts, react-oidc-context, @aws-sdk/credential-providers — apenas autenticação IAM
  • react-oidc-context — autenticação Cognito

Cada hook useAgui<AgentName> lê o valor de runtime do seu agente da Configuração de Runtime e instancia um HttpAgent @ag-ui/client:

  • Implantado: o valor de runtime é um ARN do Bedrock AgentCore Runtime, que é convertido para o endpoint HTTPS do AgentCore: https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/invocations?qualifier=DEFAULT
  • Desenvolvimento local: dev substitui o valor pela URL local do agente (por exemplo, http://localhost:8081)

O AguiProvider compartilhado chama cada hook gerado e espalha cada um em selfManagedAgents em um único CopilotKitProvider, que os expõe todos aos componentes CopilotKit.

CopilotKit é o cliente React de referência de primeira parte para o protocolo AG-UI e vem com componentes de chat prontos:

  • <CopilotChat /> — interface de chat completa
  • <CopilotSidebar /> — chat em painel lateral fixo
  • <CopilotPopup /> — popup de chat flutuante

Coloque qualquer um destes em qualquer lugar dentro do wrapper <AguiProvider> (já conectado em main.tsx para você).

O código gerado lida com autenticação dependendo da configuração do seu agente:

  • IAM (padrão): usa requisições HTTP assinadas com AWS SigV4. As credenciais são obtidas do Cognito Identity Pool configurado com a autenticação do seu site.
  • Cognito: incorpora o token de acesso JWT no cabeçalho Authorization como um Bearer token.

AG-UI e AgentCore Runtime identificam uma conversa de maneira diferente, e o hook gerado os conecta:

  • threadId — o identificador de conversa AG-UI, enviado no corpo da requisição. CopilotKit gera um UUID aleatório por chat, a menos que você passe um threadId explícito.
  • Session ID — a sessão do AgentCore Runtime, enviada no cabeçalho X-Amzn-Bedrock-AgentCore-Runtime-Session-Id. Ele seleciona a microVM que atende a requisição, e é o que o session.ts / session.py do seu agente usa como chave para o estado da conversa.

O hook deriva o session ID do thread ID, preenchendo-o à direita até os 33 caracteres que o AgentCore Runtime requer:

function agentCoreSessionId(input: RunAgentInput): string {
return (input.threadId ?? '').padEnd(33, '0');
}

Deixar threadId não definido é mais simples — o UUID gerado pelo CopilotKit já tem 36 caracteres. Se você passar um explicitamente, faça com que tenha pelo menos 33 caracteres, pois o preenchimento mapeia thread IDs que diferem apenas em caracteres finais para a mesma sessão.

Tanto o Session ID quanto o Thread ID são fornecidos pelo navegador. Para restringir cada usuário às suas próprias conversas, consulte o guia py#agent ou ts#agent.

Se o seu agent usa autenticação IAM, a função autenticada do Cognito Identity Pool deve receber permissão para invocar o agent.

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 conecta todas as ações de invocação do AgentCore (InvokeAgentRuntime, InvokeAgentRuntimeWithWebSocketStream) no ARN de runtime do agent.

Se o seu agent usa autenticação Cognito, você não precisa definir nenhuma infraestrutura adicional para conectar seu website ao seu agent.

Instancie componentes CopilotKit com agentId para selecionar qual agente usar. O id é o nome do agente — o mesmo que você escolheu quando executou o gerador ts#agent ou py#agent — e você também pode encontrá-lo no arquivo de hook gerado (por exemplo, a chave retornada de packages/web/src/hooks/useAgui<AgentName>.tsx).

Importe os componentes de chat do módulo ./components/copilot gerado para que o tema que corresponde ao ux do seu site seja aplicado automaticamente:

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

Execute o gerador connection uma vez por agente. Cada agente registrado via AguiProvider compartilhado é visível de qualquer lugar no aplicativo — instancie um componente CopilotKit com um agentId diferente para rotear cada chat para o agente que você deseja:

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

<CopilotChat /> (e <CopilotSidebar />, <CopilotPopup />) usam um sistema de slots recursivo — você pode substituir qualquer subcomponente com uma string de classe Tailwind, um objeto de props ou um componente React personalizado. Veja o guia de slots do CopilotKit para a árvore completa de slots.

O gerador lê metadata.ux do seu projeto de site React e fornece um módulo wrapper temático em src/components/copilot/index.tsx para que os componentes de chat correspondam ao resto da sua UI sem nenhuma configuração extra:

uxEstilo aplicado a CopilotChat / CopilotSidebar / CopilotPopup
cloudscapeMensagens renderizadas dentro de ChatBubbles Cloudscape com Avatars gen-AI (correspondendo ao padrão de chat de IA generativa Cloudscape); o indicador de digitação se torna uma LoadingBar e a entrada é um PromptInput. Construído a partir de @cloudscape-design/components e @cloudscape-design/chat-components.
shadcnMensagens do assistente renderizadas em uma bolha bg-muted com um avatar Sparkles; mensagens do usuário renderizadas alinhadas à direita em uma bolha bg-primary com um avatar User. A entrada é um Textarea arredondado + Button de enviar/parar em forma de pílula (Enter envia, Shift+Enter nova linha). Usa primitivos shadcn do pacote compartilhado common-shadcn.
none (ou qualquer outra coisa)Sem tema — o módulo apenas re-exporta os componentes padrão do CopilotKit.

Importe os componentes temáticos do módulo de tema local (não diretamente de @copilotkit/react-core/v2) para que o tema seja aplicado automaticamente:

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

O tema é aplicado como padrões de slot, então qualquer slot que você passar explicitamente ainda prevalece — você mantém controle total sempre que precisar de uma substituição pontual.

O tema gerado vive inteiramente dentro do seu projeto:

  • src/components/copilot/index.tsx — exporta os CopilotChat / CopilotSidebar / CopilotPopup temáticos e os objetos cloudscapeCopilotTheme / shadcnCopilotTheme. Edite este arquivo para alterar a conexão de slot padrão para cada chat no seu aplicativo.
  • src/components/copilot/<ThemeComponent>.tsx — componentes de tema por slot (por exemplo, CloudscapeAssistantMessage, ShadcnChatInput). Edite estes para ajustar a aparência de um único slot sem reconectar o tema.

Por exemplo, para inserir seu próprio renderizador de mensagem de usuário mantendo o resto do tema, edite o arquivo relevante em src/components/copilot/ e re-exporte-o de index.tsx.

Substituições por chat ainda funcionam junto com o tema — qualquer coisa que você passar como prop de slot substitui o padrão 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',
}}
/>

Substituindo um slot com um componente personalizado

Seção intitulada “Substituindo um slot com um componente personalizado”

Qualquer slot pode receber um componente React em vez de um className, então você pode substituir o padrão inteiramente:

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

Substituições mais profundas seguem a mesma forma — por exemplo, substitua apenas o botão de copiar nas mensagens do assistente:

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

O gerador de conexão configura automaticamente a integração dev:

  1. Executar nx dev <website> também iniciará o servidor local do agente
  2. A configuração de runtime é substituída para apontar para a URL AG-UI local (por exemplo, http://localhost:8081)
  3. Tanto o site quanto o agente recarregam automaticamente juntos
Terminal window
pnpm nx dev <WebsiteProject>