CopilotKit Headless Chat 最小实战指南基于 LlamaIndex 的 useAgent useCopilotKit 双 Hook 手写聊天界面【免费下载链接】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 开源仓库中 LlamaIndex 集成示例的 Headless ChatSimple场景讲解如何在不使用CopilotChat /预构建组件的前提下仅凭useAgent与useCopilotKit两个核心 Hook 加一套 shadcn/ui 外壳搭出一个可运行、可测试的最小聊天界面。读完本文你将掌握 Headless 模式的核心数据流、agent.addMessagerunAgent的调用链、文本气泡与输入框的自实现方案以及这套界面如何与 LlamaIndex 后端 Agent 通过 AG-UI 协议联通。一、Headless 模式是什么Bring Your Own UI在 CopilotKit 的体系里聊天界面有两种构建方式Pre-Built预构建直接使用CopilotChat /、CopilotSidebar /、CopilotPopup /等现成组件由框架接管消息列表、输入框、气泡样式等全部 UI 细节。仓库中 prebuilt-sidebar 和 prebuilt-popup 是这类方式的代表。Headless无头CopilotKit 只提供状态与行为Hook界面的每一像素都由你手写。Headless 的价值在于可以把 Agent 能力无缝嵌入你已有的设计系统、品牌风格或特殊布局而不必受限于框架自带的 UI。本文要讲的 headless-simple 就是这个方向的最小实现源码注释明确写道「Headless bring-your-own-UI. Simple the smallest possible chat using the two core hooks (useAgentuseCopilotKit), styled with shadcn/ui」。它刻意不做工具渲染tool rendering、不做生成式 UIgenerative UI只有纯文本进、纯文本出作为开发者复制粘贴起步的规范样本。与之对应仓库中还提供了功能更完整的 headless-complete包含附件上传、工具卡片渲染、流式打字指示等完整实现。两者对照阅读可以清晰看到从「最小可用」到「完整可用」的演进路径。二、QA 清单解析这个 Demo 要验证什么本指南对应的 QA 文档 headless-simple.md 定义了三条验收标准它们是理解该 Demo 定位的钥匙Navigate to/demos/headless-simple——导航到该演示路由确认页面可访问Verify the hand-rolled chat UI is visible (no CopilotChat)——验证页面上渲染的是手写聊天 UI而不是默认的CopilotChat /组件。这是 Headless 模式的「结构性信号」Send Show a card about cats and verify theshow_cardtool renders a titled card——发送示例指令验证 Agent 通过show_card前端工具在界面上渲染出一张带标题的卡片。第三条中的show_card是 LlamaIndex 侧 Agent 暴露的前端工具frontend tool其定义位于 agent.pydef show_card( title: Annotated[str, Short heading for the card.], body: Annotated[str, Body text for the card.], ) - str: Display a titled card with a short body of text. Rendered on the frontend via useComponent. return fDisplayed card: {title}从源码结构看这个工具本身不执行任何后端逻辑只返回一行确认字符串真正的「渲染」发生在前端——Agent 发出调用意图后由前端注册的组件useComponent把title和body渲染成卡片。这是理解 CopilotKit 前端工具模型的关键工具声明在 Agent 侧执行渲染在浏览器侧。三、页面装配一个 Provider 加一个自定义组件整个页面的装配非常精简page.tsx 只有十几行use client; import { CopilotKit } from copilotkit/react-core/v2; import { Chat } from ./chat; export default function HeadlessSimpleDemo() { return ( CopilotKit runtimeUrl/api/copilotkit agentheadless-simple Chat / /CopilotKit ); }三个关键点CopilotKitProvider来自copilotkit/react-core/v2是所有 Hook 的上下文来源。它接收两个属性——runtimeUrl指向 Next.js 的 API 路由/api/copilotkitagent指定要绑定的 Agent 名称headless-simple。use client指令所有使用 Hook 的组件都必须在客户端渲染这与 Next.js App Router 的约定一致。Chat /自定义组件聊天界面的一切都由这个手写组件承载。Agent 名称headless-simple与后端的路由注册对应。在 route.ts 中headless-simple以及下划线别名headless_simple被注册进共享 Agent 列表所有共享 Agent 都指向同一个 LlamaIndex 后端const sharedAgentNames [ // ... headless_simple, headless_complete, // Hyphenated aliases matching what the demo pages actually request headless-simple, headless-complete, // ... ];而该 API 路由内部通过CopilotRuntimeHttpAgent把请求代理到独立的 LlamaIndex Agent 服务默认http://localhost:8000双方通过AG-UI 协议通信const AGENT_URL process.env.AGENT_URL || http://localhost:8000; function createAgent(subpath: string ) { return new HttpAgent({ url: ${AGENT_URL}${subpath}/run }); }在 LlamaIndex 侧get_ag_ui_workflow_router()自动把工作流包装成 AG-UI 兼容的 FastAPI 路由见 agent.py 的模块注释并由 agent_server.py 的app.include_router(agent_router)挂载。也就是说前端 Hook → CopilotKit Runtime → AG-UI 协议 → LlamaIndex 工作流这就是整条数据链路。四、核心逻辑两个 Hook 撑起整个聊天Headless-simple 的灵魂在 chat.tsx。整个聊天逻辑的核心区域源码中以region[use-agent-simple]标注只有约 20 行const { agent } useAgent({ agentId: headless-simple }); const { copilotkit } useCopilotKit(); const [input, setInput] useState(); const send (text: string) { const trimmed text.trim(); if (!trimmed || agent.isRunning) return; agent.addMessage({ id: crypto.randomUUID(), role: user, content: trimmed, }); setInput(); void copilotkit.runAgent({ agent }).catch((err) { console.error([langgraph-python:headless-simple] runAgent failed, err); }); };拆解这段代码就是 Headless 模式的标准三步曲useAgent({ agentId })拿到目标 Agent 的句柄。它暴露了messages消息日志、addMessage()追加消息、isRunning运行状态等核心能力。注意这里的agentId要与 Provider 上的agent属性对应。agent.addMessage()先把用户输入以role: user追加进本地消息列表。crypto.randomUUID()生成消息 ID无需服务端参与。copilotkit.runAgent({ agent })真正触发一次 Agent 运行。它返回 PromiseDemo 里用void丢弃返回值只保留.catch做错误日志——源码注释特别强调静默吞掉错误会示范不良实践因此这里把网络失败、运行时错误、传输断开等问题打印到控制台方便开发者排查。if (!trimmed || agent.isRunning) return;这行防御逻辑同时处理了两件事过滤空白输入、防止在 Agent 运行期间重复发送。消息渲染只显示用户与助手的纯文本运行结束后Agent 的消息会流式写入agent.messages。Simple 版刻意做了最小化过滤只渲染纯文本的用户/助手消息const visible agent.messages.flatMap((m) { if (m.role ! user m.role ! assistant) return []; if (typeof m.content ! string || m.content.length 0) return []; return [{ id: m.id, role: m.role, content: m.content }]; });这个过滤有两个意图跳过工具调用tool call、系统消息等非文本消息类型同时跳过内容为空的条目。之后遍历visible数组分别渲染UserBubble和AssistantBubble定义见 message-bubble.tsx。每个气泡都带data-testidheadless-message-user/headless-message-assistant和data-message-role属性这些是下方测试章节会用到的重要锚点。打字指示器由运行状态驱动const last visible[visible.length - 1]; const showTyping agent.isRunning (!last || last.role user);当agent.isRunning为真、且最后一条可见消息来自用户或还没有消息时显示 TypingIndicator——三个带动画延迟的跳动圆点模拟「Agent 正在思考」。空状态首屏引导的三个示例提示首次加载、还没有消息时页面渲染 EmptyState其中定义了三句示例提示词const SAMPLES [ Say hello in one short sentence., Tell me a one-line joke., Give me a fun fact., ];点击任意一个 Badge 按钮会直接调用send()填入该提示词。源码中对空状态的布局处理还有一个值得注意的细节它被渲染在ScrollAreaRadix之外因为 Radix ScrollArea 内部会包一层display: table的容器破坏h-full的高度传播导致子元素无法垂直居中——这个注释见 chat.tsx对任何使用 Radix ScrollArea 做居中的开发者都有借鉴价值。输入框Enter 发送ShiftEnter 换行composer.tsx 实现底部输入区单行 Textarea回车发送、Shift回车插入换行发送按钮在输入为空或 Agent 运行时禁用。其data-testidheadless-composer同样是测试锚点。五、后端支撑LlamaIndex 工作流如何提供 Agent虽然 Simple 版前端极简但后端依然由完整的 LlamaIndex Agent 支撑。在 agent.py 中工作流通过FixedAGUIChatWorkflow装配async def _agent_workflow_factory(): wf FixedAGUIChatWorkflow( llmOpenAI(modelgpt-4.1, **_openai_kwargs), frontend_tools[ change_background, generate_haiku, generate_task_steps, book_call, show_card, get_weather, ], backend_tools[ query_data, manage_sales_todos, get_sales_todos_tool, schedule_meeting, search_flights, generate_a2ui, ], system_prompt_AGENT_SYSTEM_PROMPT, initial_state{todos: []}, ) wf.render_only_tool_names {get_weather} return wf要点解读frontend_tools声明前端工具show_card就在其中——QA 文档要求验证的正是它。这类工具的执行发生在浏览器端由前端useComponent渲染结果Agent 只负责在合适时机发起调用。backend_tools服务端执行的工具如query_data查询金融数据、search_flights搜索航班等。system_prompt系统提示词中明确包含「- Show titled cards with a body of text (via show_card frontend tool)」告诉模型何时调用该工具。render_only_tool_names标记仅渲染不阻塞的工具get_weather使其渲染状态能正确过渡到「完成」。这里的FixedAGUIChatWorkflow是从 hitl_in_chat_agent.py 导入的模块注释说明它修复了上游库的三个 bug重复的工具调用渲染、缺失的parent_message_id、错误的工具结果消息角色属于仓库内部的工程化处理可作为理解项目深度的一个注脚。启动这套前后端的最直接方式是仓库package.json中定义的dev脚本next dev --turbopack # 以及并行运行 PYTHONPATH. python -m uvicorn agent_server:app --host 0.0.0.0 --port 8000 --reload即 Next.js 前端 8000 端口的 LlamaIndex Agent 服务详见 package.json 中的dev命令。OPENAI_API_KEY需在环境中配置路由的健康检查会显示其是否已设置。六、测试验证E2E 如何守护「Headless」语义QA 清单的验收可以由 Playwright 测试自动覆盖测试文件是 headless-simple.spec.ts。该测试描述了明确的守护语义自定义输入框是「Headless」的结构性信号如果页面退化回默认的CopilotChat /headless-composer这个 testid 就会消失测试随即失败自定义气泡是另一道防线headless-message-assistanttestid 的缺失同样意味着回归到了预构建 UI确定性夹具测试使用aimock确定性响应夹具为三个示例提示词分别固定了回答内容如问候语Hi! In one short sentence: Im a CopilotKit demo agent、笑话、冷知识如果夹具匹配路由出错、导致某个提示词拿到了别的回复断言会以清晰的 diff 失败。测试结构为 4 个用例页面加载后自定义输入框与三个示例提示按钮可见点击 Say hello in one short sentence. 后确定性的问候语出现在自定义助手气泡中点击 Tell me a one-line joke. 后确定性笑话出现在助手气泡中点击 Give me a fun fact. 后确定性冷知识出现在助手气泡中。每个断言都设置了 30 秒超时ASSERT_TIMEOUT以容纳 Agent 运行时长。这套测试同时守护了「Headless 界面存在」与「消息链路工作正常」两层语义是理解该 Demo 验收标准的权威参考。七、延伸从 Simple 到 Complete 的演进路径如果你需要工具渲染、附件上传、建议栏、流式打字效果等更完整的能力仓库中的 headless-complete 是下一站。它把聊天拆分为chat.tsx、composer.tsx、message-list.tsx、message-assistant.tsx等模块并新增hooks/use-tool-renderers.tsx、hooks/use-frontend-components.ts、hooks/use-headless-suggestions.ts等 Hook展示如何在纯手写界面上逐步叠加高级特性。对比两个 Demo 的目录结构headless-simple 5 个文件 vs headless-complete 十余个模块可以直观感受「最小可用」到「生产级」的复杂度跃迁。八、小结Headless Simple 用最少的前端代码演示了 CopilotKit 的完整心智模型CopilotKitProvider 提供运行时useAgent管理单个 Agent 的消息与状态useCopilotKit负责触发执行UI 全部自绘测试锚点由自定义data-testid提供后端通过 CopilotKit Runtime 以 AG-UI 协议连接 LlamaIndex 工作流。对于需要在现有设计系统中嵌入 Agent 能力的开发者这个 Demo 就是最合适的起点模板。【免费下载链接】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),仅供参考