CopilotKit React 能力特性门控指南:深入 useCapabilities 与 AgentCapabilities
2026/9/10 2:26:40 网站建设 项目流程

CopilotKit React 能力特性门控指南:深入 useCapabilities 与 AgentCapabilities

【免费下载链接】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

导读

useCapabilities是 CopilotKit React 前端(@copilotkit/react-corev2)提供的特性门控(feature-gating)入口:它基于useAgent读取 agent 在 runtime/info响应中声明的能力清单,让 UI 可以按“该 agent 是否支持语音转写、工具、流式传输”等能力有选择地渲染。读完本文你将掌握useCapabilities的完整用法、AgentCapabilities的字段语义与声明规则,以及三类高危误用的规避方法,并能在多 agent 界面中精确地为每个 agent 声明和消费能力。

useCapabilities 的定位与工作原理

useCapabilities是 react-core skill 中 “Feature-gate UI on declared agent capabilities” 一节对应的核心 hook,它建立在同目录的 agent-access.md 所述的useAgent之上。整个数据流可以概括为:

  1. 服务端 agent 通过配置声明自己的能力(如是否支持工具、是否支持客户端工具、是否支持流式传输);
  2. 前端在连接 runtime 时通过/info握手拿到这些能力,填充到 agent 实例的capabilities字段;
  3. useCapabilities内部调用useAgent并同步读取该字段,返回给组件用于条件渲染。

从源码看,use-capabilities.tsx 的实现非常精简:

export function useCapabilities( agentId?: string, ): AgentCapabilities | undefined { const { agent } = useAgent({ agentId }); if (agent && "capabilities" in agent) { return (agent as { capabilities?: AgentCapabilities }).capabilities; } return undefined; }

值得注意的同步语义:这个 hook没有 loading 状态。它从 agent 实例同步读取capabilities字段,因此在/info握手完成之前返回值始终是undefinedAgentCapabilities类型来自@ag-ui/core(AG-UI 协议客户端核心包),是一个 partial 声明——agent 可以只声明部分能力,其余字段允许缺失。

这一行为在测试中得到了完整覆盖:useCapabilities的四个分支(agent 暴露 capabilities、agent 无 capabilities 属性、agent 尚未连接、capabilities 显式为 undefined)均有对应的单元测试,见 use-capabilities.test.tsx;Angular 端也有等价的injectCapabilities及其测试 capabilities.spec.ts。

快速上手:按能力渲染 UI

useCapabilities@copilotkit/react-core/v2导出,使用前请确保已在应用根部挂载CopilotKitProvider(参见 provider-setup.md)。以下是一个“语音录制按钮”示例:只有当 agent 声明支持转录(transcription)时才显示“Record”按钮。

