ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CopilotKit 只读 Agent Context 模式(LangGraph Python):useAgentContext 原理、Demo 实现与 QA 验证全解

CopilotKit 只读 Agent Context 模式(LangGraph Python):useAgentContext 原理、Demo 实现与 QA 验证全解 CopilotKit 只读 Agent Context 模式LangGraph PythonuseAgentContext 原理、Demo 实现与 QA 验证全解【免费下载链接】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 仓库中 LangGraphPython集成展示站的 QA 文档 qa/readonly-state-agent-context.md 为核心完整讲解useAgentContext只读上下文模式的端到端行为前端如何把用户名、时区、最近活动等状态“单向发布”给 Agent、后端CopilotKitMiddleware如何逐轮消费这些上下文以及 QA 检查清单中每一项测试点在前端源码、后端图和 Playwright e2e 测试中对应的验证位置帮助你掌握该模式的可复现验证方案。1. 主题定位useAgentContext 是“反向”共享状态在 CopilotKit 的状态体系中共享状态默认支持 Agent 双向读写而useAgentContext是其反向形态——前端把数据提供给 AgentAgent 每轮every turn都能读到最新值但没有任何回写通道。展示站后端的模块文档字符串对这一语义描述得很直接Demonstrates theuseAgentContexthook from copilotkit/react-core/v2: the frontend provides READ-ONLY contexttothe agent. This is the reverse direction of writable-shared-state — the UI cannot be edited by the agent, but the agent reads this context on every turn viaCopilotKitMiddleware.见 readonly_state_agent_context.py。该 Demo 被刻意设计为“最小形态”无自定义 state、无 toolsAgent 唯一要做的事就是读取前端注册的上下文并据此回答。这使得它成为验证useAgentContext接线是否正确的理想用例。三条数据流概括了整体链路前端React 组件通过useAgentContext注册带description的键值上下文每次渲染值变化即重新发布运行时CopilotKit RuntimeNext.js 单路由模式把上下文条目随请求转发给 LangGraph 后端后端CopilotKitMiddleware将上下文条目路由进模型的 message historyAgent 在每一轮推理时都能“看见”当前最新值no stale context。2. 前置条件与部署拓扑QA 文档列出的三项前置条件均可在仓库中找到对应实现Demo 已部署且可访问前端为 Next.js 应用Demo 页面位于src/app/demos/readonly-state-agent-context/Agent 后端健康check /api/health路由层还内置了GET /api/copilotkit健康探针它会主动探测 LangGraph 服务的/ok端点并返回langgraph_statusreachable / unreachable / error同时报告OPENAI_API_KEY、LANGSMITH_API_KEY是否已设置见 route.ts图readonly_state_agent_context已在运行时注册这里涉及两层注册——LangGraph 服务端langgraph.json 将图名readonly_state_agent_context映射到./src/agents/readonly_state_agent_context.py:graphCopilotKit Runtimeroute.ts 中将该前端 Agent 名注册到该图// Shared state RW and read-only agent context. agents[shared-state-read-write] createAgent(shared_state_read_write); agents[readonly-state-agent-context] createAgent(readonly_state_agent_context);createAgent的底层实现见 route.ts值得注意它构造LangGraphAgentdeploymentUrl取自环境变量LANGGRAPH_DEPLOYMENT_URL默认http://localhost:8123并把recursion_limit: 100固化进assistantConfig。源码注释解释了原因——LangGraph 的recursion_limit默认为 25而通过 langgraph server 的 runs API 调用时with_config不会传播到 assistant config因此必须在运行时侧显式注入。3. 前端实现三个 useAgentContext 调用与 Published Context 面板3.1 页面骨架与 CopilotKit ProviderDemo 入口 page.tsx 用CopilotKit包裹整个页面锁定运行时地址与 Agent 名CopilotKit runtimeUrl/api/copilotkit agentreadonly-state-agent-context DemoContent / CopilotPopup agentIdreadonly-state-agent-context defaultOpen{true} labels{{ chatInputPlaceholder: Ask about your context... }} / /CopilotKitchatInputPlaceholder: Ask about your context...正是 QA 清单中“chat panel 渲染占位符”检查项的落点。3.2 上下文状态与 useAgentContext 注册DemoContent组件维护三组本地状态默认值与 QA 文档逐项吻合const [userName, setUserName] useState(Atai); const [userTimezone, setUserTimezone] useState(America/Los_Angeles); const [recentActivity, setRecentActivity] useStatestring[]([ ACTIVITIES[0], // Viewed the pricing page ACTIVITIES[2], // Watched the product demo video ]); useAgentContext({ description: The currently logged-in users display name, value: userName, }); useAgentContext({ description: The users IANA timezone (used when mentioning times), value: userTimezone, }); useAgentContext({ description: The users recent activity in the app, newest first, value: recentActivity, });可以看到useAgentContext接收{ description, value }description是给 Agent 的语义说明帮助模型理解该值如何使用value支持字符串、数组等可序列化类型。每次useState触发重渲染新值即随下一次请求发布给 Agent——这就是 QA 文档中“每次修改都应立即反映”这一期望的机制来源。3.3 布局与 Published Context JSON 预览demo-layout.tsx 定义了两个关键常量与 QA 清单中的选项列表完全一致export const TIMEZONES [ America/Los_Angeles, America/New_York, Europe/London, Europe/Berlin, Asia/Tokyo, Australia/Sydney, ]; export const ACTIVITIES [ Viewed the pricing page, Added Pro Plan to cart, Watched the product demo video, Started the 14-day free trial, Invited a teammate, ];页面核心是data-testidcontext-card的卡片网格包含三块Identity 卡Name 输入框data-testidctx-nameplaceholder e.g. Atai、Timezone 下拉data-testidctx-timezone、由姓名首字母与所在大洲组成的 Avatar姓名为空时头像显示?、姓名显示 Anonymous——这为 QA 中“清空 Name 应优雅降级no crash”提供了 UI 侧依据Recent Activity 卡五个 checkbox每个 label 的 testid 由活动名 kebab-case 化生成如activity-viewed-the-pricing-page选中项标注 Visible to the agent / on未选中项标注 Hidden from the agentPublished Context 卡实时渲染JSON.stringify({ name, timezone, recentActivity }, null, 2)到data-testidctx-state-json的pre中标签为 read-only / streamed描述为 The exact JSON payload broadcast to the agent on every render。这就是 QA 清单里“Published Context JSON 预览”检查项的实体。3.4 建议Suggestionssuggestions.ts 用useConfigureSuggestions注册了三条建议其title即 QA 清单要求可见的三个 pillmessage为点击后实际发送的完整问句useConfigureSuggestions({ suggestions: [ { title: Who am I?, message: What do you know about me from my context? }, { title: Suggest next steps, message: Based on my recent activity, what should I try next? }, { title: Plan my morning, message: What time is it in my timezone and what should I do for the next hour?, }, ], available: always, });注意“点击建议”与“直接输入问句”发送的文案不同例如 Who am I? 实际发送 What do you know about me from my context?QA 文档中两种交互方式并列为可替代路径即源于此。4. 后端实现CopilotKitMiddleware 消费上下文完整的后端图仅 35 行是理解该模式的最小参考实现from langchain.agents import create_agent from langchain_openai import ChatOpenAI from copilotkit import CopilotKitMiddleware graph create_agent( modelChatOpenAI(modelgpt-5.4), tools[], middleware[CopilotKitMiddleware()], system_prompt( You are a helpful, concise assistant. The frontend may provide read-only context about the user (e.g. name, timezone, recent activity) via the useAgentContext hook. Always consult that context when it is relevant — address the user by name if known, respect their timezone when mentioning times, and reference recent activity when it helps you answer. Keep responses short. ), )见 readonly_state_agent_context.py。要点middleware[CopilotKitMiddleware()]是唯一必需的接线它负责把前端发布的上下文条目注入模型的 message history。Demo 没有自定义 state schema、没有工具说明只读上下文与共享状态机制相互独立system prompt 承担“如何使用上下文”的约束称呼用户姓名、提及时间时尊重时区、回答时引用最近活动。QA 中“Agent 是否称呼 Atai / 是否提到 Tokyo/JST / 是否引用 trial 活动”等行为断言本质上是在验证 prompt 与注入上下文的共同效果tools[]排除了工具调用干扰让验证聚焦在“读上下文 → 生成回答”这一条路径上。从源码结构看上下文并非以state字段形式存在图中未定义任何 state 字段而是由 middleware 在每轮请求时从运行时通道读入——这与 QA 期望中“Agent responses reflect the CURRENT context values on every turn (no stale context)”的“每轮重新注入”语义一致。5. QA 检查清单逐项拆解以下按 QA 文档 qa/readonly-state-agent-context.md 的原始结构完整展开并在每节标注可验证的源码依据。5.1 基础功能Basic Functionality检查项验证要点源码依据进入 demo 页面路由/demos/readonly-state-agent-context目录 src/app/demos/readonly-state-agent-contextAgent Context 卡片可见data-testidcontext-carddemo-layout.tsx描述文案提及useAgentContextRead-only context provided to the agent viauseAgentContext. The agent cannot modify these.卡片头部文案Edit fields below and watch the data flow into the agent. The agent can read this context, but cannot modify it.右侧聊天面板渲染占位符 Ask about your context...CopilotPopup的labels.chatInputPlaceholder发送 Hello 后 Agent 以文本回复走完整 runtime → LangGraph → LLM 链路agents[readonly-state-agent-context]注册5.2 初始上下文状态Initial Context StateName 输入ctx-name默认 AtaiTimezone 下拉ctx-timezone默认 America/Los_Angeles且六个选项与TIMEZONES常量一一对应America/Los_Angeles、America/New_York、Europe/London、Europe/Berlin、Asia/Tokyo、Australia/SydneyRecent Activity 五个 checkbox 与ACTIVITIES常量一致默认勾选第 1 项Viewed the pricing page与第 3 项Watched the product demo video即useState([ACTIVITIES[0], ACTIVITIES[2]])Published Context JSON 预览ctx-state-json初始形如{ name: Atai, timezone: America/Los_Angeles, recentActivity: [...] }。以上默认值全部由 page.tsx 与 demo-layout.tsx 决定无需后端参与即可验证。5.3 建议可见性SuggestionsWho am I?、Suggest next steps、Plan my morning 三个 pill 必须可见。由于available: always建议不依赖会话状态e2e 测试通过data-testidcopilot-suggestion定位并hasText过滤标题来断言。5.4 Agent 读取用户名useAgentContext 核心路径点击 Who am I?或输入 What is my name?→ Agent 应称呼 Atai将 Name 改为 Jamie →ctx-state-json立即显示name: Jamie再次询问 → Agent 应答 Jamie 而非 Atai。这一步同时验证“初始值生效”与“值变更后新值生效”。e2e 中该路径通过 aimock 录制的确定性 fixture 断言对 pill 原文 prompt 的回复以 I see youre Atai 开头见 spec 文件改名 改时区后的 JSON 预览断言为await page.getByTestId(ctx-name).fill(Jamie); await expect(json).toContainText(name: Jamie); await page.getByTestId(ctx-timezone).selectOption(Asia/Tokyo); await expect(json).toContainText(timezone: Asia/Tokyo);5.5 Agent 读取时区将ctx-timezone切到 Asia/Tokyo确认 JSON 预览更新后点击 Plan my morningAgent 在讨论时间时应引用 Tokyo / JST / Asia/Tokyo。对应 system prompt 中的 respect their timezone when mentioning times 约束且该 prompt 问句为 What time is it in my timezone and what should I do for the next hour?。5.6 Agent 读取最近活动取消全部默认勾选只保留 Started the 14-day free trial 与 Invited a teammate确认ctx-state-json的recentActivity数组更新后点击 Suggest next stepsAgent 的回复应引用 trial / 邀请同事这两项而不再引用 pricing page 或 demo video。e2e 对默认活动场景的断言是回复以 Since you recently viewed the pricing page and watched the product demo video 开头spec反向验证“数组内容被精确消费”的机制相同。5.7 错误处理Error HandlingName 清空后询问Agent 应优雅处理不崩溃。UI 侧已有降级姓名为空时显示 Anonymous、Avatar 显示 ?见demo-layout.tsx中userName.charAt(0).toUpperCase() || ?与userName || Anonymous空聊天消息输入应被拒绝且不报错由聊天组件自身约束正常使用时控制台无错误Agent 不能修改上下文Name / Timezone / Activity 勾选始终由用户控制——这是只读模式的本质属性对应模块文档中 The UI cannot be edited by the agent。5.8 期望结果Expected ResultsQA 文档给出的量化基线上下文卡片与聊天在 3 秒内加载、Agent 在 10 秒内响应、每次修改立即反映到 Published Context JSON、Agent 每轮响应基于当前上下文值、无 UI 错误或布局破损。e2e 侧对应地把页面级等待设为 15s、回复级等待设为 60s、整个 describe 块超时 90stest.setTimeout(90_000)为真实 LLM 链路留出了裕量。6. Playwright e2e 测试映射自动化版本位于 tests/e2e/readonly-state-agent-context.spec.ts文件头注释明确了 QA 文档、Demo 源码、fixture 三者的对应关系共 5 个用例page loads: context-card composer render——context-card可见、Ask about your context... 占位符可见editing name timezone updates the published JSON preview——修改 Name/Timezone 后ctx-state-json含name: Jamie与timezone: Asia/TokyoWho am I? pill——先锁定 Identity 卡默认值identity-name Atai、identity-timezone America/Los_Angeles、identity-avatar A再点击 pill断言助手回复含 I see youre Ataiactivity checkboxes default-checked——断言activity-viewed-the-pricing-page与activity-watched-the-product-demo-video两个 label 内部的input typecheckbox处于 checked 状态Suggest next steps pill——断言回复以 Since you recently viewed the pricing page and watched the product demo video 开头验证活动数组被逐条消费。测试头部注释还交代了 CI 与真实环境的差异固定 prompt 被钉在 aimock 录制 fixture 上回复首句在 CI 中稳定而在 Railway 等真实部署上同样的 prompt 会产出真实 LLM 回复并提及所发布的上下文字段从而证明端到端useAgentContext接线成立。运行层面测试通过 playwright.config.ts 接入该 Next.js 应用前置条件即 QA 文档列出的三项部署可访问、后端健康、图已注册。7. 与可写共享状态的边界区分同一展示站还有一个方向相反的 Demoshared-state-read-writeshared_state_read_write.py它对应 QA 文档 shared-state-read-write.md。两者在运行时共用同一个agents注册表见 route.ts 的相邻两行便于对照维度useAgentContext本文 Demo可写共享状态数据方向前端 → Agent单向双向Agent 能否回写 UI不能能后端形态tools[]无自定义 state仅 middleware需要 state 定义与写回通道典型验证修改 UI 后 Agent 回答变化Agent 触发工具后 UI 变化理解这个边界后QA 清单中“Agent 不能修改上下文值”就不只是一个检查项而是该模式与可写模式的分界线。8. 小结readonly_state_agent_contextDemo 以最小的代码面前端三个useAgentContext调用 后端一个带CopilotKitMiddleware的create_agent完整覆盖了只读 Agent Context 模式的三大验证维度初始状态正确性默认值、选项集、默认勾选、动态传播改名/改时区/换活动后每轮立即生效且无陈旧值、单向性Agent 只能读不能写。结合 QA 检查清单、Playwright e2e 与 前端源码、后端图即可对该模式做一份可复现、可回归的完整验证。【免费下载链接】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),仅供参考
返回列表