使用 AG-UI,只需 30 分钟即可轻松为您的 AWS Strands 代理构建前端
太长不看
本指南将介绍如何使用 AG-UI 协议和 CopilotKit 为 AWS Strands 代理构建前端。AWS Strands 将为 AI 代理后端提供支持,CopilotKit 将为前端提供支持,而 AG-UI 则创建一个桥梁,使前端能够与后端通信。
顺便提一下,这个集成是由CopilotKit / AG-UI 社区的Umar Majeed构建的,AWS 则进行了最后的润色。
在正式开始之前,我们先来看看我们将要涵盖的内容:
-
什么是AWS Strands?
-
使用 CLI 设置 AWS Strands + AG-UI + CopilotKit 代理
-
将您的 AWS Strands 代理与后端 AG-UI 协议集成
-
使用 CopilotKit 为您的 AWS Strands + AG-UI 代理构建前端
以下是使用 AWS Strands + AG-UI + CopilotKit 可以构建的内容预览。
什么是AWS Strands?
AWS Strands,也称为 Strands Agents,是由 AWS 团队开发的开源代理开发框架,用于构建和部署 AI 代理。
该框架采用模型驱动的方法,利用模型推理来规划、协调任务并反思目标。
此外,Strands 与模型无关,支持各种 LLM 提供商,包括 Amazon Bedrock、Anthropic、OpenAI、Meta Llama 以及通过 Ollama 或 LiteLLM 提供的本地模型。
以下是 AWS Strands 的主要特性和功能:
-
工具集成:它提供了集成自定义工具的简单机制,并原生支持模型上下文协议 (MCP),使代理能够访问庞大的第三方工具生态系统。
-
多智能体系统: Strands 简化了多个专业智能体协作完成复杂任务的复杂系统的创建。
-
可观测性:它包含用于可观测性的原生功能,例如跟踪、指标和日志,这些对于调试和监控代理性能至关重要。
您可以访问Strands Agents 文档,了解有关 AWS Strands 的更多信息。
先决条件
-
Node.js 20+
-
Python 3.12+
-
OpenAI API 密钥(用于 Strands 代理)
-
以下任何一种软件包管理器:
- pnpm(推荐)
- npm
- 纱
- 包子
使用 CLI 设置 AWS Strands + AG-UI + CopilotKit 代理
在本节中,您将学习如何使用 CLI 命令设置全栈 AWS Strands 代理,该命令使用 AG-UI 协议设置后端,使用 CopilotKit 设置前端。
我们开始吧。
步骤 1:运行 CLI 命令
如果您还没有 AWS Strands 代理,可以通过在终端中运行以下 CLI 命令快速设置一个。
npx copilotkit@latest create -f aws-strands-py
然后按照下面的示例给你的项目命名。
步骤 2:安装依赖项
项目创建成功后,请使用您首选的包管理器安装依赖项:
# Using pnpm (recommended)
pnpm install
# Using npm
npm install
# Using yarn
yarn install
# Using bun
bun install
步骤 3:设置您的 OpenAI 密钥
安装完依赖项后,在根文件夹中创建一个 .env 文件,并添加您的 OpenAI API 密钥。
OPENAI_API_KEY="your-open-api-key-here”
步骤 4:运行开发服务器
然后使用您首选的包管理器启动开发服务器:
# Using pnpm
pnpm dev
# Using npm
npm run dev
# Using yarn
yarn dev
# Using bun
bun run dev
开发服务器运行后,访问http://localhost:3000/,您应该可以看到您的 AWS Strands + AG-UI + CopilotKit 代理已启动并运行。
恭喜!您已成功设置全栈式 AWS Strands 代理。您的 AI 代理现在可以使用了!您可以尝试使用聊天中的建议来测试集成效果。
将您的 AWS Strands 代理与后端 AG-UI 协议集成
在本节中,您将学习如何将 AWS Strands 代理与 AG-UI 协议集成,以便将其暴露给前端。
让我们开始吧。
步骤 1:安装 AWS Strands + AG-UI 软件包
首先,请使用以下命令安装 AWS Strands + AG-UI 软件包以及其他必要的依赖项。
uv pip install ag-ui-protocol strands-agents[OpenAI] strands-agents-tools ag_ui_strands
步骤 2:导入所需软件包
安装完所需的软件包后,按照以下示例将其导入到main.py文件中。
# AG-UI / Strands integration helpers:
# - StrandsAgent: Wrapper that makes a Strands Agent compatible with AG-UI protocol
# - StrandsAgentConfig: Configuration for shared state and tool behaviors
# - ToolBehavior: Defines how specific tools interact with the AG-UI state system
# - create_strands_app: Factory function that creates a FastAPI application
from ag_ui_strands import (
StrandsAgent,
StrandsAgentConfig,
ToolBehavior,
create_strands_app,
)
# dotenv: Loads environment variables from a .env file for local development
from dotenv import load_dotenv
# Pydantic: Used for data validation and schema definition
from pydantic import BaseModel, Field
# Strands SDK:
# - Agent: The core agent class that orchestrates LLM interactions
# - tool: Decorator to mark functions as tools the agent can call
from strands import Agent, tool
# OpenAI model wrapper from Strands for using GPT models
from strands.models.openai import OpenAIModel
// ...
步骤 3:定义 AWS Strands 代理数据模型
导入所需软件包后,定义 Pydantic 模型进行结构化数据验证,以确保工具输入在处理之前得到充分验证,如下所示。
# Pydantic: Used for data validation and schema definition
from pydantic import BaseModel, Field
// ...
class ProverbsList(BaseModel):
"""Pydantic model representing the entire proverbs list.
We use a dedicated model to validate tool inputs for `update_proverbs`.
The `proverbs` field is a list of strings describing the stored proverbs.
"""
# The proverbs field is a list of strings with a description for the LLM
proverbs: List[str] = Field(description="The complete list of proverbs")
// ...
步骤 4:定义您的 AWS Strands 代理工具
定义好代理数据模型后,定义代理工具,并使用 @tool 进行修饰,以便将其注册到 Strands 框架中,如下所示。
// ...
@tool
def get_weather(location: str):
"""Backend tool example: returns weather information for a location.
This is a simple synchronous tool demonstrating a backend operation. In a
real app this would call an external weather API. Here it returns a JSON
string for simplicity so agents and UI can display structured data.
Args:
location: The location to get weather for (e.g., "Seattle, WA")
Returns:
A JSON string containing weather information.
"""
# Return a JSON-encoded placeholder response
# In production, this would call an actual weather API like OpenWeatherMap
return json.dumps({"location": "70 degrees"})
@tool
def set_theme_color(theme_color: str):
"""Frontend-only tool example: request a UI theme color change.
Frontend tools are declared on the backend so the agent can request UI
actions, but actual execution happens in the browser via a frontend
integration (e.g., `useFrontendTool`). Because the frontend performs the
action, this backend implementation returns `None`.
Args:
theme_color: CSS color (hex, name, or rgb) that the UI should apply
"""
# Return None because the actual implementation is in the frontend
# The frontend will intercept this tool call and apply the theme change
return None
@tool
def update_proverbs(proverbs_list: ProverbsList):
"""Backend tool: replace the entire proverbs list.
IMPORTANT: This tool expects the complete list of proverbs, not just
additions. When the UI or user wants to modify the list, always send the
full array so the backend can store a canonical snapshot.
Args:
proverbs_list: A validated `ProverbsList` instance containing the
complete array of proverbs.
Returns:
A success message string on completion.
"""
# In a real app, this would persist to a DB. Here we return success.
# The state synchronization happens via the ToolBehavior config below.
return "Proverbs updated successfully."
// ...
第五步:定义状态管理功能
定义好代理工具后,配置状态管理功能以处理代理和 UI 之间的状态同步,如下所示。
// ...
def build_proverbs_prompt(input_data, user_message: str) -> str:
"""Build a model prompt that includes the current proverbs state.
When the agent composes messages for the model, we inject the current
`proverbs` array into the prompt so the model can reference or modify it.
This function acts as a "state context builder" - it takes the current
shared state and incorporates it into the prompt sent to the LLM.
Args:
input_data: The shared state container (may include a `state` key)
user_message: The user's raw request/message
Returns:
The combined prompt string includes proverbs when available.
"""
# Step 5a: Try to extract the state dictionary from input_data
state_dict = getattr(input_data, "state", None)
# Step 5b: Check if we have a valid state with proverbs
if isinstance(state_dict, dict) and "proverbs" in state_dict:
# Step 5c: Pretty-print the proverbs array for the model to read easily
# Using indent=2 makes the JSON human-readable in the prompt
proverbs_json = json.dumps(state_dict["proverbs"], indent=2)
# Step 5d: Combine the proverbs context with the user message
return (
f"Current proverbs list:\n{proverbs_json}\n\nUser request: {user_message}"
)
# Step 5e: Fall back to the plain user message if no proverbs state is available
return user_message
async def proverbs_state_from_args(context):
"""Extract a `{'proverbs': [...]}` snapshot from tool arguments.
This function is used by the shared state system when the `update_proverbs`
tool runs. It inspects the tool input and returns a small dictionary
containing only the `proverbs` array so AG-UI can update its local state.
This is an async function because AG-UI's state handling may involve
async operations in more complex scenarios.
Args:
context: ToolResultContext containing `tool_input` (string or dict)
Returns:
A dictionary like `{"proverbs": [...]}` or `None` on error.
"""
try:
# Step 5f: Get the raw tool input from the context
tool_input = context.tool_input
# Step 5g: If the tool input was serialized to a string, parse it back
# This handles cases where the LLM sends the input as a JSON string
if isinstance(tool_input, str):
tool_input = json.loads(tool_input)
# Step 5h: Some call sites may package the list under `proverbs_list` key
# This provides flexibility in how the data is structured
proverbs_data = tool_input.get("proverbs_list", tool_input)
# Step 5i: Ensure we extract the array safely with proper type checking
if isinstance(proverbs_data, dict):
proverbs_array = proverbs_data.get("proverbs", [])
else:
proverbs_array = []
# Step 5j: Return the state snapshot in the expected format
return {"proverbs": proverbs_array}
except Exception:
# Step 5k: Return None to indicate we couldn't build a valid state snapshot
# AG-UI will handle this gracefully and not update the state
return None
// ...
步骤 6:配置代理和用户界面之间的共享状态
定义状态管理功能后,使用您之前定义的 AG-UI 类和状态管理功能,配置 AWS Strands 代理和 UI 如何共享状态以及针对特定工具的行为StrandsAgentConfig,如下所示。
// ...
shared_state_config = StrandsAgentConfig(
# Step 6a: Inject proverbs into the prompt using the builder function above
# This ensures the LLM always has context about the current proverbs list
state_context_builder=build_proverbs_prompt,
# Step 6b: Define tool-specific behaviors for AG-UI integration
# This dictionary maps tool names to their ToolBehavior configurations
tool_behaviors={
"update_proverbs": ToolBehavior(
# Step 6c: Skip messages snapshot to avoid redundant state updates
# When this is True, the tool result won't trigger a full message sync
skip_messages_snapshot=True,
# Step 6d: Use our custom state extractor function
# This tells AG-UI how to extract state changes from tool arguments
state_from_args=proverbs_state_from_args,
)
},
)
// ...
步骤 7:配置 AWS Strands 代理
配置共享状态后,首先使用 OpenAI API 密钥初始化 OpenAI 模型,然后配置 AWS Strands 代理,如下所示。
// ...
# Step 7a: Retrieve the OpenAI API key from environment variables
# Default to empty string if not set (will cause authentication errors)
api_key = os.getenv("OPENAI_API_KEY", "")
# Step 7b: Create the OpenAI model instance with configuration
model = OpenAIModel(
# Pass API key through client_args for the underlying OpenAI client
client_args={"api_key": api_key},
# Use GPT-4o (the optimized version); change as appropriate for your account
model_id="gpt-4o",
)
// ...
然后定义系统提示,以设置代理的角色和行为,如下所示。
// ...
system_prompt = (
"You are a helpful and wise assistant who helps manage a collection of proverbs."
)
// ...
Agent最后,使用模型和声明的工具创建 Strands ,如下所示。
// ...
strands_agent = Agent(
model=model, # The LLM to use
system_prompt=system_prompt, # Agent's persona
tools=[update_proverbs, get_weather, set_theme_color], # Available tools
)
// ...
步骤 8:将 AWS Strands 代理与 AG-UI 协议集成
配置好 AWS Strands 代理后,使用 AG-UI 的 StrandsAgent 包装器将其与 AG-UI 协议集成,如下所示。
// ...
# Step 9a: Create a StrandsAgent wrapper that adds AG-UI capabilities
agui_agent = StrandsAgent(
agent=strands_agent, # The underlying Strands agent
name="proverbs_agent", # Unique identifier for this agent
description="A proverbs assistant that collaborates with you to manage proverbs",
config=shared_state_config, # Shared state and tool behavior configuration
)
// ...
步骤 9:创建 FastAPI 服务器
将 AWS Strands 代理与 AG-UI 协议集成后,使用 AG-UI 工厂函数创建一个 FastAPI 服务器,将 Strands + AG-UI 代理暴露给前端,如下所示。
// ...
app = create_strands_app(agui_agent, "/")
if __name__ == "__main__":
# Step 11a: Import uvicorn ASGI server (only needed when running directly)
import uvicorn
# Step 11b: Start the development server with auto-reload enabled
# - "main:app": Module and app variable reference for uvicorn
# - host="0.0.0.0": Listen on all network interfaces
# - port=8000: Default HTTP port for development
# - reload=True: Auto-restart on code changes (development mode)
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
恭喜!您已成功将 Python AWS Strands Agent 与 AG-UI 协议集成,并且可通过http://localhost:8000(或指定端口)端点访问。
现在让我们看看如何为 AG-UI 封装的 AWS Strands 代理添加前端。
使用 CopilotKit 为您的 AWS Strands + AG-UI 代理构建前端
在本节中,您将学习如何使用 CopilotKit 为您的 AWS Strands + AG-UI 代理添加前端,CopilotKit 可以在 React 运行的任何地方运行。
我们开始吧。
步骤 1:安装 CopilotKit 软件包
首先,请在前端安装最新的 CopilotKit 软件包。
npm install @copilotkit/react-ui @copilotkit/react-core @copilotkit/runtime @ag-ui/client
步骤 2:设置 Copilot 运行时实例
安装 CopilotKit 软件包后,使用/api/copilotkitAPI 路由中的 HttpAgent 示例设置 Copilot 运行时实例,以使前端能够向后端发出 HTTP 请求。
import {
CopilotRuntime,
ExperimentalEmptyAdapter,
copilotRuntimeNextJSAppRouterEndpoint,
} from "@copilotkit/runtime";
import { HttpAgent } from "@ag-ui/client";
import { NextRequest } from "next/server";
// 1. You can use any service adapter here for multi-agent support. We use
// the empty adapter since we're only using one agent.
const serviceAdapter = new ExperimentalEmptyAdapter();
// 2. Create the CopilotRuntime instance and utilize the Strands AG-UI
// integration to set up the connection.
const runtime = new CopilotRuntime({
agents: {
// Our FastAPI endpoint URL
strands_agent: new HttpAgent({ url: "http://localhost:8000" }),
},
});
// 3. Build a Next.js API route to handle CopilotKit runtime requests.
export const POST = async (req: NextRequest) => {
const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
runtime,
serviceAdapter,
endpoint: "/api/copilotkit",
});
return handleRequest(req);
};
步骤 3:设置 CopilotKit 提供程序
设置好 Copilot Runtime 实例后,设置管理 ADK 代理会话的 CopilotKit 提供程序组件。
要设置 CopilotKit 提供程序, 组件必须封装应用程序中支持 Copilot 的部分。
对于大多数使用场景,最好将 CopilotKit 提供程序包装在整个应用程序周围,例如,在您的 layout.tsx文件中。
// Step 1: Import necessary types and components from Next.js and CopilotKit
import type { Metadata } from "next";
import { CopilotKit } from "@copilotkit/react-core";
import "./globals.css";
import "@copilotkit/react-ui/styles.css";
// Step 2: Define metadata for the application, used by Next.js for SEO and page headers
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
// Step 3: Define the RootLayout component, which wraps the entire application
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
// Step 4: Return the JSX structure for the layout
return (
<html lang="en">
<body className={"antialiased"}>
{/* Step 5: Wrap the children components with CopilotKit provider to enable CopilotKit functionality */}
<CopilotKit runtimeUrl="/api/copilotkit" agent="strands_agent">
{children}
</CopilotKit>
</body>
</html>
);
}
步骤 4:设置 Copilot UI 组件
设置好 CopilotKit 提供程序后,添加一个 Copilot UI 组件以启用与 ADK 代理的交互。CopilotKit 附带几个内置聊天组件,包括CopilotPopup、 CopilotSidebar和CopilotChat。
要设置 Copilot UI 组件,请将其与核心页面组件一起定义,例如,在您的 page.tsx 文件中。
"use client";
import { CopilotKitCSSProperties, CopilotSidebar } from "@copilotkit/react-ui";
import { useState } from "react";
export default function CopilotKitPage() {
// ...
return (
<main
// Step 2d-i: Apply theme color as a CSS custom property
// CopilotKit components read this variable to style their elements
style={
{ "--copilot-kit-primary-color": themeColor } as CopilotKitCSSProperties
}
>
{/* Step 2d-ii: CopilotSidebar provides the chat interface */}
<CopilotSidebar
// Step 2d-iii: Configuration options for the sidebar behavior
clickOutsideToClose={false} // Keep sidebar open when clicking outside
defaultOpen={true} // Start with sidebar visible
// Step 2d-iv: Labels customize the sidebar header and welcome message
labels={{
title: "Popup Assistant",
initial: "👋 Hi, there! You're chatting with a Strands agent.",
}}
// Step 2d-v: Suggestions provide quick-action buttons for users
// Each suggestion sends a predefined message when clicked
suggestions={[
{
title: "Generative UI",
message: "What's the weather in San Francisco?",
},
{
title: "Frontend Tools",
message: "Set the theme to green.",
},
{
title: "Writing Agent State",
message: "Add a proverb about AI.",
},
]}
>
{/* Step 2d-vi: Child content is pushed to the side by the sidebar */}
<YourMainContent themeColor={themeColor} />
</CopilotSidebar>
</main>
);
}
步骤 5:将您的 AWS Strands + AG-UI 代理状态与前端同步
设置好 Copilot UI 组件后,使用 CopilotKit 钩子将 AWS Strands + AG-UI 代理状态与前端同步。
要将 AWS Strands + AG-UI 代理状态与前端同步,请使用 CopilotKit useCoAgent 钩子, 该钩子允许您在应用程序和代理之间双向共享状态。
"use client";
import { useCoAgent } from "@copilotkit/react-core";
function YourMainContent({ themeColor }: { themeColor: string }) {
// 🪁 Shared State: https://docs.copilotkit.ai/coagents/shared-state
const { state, setState } = useCoAgent({
// Agent name must match the CopilotKit Provider StrandsAgent name
name: "strands_agent",
initialState: {
proverbs: [
"CopilotKit may be new, but it's the best thing since sliced bread.",
],
},
})
// ...
return (
// ...
)
步骤 6:渲染您的 AWS Strands + AG-UI 代理工具调用
将代理状态与前端同步后,使用 CopilotKit 的 [useRenderToolCall](https://docs.copilotkit.ai/reference/hooks/useRenderToolCall) 钩子,通过自定义 UI 组件渲染代理的工具调用,以便向用户提供有关代理正在执行的操作的反馈,特别是代理何时调用工具,如下所示。
"use client";
import {
useDefaultTool,
useRenderToolCall,
} from "@copilotkit/react-core";
// ...
function YourMainContent({ themeColor }: { themeColor: string }) {
// -------------------------------------------------------------------------
// Step 3c: Generative UI for Weather Tool
// -------------------------------------------------------------------------
// 🪁 Generative UI: https://docs.copilotkit.ai/strands/generative-ui/backend-tools
//
// This hook tells CopilotKit how to render the "get_weather" tool call.
// Instead of showing raw JSON, it displays a custom WeatherCard component.
useRenderToolCall(
{
// Step 3c-i: Tool name to intercept for custom rendering
name: "get_weather",
// Step 3c-ii: Parameter schema (for documentation/type checking)
parameters: [
{
name: "location",
description: "The location to get the weather for.",
required: true,
},
],
// Step 3c-iii: Render function called when this tool is executed
// Returns a React component that displays the tool result visually
render: (props) => (
<WeatherCard themeColor={themeColor} location={props.args.location} />
),
},
// Step 3c-iv: Dependency array - re-creates the render when themeColor changes
[themeColor],
);
// -------------------------------------------------------------------------
// Step 3d: Default Generative UI (Fallback Renderer)
// -------------------------------------------------------------------------
// 🪁 Default Generative UI: https://docs.copilotkit.ai/strands/generative-ui/backend-tools
//
// This hook provides a fallback UI for any tool that doesn't have a
// specific useRenderToolCall defined. It ensures all tools have some
// visual representation in the chat.
useDefaultTool(
{
// Step 3d-i: Default render function receives all tool props
render: (props) => (
<DefaultToolComponent themeColor={themeColor} {...props} />
),
},
// Step 3d-ii: Dependency array for re-render on theme changes
[themeColor],
);
return (
// ...
);
}
然后尝试向客服询问某个地点的天气。您应该会看到我们添加的自定义 UI 组件,该组件会渲染get weather工具调用并显示传递给工具的参数。
步骤 7:声明前端工具
在渲染完代理的工具调用后,您可以使用 CopilotKit 的[useFrontendTool](https://docs.copilotkit.ai/reference/hooks/useFrontendTool)钩子声明前端工具,代理可以调用这些工具与客户端原语进行交互,例如:
-
读取或修改 React 组件状态
-
访问浏览器 API,例如 localStorage、sessionStorage 或 cookie
-
触发用户界面更新或动画
-
与第三方前端库交互
-
执行需要用户直接访问浏览器上下文的操作
您可以声明前端工具并在 AWS Strands 代理中使用它们,如下所示。
"use client";
import {
useFrontendTool,
} from "@copilotkit/react-core";
export default function CopilotKitPage() {
// -------------------------------------------------------------------------
// Step 2a: Local State for Theme Color
// -------------------------------------------------------------------------
// Initialize with a default indigo color. This state will be updated
// when the agent calls the "set_theme_color" frontend tool.
const [themeColor, setThemeColor] = useState("#6366f1");
// Step 2b: Debug Effect - logs theme color changes to console
useEffect(() => {
console.log(themeColor);
}, [themeColor]);
// -------------------------------------------------------------------------
// Step 2c: Frontend Tool Declaration
// -------------------------------------------------------------------------
// 🪁 Frontend Actions: https://docs.copilotkit.ai/guides/frontend-actions
//
// This hook declares a tool that the agent can call, but the execution
// happens here in the browser (not on the backend server).
//
// When the backend agent calls "set_theme_color", CopilotKit intercepts
// the call and runs the handler function defined here instead.
useFrontendTool({
// Step 2c-i: Tool name must match the backend tool declaration
name: "set_theme_color",
// Step 2c-ii: Parameter schema for the LLM to understand the tool
parameters: [
{
name: "theme_color",
description: "The theme color to set. Make sure to pick nice colors.",
required: true,
},
],
// Step 2c-iii: Handler function executed when the tool is called
// Destructures the theme_color from the tool arguments and updates the state
handler({ theme_color }) {
setThemeColor(theme_color);
},
});
// -------------------------------------------------------------------------
// Step 2d: Render the Page Layout
// -------------------------------------------------------------------------
return (
<main
// Step 2d-i: Apply theme color as a CSS custom property
// CopilotKit components read this variable to style their elements
style={
{ "--copilot-kit-primary-color": themeColor } as CopilotKitCSSProperties
}
>
{/* Step 2d-ii: CopilotSidebar provides the chat interface */}
<CopilotSidebar
// Step 2d-iii: Configuration options for the sidebar behavior
clickOutsideToClose={false} // Keep sidebar open when clicking outside
defaultOpen={true} // Start with sidebar visible
// Step 2d-iv: Labels customize the sidebar header and welcome message
labels={{
title: "Popup Assistant",
initial: "👋 Hi, there! You're chatting with a Strands agent.",
}}
// Step 2d-v: Suggestions provide quick-action buttons for users
// Each suggestion sends a predefined message when clicked
suggestions={[
{
title: "Generative UI",
message: "What's the weather in San Francisco?",
},
{
title: "Frontend Tools",
message: "Set the theme to green.",
},
{
title: "Writing Agent State",
message: "Add a proverb about AI.",
},
]}
>
{/* Step 2d-vi: Child content is pushed to the side by the sidebar */}
<YourMainContent themeColor={themeColor} />
</CopilotSidebar>
</main>
);
}
然后尝试让客服人员将用户界面主题设置为绿色。您应该会看到主题变为绿色,如下图所示。
步骤 8:在前端流式传输 AWS Strands + AG-UI 代理响应
要将 AWS Strands + AG-UI 代理的响应或结果流式传输到前端,请将代理的状态字段值传递给前端组件,如下所示。
"use client";
import { useCoAgent } from "@copilotkit/react-core";
function YourMainContent({ themeColor }: { themeColor: string }) {
// 🪁 Shared State: https://docs.copilotkit.ai/coagents/shared-state
const { state, setState } = useCoAgent<AgentState>({
name: "strands_agent",
initialState: {
proverbs: [
"CopilotKit may be new, but it's the best thing since sliced bread.",
],
},
})
// ...
return (
<div
// Step 3e-i: Dynamic background color from theme state
style={{ backgroundColor: themeColor }}
className="h-screen flex justify-center items-center flex-col transition-colors duration-300"
>
{/* Step 3e-ii: Glass-morphism card container for proverbs */}
<div className="bg-white/20 backdrop-blur-md p-8 rounded-2xl shadow-xl max-w-2xl w-full">
{/* Step 3e-iii: Page header */}
<h1 className="text-4xl font-bold text-white mb-2 text-center">
Proverbs
</h1>
<p className="text-gray-200 text-center italic mb-6">
This is a demonstrative page, but it could be anything you want! 🪁
</p>
<hr className="border-white/20 my-6" />
{/* Step 3e-iv: Proverbs list - maps over shared state array */}
<div className="flex flex-col gap-3">
{state.proverbs?.map((proverb, index) => (
<div
key={index}
className="bg-white/15 p-4 rounded-xl text-white relative group hover:bg-white/20 transition-all"
>
{/* Step 3e-v: Proverb text content */}
<p className="pr-8">{proverb}</p>
{/* Step 3e-vi: Delete button - appears on hover */}
<button
onClick={() =>
// Step 3e-vii: Update shared state by filtering out this proverb
// This change will sync back to the backend agent
setState({
...state,
proverbs: state.proverbs?.filter((_, i) => i !== index),
})
}
className="absolute right-3 top-3 opacity-0 group-hover:opacity-100 transition-opacity
bg-red-500 hover:bg-red-600 text-white rounded-full h-6 w-6 flex items-center justify-center"
>
✕
</button>
</div>
))}
</div>
{/* Step 3e-viii: Empty state message when no proverbs exist */}
{state.proverbs?.length === 0 && (
<p className="text-center text-white/80 italic my-8">
No proverbs yet. Ask the assistant to add some!
</p>
)}
</div>
</div>
);
}
如果您查询 AWS Strands + AG-UI 代理,您应该会在 UI 中看到代理的响应或结果流,如下所示。
结论
在本指南中,我们逐步介绍了如何使用 AG-UI 协议和 CopilotKit 为您的 AWS Strands 代理构建前端。
虽然我们已经探索了一些功能,但我们仅仅触及了 CopilotKit 无数用例的皮毛,从构建交互式 AI 聊天机器人到构建代理解决方案——本质上,CopilotKit 可以让您在几分钟内为您的产品添加大量功能性 AI 功能。
希望本指南能帮助您更轻松地将人工智能驱动的副驾驶功能集成到您现有的应用程序中。
关注 CopilotKit 的 Twitter 账号 并打个招呼。如果你想开发一些很酷的东西,欢迎加入我们的 Discord 社区。
文章来源:https://dev.to/copilotkit/easily-build-a-frontend-for-your-aws-strands-agents-using-ag-ui-in-30-minutes-42ji





