React 连接到 AG-UI Agent
Nx Plugin for AWS 提供了一个生成器,用于将 React 网站连接到公开 AG-UI 协议的 Strands Agent。它在您的网站上将 CopilotKit 与 @ag-ui/client HttpAgent 连接起来,并支持 AWS IAM 和 Cognito 身份验证。
在使用此生成器之前,请确保您拥有:
- 一个 React 网站(使用
ts#react-website生成器生成) - 一个带有
protocol=AG-UI的 Python Strands Agent(使用py#strands-agent生成器生成) - 对于已部署的代理,通过
ts#react-website-auth生成器添加 Cognito Auth
- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - connection - 填写必需参数
- 点击
Generate
pnpm nx g @aws/nx-plugin:connectionyarn nx g @aws/nx-plugin:connectionnpx nx g @aws/nx-plugin:connectionbunx nx g @aws/nx-plugin:connection系统将提示您选择 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时创建,并在后续运行时更新以注册每个新代理。
- AguiProvider.tsx 为每个 AG-UI 代理提供单一的
文件夹hooks
- useAgui<AgentName>.tsx 注册一个 AG-UI 代理。每次运行
connection生成一个文件。 - useSigV4.tsx SigV4 签名(仅 IAM)
- useAgui<AgentName>.tsx 注册一个 AG-UI 代理。每次运行
第二次为不同的代理运行 connection 会添加一个新的 useAgui<AgentName>.tsx 钩子并更新 AguiProvider.tsx 以注册两个钩子——您对提供者所做的任何自定义编辑都会被保留。main.tsx 保持其单一的 <AguiProvider> 包装器——您永远不会出现嵌套的提供者。
以下依赖项被添加到根 package.json:
@copilotkit/react-core— 提供CopilotKitProvider和聊天组件(CopilotChat、CopilotSidebar、CopilotPopup)@ag-ui/client— 生成的钩子使用的HttpAgentaws4fetch、oidc-client-ts、react-oidc-context、@aws-sdk/credential-providers— 仅 IAM 身份验证react-oidc-context— Cognito 身份验证
AG-UI 连接
Section titled “AG-UI 连接”每个 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 调用每个生成的钩子,并将每个钩子展开到单个 CopilotKitProvider 的 selfManagedAgents 中,从而将它们全部暴露给 CopilotKit 组件。
CopilotKit 集成
Section titled “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 的已认证角色调用代理的权限。
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 会在代理的运行时 ARN 上连接所有 AgentCore 调用操作(InvokeAgentRuntime、InvokeAgentRuntimeWithWebSocketStream)。
module "identity" { source = "../../common/terraform/src/core/user-identity"}
module "my_agent" { source = "../../common/terraform/src/app/agents/my-agent"}
# 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}如果您的代理使用 Cognito 身份验证,则无需定义任何额外的基础设施来将您的网站连接到您的代理。
使用生成的代码
Section titled “使用生成的代码”添加聊天界面
Section titled “添加聊天界面”使用 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...', }} /> );}连接多个 AG-UI 代理
Section titled “连接多个 AG-UI 代理”为每个代理运行一次 connection 生成器。通过共享的 AguiProvider 注册的每个代理都可以从应用程序的任何地方看到——使用不同的 agentId 实例化 CopilotKit 组件,将每个聊天路由到您想要的代理:
<CopilotChat agentId="story" /> {/* talks to StoryAgent */}<CopilotChat agentId="research" /> {/* talks to ResearchAgent */}自定义外观和感觉
Section titled “自定义外观和感觉”<CopilotChat />(以及 <CopilotSidebar />、<CopilotPopup />)使用递归的插槽系统——您可以使用 Tailwind 类字符串、prop 对象或自定义 React 组件覆盖任何子组件。请参阅 CopilotKit 插槽指南了解完整的插槽树。
通过插槽进行 Tailwind 样式设置
Section titled “通过插槽进行 Tailwind 样式设置”<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', }}/>用自定义组件替换插槽
Section titled “用自定义组件替换插槽”任何插槽都可以接受 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 集成:
- 运行
nx serve-local <website>也会启动代理的本地服务器 - 运行时配置被覆盖以指向本地 AG-UI URL(例如
http://localhost:8081) - 网站和代理一起热重载
pnpm nx serve-local <WebsiteProject>yarn nx serve-local <WebsiteProject>npx nx serve-local <WebsiteProject>bunx nx serve-local <WebsiteProject>