CopilotKit 与 Langroid 集成实战:用 useAgentContext 实现只读 Agent 上下文(Readonly State)
2026/9/14 15:49:03 网站建设 项目流程

CopilotKit 与 Langroid 集成实战:用 useAgentContext 实现只读 Agent 上下文(Readonly State)

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

导读

本文围绕 CopilotKit 展示项目(showcase)中 Langroid 集成模块的只读 Agent 上下文功能展开,讲解如何通过useAgentContext将前端 UI 状态(用户身份、时区、最近活动等)以单向、只读的方式发布给后端 Langroid Agent,并详细拆解官方 QA 验证清单(showcase/integrations/langroid/qa/readonly-state-agent-context.md)中每一条测试步骤的预期行为与底层实现。读完本文,你将掌握useAgentContext的调用方式、上下文数据的传输链路(Next.js Runtime → AG-UI → Langroid Agent Server),以及如何用 Playwright E2E 测试固化这类"只读上下文"行为。

一、功能定位:让 Agent"知道"但"不能改"的 UI 状态

在 CopilotKit 的前端框架体系中,Agent 有时需要了解"用户当前在界面上看到了什么",例如:

  • 当前登录用户的显示名(identity);
  • 用户所在的 IANA 时区(用于回答"现在几点"这类问题);
  • 用户在应用内的最近活动记录(用于推荐下一步操作)。

这些值属于纯输入(input):Agent 只需要读取,绝不应该被 LLM 通过工具调用反向修改。为此,CopilotKit 提供了useAgentContext—— 一条单向的 UI → Agent 通道

官方文档(showcase/shell-docs/src/content/docs/shared-state/agent-readonly.mdx)对它的设计定位概括为:

"props for the agent"(给 Agent 传的 props)。

与完整的共享状态(shared state,Agent 可以调用工具把状态写回 UI)不同,useAgentContext发布的值:

  • 在每一轮对话中都会通过运行时的上下文注入被 Agent 看到;
  • 没有任何 setter,也没有任何可写回的工具;
  • 组件卸载时自动注销(例如离开当前页面,"当前记录"上下文随之消失)。

因此它天然适合用户身份、功能开关、当前选中的记录、滚动位置这类"UI 拥有、Agent 只读"的数据。

二、核心 API:useAgentContext 的调用方式与参数

Langroid 集成模块的 demo 页面位于 showcase/integrations/langroid/src/app/demos/readonly-state-agent-context/page.tsx,其核心调用如下:

useAgentContext({ description: "The currently logged-in user's display name", value: userName, }); useAgentContext({ description: "The user's IANA timezone (used when mentioning times)", value: userTimezone, }); useAgentContext({ description: "The user's recent activity in the app, newest first", value: recentActivity, });

每个useAgentContext调用只接受两个字段:

参数含义注意事项
description一段简短的人类可读标签,Agent 会与 value 一起看到官方文档强调它"像参数 docstring 一样重要",直接影响 LLM 理解该值的用途
value要发布的实际值(字符串、数组等)值变化时(React 重渲染)自动刷新注册项;组件卸载时自动移除

从 demo 可以看到,三处调用的value分别来自三个独立的useState

