跳转到内容

React 连接到 AG-UI Agent

Nx Plugin for AWS 提供了一个生成器,用于将 React 网站连接到公开 AG-UI 协议的 Strands Agent。它在您的网站上将 CopilotKit@ag-ui/client HttpAgent 连接起来,并支持 AWS IAM 和 Cognito 身份验证。

在使用此生成器之前,请确保您拥有:

  1. 一个 React 网站(使用 ts#react-website 生成器生成)
  2. 一个带有 protocol=AG-UI 的 Python Strands Agent(使用 py#strands-agent 生成器生成)
  3. 对于已部署的代理,通过 ts#react-website-auth 生成器添加 Cognito Auth
  1. 安装 Nx Console VSCode Plugin 如果您尚未安装
  2. 在VSCode中打开Nx控制台
  3. 点击 Generate (UI) 在"Common Nx Commands"部分
  4. 搜索 @aws/nx-plugin - connection
  5. 填写必需参数
    • 点击 Generate

    系统将提示您选择 React 网站作为源项目,并选择包含 AG-UI Strands Agent 的项目作为目标项目。如果您的目标项目包含多个组件(例如多个代理或其他组件类型),系统将提示您指定 targetComponent 以消除歧义。

    参数 类型 默认值 描述
    sourceProject 必需 string - 源项目
    targetProject 必需 string - 要连接到的目标项目
    sourceComponent string - 要从其连接的源组件(组件名称、相对于源项目根目录的路径或生成器 ID)。使用 '.' 显式选择项目作为源。
    targetComponent string - 要连接到的目标组件(组件名称、相对于目标项目根目录的路径或生成器 ID)。使用 '.' 显式选择项目作为目标。

    生成器创建一个单一共享的 AguiProvider 组件和每个连接的代理一个钩子:

    • 文件夹src
      • 文件夹components
        • AguiProvider.tsx 为每个 AG-UI 代理提供单一的 CopilotKitProvider。在第一次运行 connection 时创建,并在后续运行时更新以注册每个新代理。
      • 文件夹hooks
        • useAgui<AgentName>.tsx 注册一个 AG-UI 代理。每次运行 connection 生成一个文件。
        • useSigV4.tsx SigV4 签名(仅 IAM)

    第二次为不同的代理运行 connection添加一个新的 useAgui<AgentName>.tsx 钩子并更新 AguiProvider.tsx 以注册两个钩子——您对提供者所做的任何自定义编辑都会被保留。main.tsx 保持其单一的 <AguiProvider> 包装器——您永远不会出现嵌套的提供者。

    以下依赖项被添加到根 package.json

    • @copilotkit/react-core — 提供 CopilotKitProvider 和聊天组件(CopilotChatCopilotSidebarCopilotPopup
    • @ag-ui/client — 生成的钩子使用的 HttpAgent
    • aws4fetchoidc-client-tsreact-oidc-context@aws-sdk/credential-providers — 仅 IAM 身份验证
    • react-oidc-context — Cognito 身份验证

    每个 useAgui<AgentName> 钩子从运行时配置读取其代理的运行时值,并实例化一个 @ag-ui/client HttpAgent

    • 已部署:运行时值是 Bedrock AgentCore Runtime ARN,它被转换为 AgentCore HTTPS 端点:https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/invocations?qualifier=DEFAULT
    • 本地开发serve-local 将该值覆盖为代理的本地 URL(例如 http://localhost:8081

    共享的 AguiProvider 调用每个生成的钩子,并将每个钩子展开到单个 CopilotKitProviderselfManagedAgents 中,从而将它们全部暴露给 CopilotKit 组件。

    CopilotKit 是 AG-UI 协议的第一方参考 React 客户端,并提供现成的聊天组件:

    • <CopilotChat /> — 完整的聊天界面
    • <CopilotSidebar /> — 固定侧面板聊天
    • <CopilotPopup /> — 浮动聊天弹窗

    将这些组件中的任何一个放置在 <AguiProvider> 包装器内的任何位置(已为您连接到 main.tsx)。

    生成的代码根据您的代理配置处理身份验证:

    • IAM(默认):使用 AWS SigV4 签名的 HTTP 请求。凭证从配置了您网站身份验证的 Cognito Identity Pool 获取。
    • Cognito:将 JWT 访问令牌作为 Bearer 令牌嵌入 Authorization 标头中。

    如果您的代理使用 IAM 身份验证,则必须授予 Cognito Identity Pool 的已认证角色调用代理的权限。

    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 会在代理的运行时 ARN 上连接所有 AgentCore 调用操作(InvokeAgentRuntimeInvokeAgentRuntimeWithWebSocketStream)。

    如果您的代理使用 Cognito 身份验证,则无需定义任何额外的基础设施来将您的网站连接到您的代理。

    使用 agentId 实例化 CopilotKit 组件以选择要使用的代理。该 id 是代理的名称——与您运行 py#strands-agent 生成器时选择的名称相同——您也可以在生成的钩子文件中找到它(例如从 packages/web/src/hooks/useAgui<AgentName>.tsx 返回的键):

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

    为每个代理运行一次 connection 生成器。通过共享的 AguiProvider 注册的每个代理都可以从应用程序的任何地方看到——使用不同的 agentId 实例化 CopilotKit 组件,将每个聊天路由到您想要的代理:

    <CopilotChat agentId="story" /> {/* talks to StoryAgent */}
    <CopilotChat agentId="research" /> {/* talks to ResearchAgent */}

    <CopilotChat />(以及 <CopilotSidebar /><CopilotPopup />)使用递归的插槽系统——您可以使用 Tailwind 类字符串、prop 对象或自定义 React 组件覆盖任何子组件。请参阅 CopilotKit 插槽指南了解完整的插槽树。

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

    任何插槽都可以接受 React 组件而不是 className,因此您可以完全替换默认值:

    import { CopilotChat } from '@copilotkit/react-core/v2';
    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>,
    },
    }}
    />

    连接生成器自动配置 serve-local 集成:

    1. 运行 nx serve-local <website> 也会启动代理的本地服务器
    2. 运行时配置被覆盖以指向本地 AG-UI URL(例如 http://localhost:8081
    3. 网站和代理一起热重载
    Terminal window
    pnpm nx serve-local <WebsiteProject>