React 连接到 AG-UI Agent
Nx Plugin for AWS 提供了一个生成器,用于将 React 网站连接到公开 AG-UI 协议的 Agent。它在您的网站上使用 @ag-ui/client HttpAgent 连接 CopilotKit,并支持 AWS IAM 和 Cognito 身份验证。
在使用此生成器之前,请确保您具备:
- 一个 React 网站(使用
ts#website生成器生成) - 一个带有
protocol=ag-ui的 TypeScript 或 Python Agent(使用ts#agent或py#agent生成器生成) - 对于已部署的 agent,需要通过
ts#website#auth生成器添加 Cognito Auth
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- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - connection - 填写必需参数
- 点击
Generate
系统将提示您选择 React 网站作为源项目,并选择包含 AG-UI Agent 的项目作为目标项目。如果您的目标项目包含多个组件(例如多个 agent 或其他组件类型),系统将提示您指定 targetComponent 以消除歧义。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| sourceProject 必需 | string | - | 源项目 |
| targetProject 必需 | string | - | 要连接到的目标项目 |
| sourceComponent | string | - | 要从其连接的源组件(组件名称、相对于源项目根目录的路径或生成器 ID)。使用 '.' 显式选择项目作为源。 |
| targetComponent | string | - | 要连接到的目标组件(组件名称、相对于目标项目根目录的路径或生成器 ID)。使用 '.' 显式选择项目作为目标。 |
| preferInstallDependencies | boolean | true | 是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。 |
生成器创建一个单一共享的 AguiProvider 组件、每个连接的 agent 一个 hook,以及一个用于 CopilotKit 聊天组件的主题包装器:
文件夹src
文件夹components
- AguiProvider.tsx 为每个 AG-UI agent 提供单一的
CopilotKitProvider。在第一次运行connection时创建,在后续运行时更新以注册每个新 agent。 文件夹copilot
- index.tsx 重新导出
CopilotChat、CopilotSidebar和CopilotPopup,并使用与您网站的ux(Cloudscape、Shadcn 或无主题)匹配的插槽默认值。 - ThemeComponents .tsx 每个插槽的主题组件(例如
CloudscapeAssistantMessage.tsx、ShadcnChatInput.tsx)。仅在ux为cloudscape或shadcn时提供。
- index.tsx 重新导出
- AguiProvider.tsx 为每个 AG-UI agent 提供单一的
文件夹hooks
- useAgui<AgentName>.tsx 注册一个 AG-UI agent。每次运行
connection生成一个文件。 - useSigV4.tsx SigV4 签名(仅限 IAM)
- useAgui<AgentName>.tsx 注册一个 AG-UI agent。每次运行
第二次为不同的 agent 运行 connection 会添加一个新的 useAgui<AgentName>.tsx hook 并更新 AguiProvider.tsx 以注册两个 hook——您对 provider 所做的任何自定义编辑都会被保留。main.tsx 保持其单一的 <AguiProvider> 包装器——您永远不会得到嵌套的 provider。
以下依赖项将添加到根 package.json:
@copilotkit/react-core— 提供CopilotKitProvider和聊天组件(CopilotChat、CopilotSidebar、CopilotPopup)@ag-ui/client— 生成的 hook 使用的HttpAgentaws4fetch、oidc-client-ts、react-oidc-context、@aws-sdk/credential-providers— 仅限 IAM 身份验证react-oidc-context— Cognito 身份验证
AG-UI 连接
Section titled “AG-UI 连接”每个 useAgui<AgentName> hook 从运行时配置读取其 agent 的运行时值,并实例化一个 @ag-ui/client HttpAgent:
- 已部署:运行时值是 Bedrock AgentCore Runtime ARN,它会被转换为 AgentCore HTTPS 端点:
https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/invocations?qualifier=DEFAULT - 本地开发:
dev将值覆盖为 agent 的本地 URL(例如http://localhost:8081)
共享的 AguiProvider 调用每个生成的 hook,并将每个 hook 展开到单个 CopilotKitProvider 的 selfManagedAgents 中,从而将它们全部公开给 CopilotKit 组件。
CopilotKit 集成
Section titled “CopilotKit 集成”CopilotKit 是 AG-UI 协议的第一方参考 React 客户端,并提供现成的聊天组件:
<CopilotChat />— 完整的聊天界面<CopilotSidebar />— 固定侧面板聊天<CopilotPopup />— 浮动聊天弹出窗口
将这些组件中的任何一个放置在 <AguiProvider> 包装器内的任何位置(已为您连接到 main.tsx 中)。
生成的代码根据您的 agent 配置处理身份验证:
- IAM(默认):使用 AWS SigV4 签名的 HTTP 请求。凭证从配置了您网站身份验证的 Cognito Identity Pool 获取。
- Cognito:将 JWT 访问令牌作为 Bearer 令牌嵌入到
Authorization标头中。
AG-UI 和 AgentCore Runtime 各自以不同的方式识别对话,生成的 hook 将它们联系在一起:
threadId— AG-UI 对话标识符,在请求正文中发送。除非您传递显式的threadId,否则 CopilotKit 会为每个聊天生成一个随机 UUID。- Session ID — AgentCore Runtime 会话,在
X-Amzn-Bedrock-AgentCore-Runtime-Session-Id标头中发送。它选择为请求提供服务的 microVM,并且是您的 agent 的session.ts/session.py用于键入对话状态的内容。
hook 从线程 ID 派生会话 ID,将其右填充到 AgentCore Runtime 所需的 33 个字符:
function agentCoreSessionId(input: RunAgentInput): string { return (input.threadId ?? '').padEnd(33, '0');}不设置 threadId 是最简单的——CopilotKit 生成的 UUID 已经是 36 个字符。如果您显式传递一个,请确保它至少有 33 个字符,因为填充会将仅在尾随字符上不同的线程 ID 映射到同一个会话。
Session ID 和 Thread ID 都由浏览器提供。要将每个用户限制为他们自己的对话,请参阅 py#agent 或 ts#agent 指南。
如果您的 agent 使用 IAM 身份验证,则必须授予 Cognito Identity Pool 的已认证角色调用该 agent 的权限。
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 会在 agent 的运行时 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}如果您的 agent 使用 Cognito 身份验证,则无需定义任何额外的基础设施即可将您的网站连接到您的 agent。
使用生成的代码
Section titled “使用生成的代码”添加聊天界面
Section titled “添加聊天界面”使用 agentId 实例化 CopilotKit 组件以选择要使用的 agent。该 id 是 agent 的名称——与您运行 ts#agent 或 py#agent 生成器时选择的名称相同——您也可以在生成的 hook 文件中找到它(例如从 packages/web/src/hooks/useAgui<AgentName>.tsx 返回的键)。
从生成的 ./components/copilot 模块导入聊天组件,以便自动应用与您网站的 ux 匹配的主题:
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 Agent
Section titled “连接多个 AG-UI Agent”每个 agent 运行一次 connection 生成器。通过共享的 AguiProvider 注册的每个 agent 在应用程序的任何位置都可见——使用不同的 agentId 实例化 CopilotKit 组件,以将每个聊天路由到您想要的 agent:
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.ux,并在 src/components/copilot/index.tsx 提供一个主题包装器模块,使聊天组件与您的 UI 的其余部分匹配,无需任何额外配置:
ux | 应用于 CopilotChat / CopilotSidebar / CopilotPopup 的样式 |
|---|---|
cloudscape | 消息在 Cloudscape ChatBubble 中渲染,带有生成式 AI Avatar(匹配 Cloudscape 生成式 AI 聊天模式);输入指示器变为 LoadingBar,输入为 PromptInput。由 @cloudscape-design/components 和 @cloudscape-design/chat-components 构建。 |
shadcn | 助手消息在 bg-muted 气泡中渲染,带有 Sparkles 头像;用户消息在 bg-primary 气泡中右对齐渲染,带有 User 头像。输入是圆角 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>, }, }}/>连接生成器会自动配置 dev 集成:
- 运行
nx dev <website>也会启动 agent 的本地服务器 - 运行时配置被覆盖以指向本地 AG-UI URL(例如
http://localhost:8081) - 网站和 agent 一起热重载
pnpm nx dev <WebsiteProject>yarn nx dev <WebsiteProject>npx nx dev <WebsiteProject>bunx nx dev <WebsiteProject>