const [userName, setUserName] = useState("Atai"); const [userTimezone, setUserTimezone] = useState("America/Los_Angeles"); const [recentActivity, setRecentActivity] = useState<string[]>([ ACTIVITIES[0], // "Viewed the pricing page" ACTIVITIES[2], // "Watched the product demo video" ]);

官方文档同时指出:useAgentContext并不关心 value 来自哪里——可以是本地useState、React Context、Redux、查询缓存等任意来源,唯一要求是值的标识足够稳定,避免 React 渲染循环。在真实应用中,这些值通常会来自 auth provider、路由 hook 或领域状态仓库。

三、demo 界面:Context 卡片与实时 JSON 预览

demo 页面布局由 demo-layout.tsx 实现,整个界面被称为 "Agent Context Inspector",包含三张卡片:

  1. Identity 卡片:展示 Name(文本框)与 Timezone(下拉选择,包含America/Los_AngelesAsia/Tokyo等 6 个时区),以及一个根据名字首字母和时区区域动态渲染的头像;
  2. Recent Activity 卡片:5 项可勾选的活动(如 "Viewed the pricing page"、"Started the 14-day free trial"),勾选状态决定该活动是否"Visible to the agent";
  3. Published Context 卡片:全宽度的 JSON 预览区,实时展示真正广播给 Agent 的载荷:
{ "name": "Atai", "timezone": "America/Los_Angeles", "recentActivity": ["Viewed the pricing page", "Watched the product demo video"] }

这个 JSON 预览是 QA 验证的核心观察点——所有字段编辑都会立即反映到该 JSON 中,形成"所见即 Agent 所得"的可视化反馈闭环。

demo 还在 suggestions.ts 中通过useConfigureSuggestions预置了三条与只读上下文强相关的建议提问:

  • "Who am I?" → "What do you know about me from my context?"
  • "Suggest next steps" → "Based on my recent activity, what should I try next?"
  • "Plan my morning" → "What time is it in my timezone and what should I do for the next hour?"

这三条建议恰好覆盖了 QA 清单中要验证的 Agent 行为(身份识别、活动推荐、时区感知)。

四、数据链路:上下文如何从 UI 到达 Langroid Agent

只读上下文并不直接"拼"进前端代码,而是走一条完整的前后端链路,由两部分组成:

4.1 前端运行时代理(Next.js route.ts)

showcase/integrations/langroid/src/app/api/copilotkit/route.ts 使用@copilotkit/runtime/v2CopilotRuntimecreateCopilotRuntimeHandler创建单一路由(mode: "single-route"),并通过HttpAgent(来自@ag-ui/client)将请求按AG-UI 协议代理到后端 Langroid Agent Server(默认http://localhost:8000,可用环境变量AGENT_URL覆盖):

const AGENT_URL = process.env.AGENT_URL || "http://localhost:8000"; function createAgent(path = "/") { return new HttpAgent({ url: `${AGENT_URL}${path}` }); }

该 route 将包括"readonly-state-agent-context"在内的 30 余个 demo agent 名称统一注册到同一个后端统一 Agent 上(代码注释明确说明"Read-only agent context — frontend exposes useAgentContext; same agent")。也就是说,只读上下文完全由前端运行时注入,后端 Agent 本身不需要任何专用工具

4.2 后端 Langroid Agent Server(agent_server.py)

showcase/integrations/langroid/src/agent_server.py 是一个 FastAPI 服务。由于 Langroid 没有原生的 AG-UI 适配器,它实现了一个自定义 SSE 端点,把 Langroid 的ChatAgent与 AG-UI 事件流相互转换。文件头注释明确指出:

The Next.js CopilotKit runtime proxies requests here via AG-UI protocol.

从 agui_adapter.py 的代码可以看到,@app.post("/")run_agent会把请求体强转为RunAgentInputRunAgentInput(**body)),再进入 AG-UI 的 SSE 事件管道。前端运行时在每一轮将useAgentContext注册的条目注入消息历史后,Agent 便能在该轮回答中感知到这些上下文值——这正是 QA 中"Agent 能引用上下文"的底层原因。

4.3 页面接线

demo 页面的外层通过<CopilotKit runtimeUrl="/api/copilotkit" agent="readonly-state-agent-context">绑定运行时与 Agent,再挂载CopilotPopup(占位提示为 "Ask about your context...")作为对话入口。整个结构是:React 状态 → useAgentContext 注册 → CopilotKit runtime 注入 → AG-UI 代理 → Langroid 统一 Agent 读取

五、QA 验证清单逐条拆解:默认值、操作与预期

原 QA 文档(showcase/integrations/langroid/qa/readonly-state-agent-context.md)定义了 6 条人工验收步骤,下面逐条给出其预期行为与源码依据。

5.1 导航到 /demos/readonly-state-agent-context

页面路由由src/app/demos/readonly-state-agent-context/page.tsx提供,浏览器访问后应渲染出三张 Context 卡片与右下角的 Copilot 弹出式聊天窗。

5.2 验证 context card 默认 Name 为 "Atai"

useState("Atai")是 Name 的默认值,Identity 卡片与 Published Context JSON 中的"name": "Atai"应同时呈现。E2E 测试用page.getByTestId("identity-name")断言其文本为 "Atai"(见下文测试章节)。

5.3 将 Name 改为 "Jordan",验证 published JSON 更新

修改 Name 输入框会触发setUserNameuseAgentContext注册项随之刷新,Published Context 的 JSON 预览立即变为"name": "Jordan"。这说明上下文与 UI 状态是实时绑定的,无需重新刷新页面或重新建立会话。

5.4 切换 recent-activity 复选框,验证 JSON 更新

toggleActivityrecentActivity数组做包含/排除切换:

const toggleActivity = (activity: string) => { setRecentActivity((prev) => prev.includes(activity) ? prev.filter((a) => a !== activity) : [...prev, activity], ); };

每次勾选/取消,recentActivity数组变化,JSON 预览中的活动列表同步增减。默认勾选的是ACTIVITIES[0](Viewed the pricing page)与ACTIVITIES[2](Watched the product demo video)。

5.5 提问 "What do you know about me?",Agent 应引用上下文值

这是整个功能的核心验证:点击 "Who am I?" 建议后,Agent 的回答应包含从上下文读到的身份信息(如名字)。在真实 LLM 环境下,回答会引用当前发布的 context 字段;在 CI 的 aimock 录制环境下,该提示词对应固定的 fixture,回复以 "I see you're Atai" 开头(见 E2E 测试注释),证明useAgentContext的数据确实到达了模型侧。

5.6 修改时区后提问 "What time is it for me?",Agent 应反映新时区

将 Timezone 从默认的America/Los_Angeles改为其他时区(如Asia/Tokyo)后,userTimezone上下文更新,Agent 回答时间类问题时将基于新的时区作答。这验证了 description("The user's IANA timezone (used when mentioning times)")对模型行为的指导作用。

六、E2E 测试:把 QA 清单固化为可回归的断言

QA 清单的人工步骤在 showcase/integrations/langroid/tests/e2e/readonly-state-agent-context.spec.ts 中被完整自动化(测试文件头注释明确标注 "QA reference: qa/readonly-state-agent-context.md")。测试覆盖了四个关键场景:

  1. 页面加载:断言context-card可见、composer 占位符 "Ask about your context..." 可见;
  2. 编辑联动:将 Name 填入 "Jamie" 后断言 JSON 出现"name": "Jamie";将时区切换为Asia/Tokyo后断言 JSON 出现"timezone": "Asia/Tokyo"
  3. 身份问答:先断言 Identity 卡默认显示 "Atai" / "America/Los_Angeles" / 头像 "A",再点击 "Who am I?" 建议,断言助手回复以 "I see you're Atai" 开头(aimock fixture 固定输出);
  4. 活动勾选默认值:断言 "pricing page" 与 "product demo video" 两个复选框默认处于 checked 状态;
  5. 活动问答:点击 "Suggest next steps" 后,断言助手回复引用默认活动("Since you recently viewed the pricing page and watched the product demo video...")。

测试注释还特别说明了测试策略:两个建议提示词被固定映射到 aimock 确定性 fixture,以保证 CI 稳定性;在 Railway 真实部署上,同样的提示词会得到引用已发布上下文字段的真实 LLM 回复——"证明端到端 useAgentContext 接线正确"

七、只读上下文与共享状态的选择边界

Langroid 集成模块同时提供了共享状态的同类 demo(如 shared-state-read-write.py 对应的读+写 demo,后端通过set_notes等工具写回状态并发射STATE_SNAPSHOT事件)。两者边界可归纳为:

维度useAgentContext(只读)Shared State(读+写)
方向UI → Agent 单向UI ↔ Agent 双向
Agent 可否修改不能(无 setter、无写回工具)可以(通过工具调用 mutate)
典型场景登录用户、时区、功能开关、当前记录需要双方协作编辑的工作区(笔记、偏好、进度)
卸载行为组件卸载自动注销显式管理

官方文档(agent-readonly.mdx)给出的选择建议是:当值是一个"输入"而非"字段"——即"每一轮传给 Agent 的上下文对象",而不是"双方共同编辑的工作区"——时,优先使用useAgentContext;当需要同时支持读与写时,才升级为完整的 共享状态。

八、小结

Langroid 集成中的 Readonly State (Agent Context) demo 完整演示了 CopilotKit 只读上下文的标准用法:前端通过useAgentContext({ description, value })发布身份、时区、活动等 UI 状态,Next.js Runtime 借助 AG-UI 协议代理到 Langroid Agent Server,使 Agent 每一轮都能感知这些值但永远无法修改它们。QA 清单的 6 条步骤(导航、默认值校验、字段编辑联动、JSON 实时更新、身份问答、时区感知问答)既是人工验收的 checklist,也在 E2E 测试中固化为自动化断言。对于任何需要"让 Agent 理解当前 UI 语境"但又必须保证数据不被 Agent 篡改的场景,这一模式都是可直接复用的参考实现。

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询