"use client"; import { useCapabilities } from "@copilotkit/react-core/v2"; export function VoiceButton() { const caps = useCapabilities(); // 不传参数时默认取 DEFAULT_AGENT_ID // 握手尚未完成——先渲染占位骨架,不要急于隐藏 if (caps === undefined) return <div className="skeleton h-8 w-8" />; // 握手完成——按能力做特性门控 if (!caps.transcription) return null; return <button>Record</button>; }

核心使用模式

1. 作用域限定到指定 agent

useCapabilities接受可选的agentId参数。在多 agent 应用中,可以为每个 agent 读取其独立声明的能力:

const caps = useCapabilities("research");

当省略agentId时,hook 会继承外层聊天配置所解析的 agent,并回退到默认 agent——这与useAgent的解析规则完全一致(测试中mockUseAgent被断言以{ agentId: undefined }调用)。

2. 用能力门控工具类 UI

对于依赖 agent 工具能力的面板,应当同时处理“握手未完成”和“能力未声明”两种状态:

const caps = useCapabilities("default"); if (caps === undefined) return <ToolsSkeleton />; if (caps.tools?.supported === false) return null; return <ToolsPanel />;

3. 防御性收窄可选字段

因为AgentCapabilities是 partial 声明,agent 可以选择不声明某个字段。读取时应使用可选链与空值合并,而不是假定字段一定存在:

const caps = useCapabilities(); const maxTokens = caps?.maxOutputTokens ?? "unknown";

AgentCapabilities 的字段结构与默认声明

从 runtime 侧实现可以准确还原AgentCapabilities的字段构成。BuiltInAgent在未显式声明能力时,会返回一组自动推断的默认值,见 packages/runtime/src/agent/index.ts:

const inferred: AgentCapabilities = { tools: { supported: true, clientProvided: true, }, transport: { streaming: true, }, humanInTheLoop: { interrupts: true, }, };

据此可以确认能力按“类别(category)”组织,常见的字段组合包括:

能力类别字段含义
toolssupportedagent 是否支持工具调用
toolsclientProvided是否支持浏览器端(客户端)注册的工具,对应useFrontendTool
transportstreaming是否支持流式传输
humanInTheLoopinterrupts是否支持人工介入(中断/恢复)
transcription(布尔)是否支持语音转写(本文示例中的caps.transcription
maxOutputTokens(数值)最大输出 token 数上限

需要说明的是:transcriptionmaxOutputTokens等字段在文档与示例中出现,但并非BuiltInAgent默认推断集合的一部分,属于 agent 按需自行声明的能力——这也正是“AgentCapabilities是 partial 声明,每个字段都可选”这一设计的意义。

常见错误与规避

高危:把undefined当作“无能力”

握手完成前useCapabilities返回undefined。如果把undefined{ transcription: false }混为一谈,功能会在握手期间被永久隐藏。

错误写法:

function VoiceButton() { const caps = useCapabilities(); if (!caps?.transcription) return null; // 握手期间按钮被永久隐藏 return <button>Record</button>; }

正确写法:

function VoiceButton() { const caps = useCapabilities(); if (caps === undefined) return <div className="skeleton h-8 w-8" />; if (!caps.transcription) return null; return <button>Record</button>; }

要点:caps === undefined只意味着“还不知道”,应当显示占位;只有握手完成后的显式false才意味着“不支持”。实现与注释见 use-capabilities.tsx。

中危:对可选字段使用非空断言

AgentCapabilities的每个字段都可选。caps!.maxOutputTokens在 agent 未声明该字段时会直接崩溃。

错误写法:

const caps = useCapabilities(); return <div>Max tokens: {caps!.maxOutputTokens}</div>; // 若 agent 未声明 capabilities,或未声明 maxOutputTokens,此处崩溃

正确写法:

const caps = useCapabilities(); return <div>Max tokens: {caps?.maxOutputTokens ?? "unknown"}</div>;

原则:先收窄(narrow)再解引用(deref)。

中危:期望服务端 capabilities 做深合并

BuiltInAgentcapabilities配置执行的是类别级别的浅合并——提供某个类别(如tools)会整体替换该类别,而不是仅覆盖其中个别字段。这一点在 packages/runtime/src/agent/index.ts 的注释中有明确说明,并在 getCapabilities() 中以“展开 inferred 默认值后再展开显式覆盖”的方式实现:

// 浅合并:显式覆盖在类别级别替换默认值,其余类别由 inferred 填充 return { ...inferred, ...capabilities, };

错误写法(期望clientProvided保留默认值):

// Server: new BuiltInAgent({ // ... capabilities: { tools: { supported: true } }, }); // 客户端期望 caps.tools.clientProvided 仍为默认的 true —— 实际已被整体替换

正确写法(提供完整类别):

// Server — 提供完整的类别字段: new BuiltInAgent({ // ... capabilities: { tools: { supported: true, clientProvided: true } }, });

因此在覆盖任一能力类别时,必须同时提供该类别下的全部字段,客户端看到的将严格等于你声明的内容。这一浅合并语义在ProxiedCopilotRuntimeAgent(packages/core/src/agent.ts)中同样被保留——代理类将capabilities原样传递给useCapabilities消费方。

小结

useCapabilities是连接“服务端能力声明”与“客户端 UI 门控”的桥梁:服务端通过BuiltInAgentcapabilities配置声明(注意类别级浅合并规则),客户端通过/info握手获取后由 hook 同步暴露。使用时牢记三条纪律——先区分undefined(未握手)与false(不支持)、对可选字段先收窄再解引用、声明能力时提供完整类别——即可在多 agent 场景下构建既稳健又精确的响应式界面。进一步的配套能力可参考 agent-access.md(agent 访问与订阅)与 switching-agents.md(多 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),仅供参考

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

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

立即咨询