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 组件、每个连接的代理一个钩子,以及 CopilotKit 聊天组件的主题化包装器:
文件夹src
文件夹components
- AguiProvider.tsx 为每个 AG-UI 代理提供单一的
CopilotKitProvider。在第一次运行connection时创建,并在后续运行时更新以注册每个新代理。 文件夹copilot
- index.tsx 重新导出
CopilotChat、CopilotSidebar和CopilotPopup,并带有与您网站的uxProvider(Cloudscape、Shadcn 或无主题)匹配的插槽默认值。 - ThemeComponents .tsx 每个插槽的主题组件(例如
CloudscapeAssistantMessage.tsx、ShadcnChatInput.tsx)。仅在uxProvider为Cloudscape或Shadcn时提供。
- index.tsx 重新导出
- 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"
appconfig_application_id = module.runtime_config_appconfig.application_id appconfig_application_arn = module.runtime_config_appconfig.application_arn}
# 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 返回的键)。
从生成的 ./components/copilot 模块导入聊天组件,这样与您网站的 uxProvider 匹配的主题会自动应用:
import { CopilotChat } from './components/copilot';
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 组件,将每个聊天路由到您想要的代理:
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="story" /> {/* talks to StoryAgent */}<CopilotChat agentId="research" /> {/* talks to ResearchAgent */}自定义外观和感觉
Section titled “自定义外观和感觉”<CopilotChat />(以及 <CopilotSidebar />、<CopilotPopup />)使用递归的插槽系统——您可以使用 Tailwind 类字符串、prop 对象或自定义 React 组件覆盖任何子组件。请参阅 CopilotKit 插槽指南了解完整的插槽树。
生成器从您的 React 网站项目读取 metadata.uxProvider,并在 src/components/copilot/index.tsx 提供一个主题化包装器模块,使聊天组件与您 UI 的其余部分匹配,无需任何额外配置:
uxProvider | 应用于 CopilotChat / CopilotSidebar / CopilotPopup 的样式 |
|---|---|
Cloudscape | 消息在带有生成式 AI Avatar 的 Cloudscape ChatBubble 内渲染(匹配 Cloudscape 生成式 AI 聊天模式);输入指示器变为 LoadingBar,输入框是 PromptInput。基于 @cloudscape-design/components 和 @cloudscape-design/chat-components 构建。 |
Shadcn | 助手消息在带有 Sparkles 头像的 bg-muted 气泡中渲染;用户消息右对齐在带有 User 头像的 bg-primary 气泡中渲染。输入框是圆角 Textarea + 药丸形发送/停止 Button(Enter 提交,Shift+Enter 换行)。使用来自共享 common-shadcn 包的 shadcn 原语。 |
None(或其他任何值) | 无主题——模块仅重新导出默认的 CopilotKit 组件。 |
从本地主题模块导入主题化组件(而不是直接从 @copilotkit/react-core/v2 导入),这样主题会自动应用:
import { CopilotChat } from './components/copilot';
<CopilotChat agentId="agent" />主题作为插槽默认值应用,因此您显式传递的任何插槽仍然优先——当您需要一次性覆盖时,您保持完全控制。
生成的主题完全存在于您的项目中:
src/components/copilot/index.tsx— 导出主题化的CopilotChat/CopilotSidebar/CopilotPopup以及cloudscapeCopilotTheme/shadcnCopilotTheme对象。编辑此文件以更改应用中每个聊天的默认插槽连接。src/components/copilot/<ThemeComponent>.tsx— 每个插槽的主题组件(例如CloudscapeAssistantMessage、ShadcnChatInput)。编辑这些文件以调整单个插槽的外观,而无需重新连接主题。
例如,要在保持主题其余部分的同时使用您自己的用户消息渲染器,请编辑 src/components/copilot/ 中的相关文件并从 index.tsx 重新导出它。
通过插槽进行 Tailwind 样式设置
Section titled “通过插槽进行 Tailwind 样式设置”每个聊天的覆盖仍然与主题一起工作——您作为插槽 prop 传递的任何内容都会覆盖主题化的默认值:
<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 './components/copilot';
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>