聊天参与者 API
聊天参与者是专门的助手,允许用户通过领域专家来扩展 VS Code 中的聊天功能。用户通过 @提及来调用聊天参与者,随后由该参与者负责处理用户的自然语言提示。
在本扩展指南中,您将学习如何使用聊天参与者 API 创建聊天参与者。
VS Code 内置了多个聊天参与者,例如 @vscode、@terminal 或 @workspace。它们经过优化,能够针对各自的领域回答问题。
聊天参与者不同于语言模型工具,后者是作为编排解决用户聊天提示所需步骤的 LLM 的一部分被调用的。聊天参与者接收用户的提示,并自行编排所需的任务。
为什么要为您的扩展实现聊天参与者?
在扩展中实现聊天参与者有以下几个好处:
- 扩展聊天功能:提供专门的领域知识和专业技能。例如,内置的
@vscode参与者拥有关于 VS Code 及其扩展 API 的知识。 - 掌控对话:管理端到端的聊天提示和响应。
- 与 VS Code 深度集成:利用丰富的扩展 API。例如,使用 调试 API 获取当前的调试上下文,并将其作为工具功能的一部分。
- 分发和部署:通过 Visual Studio Marketplace 分发聊天参与者,为用户提供可靠且无缝的体验。用户无需额外的安装和更新流程。
如果您希望提供可在自主编码会话中自动调用的领域特定功能,可以考虑实现语言模型工具或 MCP 服务器。有关不同选项以及如何决定使用哪种方法的详细信息,请参阅 AI 可扩展性概述。
聊天用户体验的组成部分
以下屏幕截图展示了示例扩展中 VS Code 聊天体验的各种聊天概念。

- 使用
@语法调用@cat聊天参与者 - 使用
/语法调用/teach命令 - 用户提供的查询,也称为用户提示
- 图标和参与者
fullName,表示 Copilot 正在使用@cat聊天参与者 - Markdown 响应,由
@cat提供 - 包含在 Markdown 响应中的代码片段
- 包含在
@cat响应中的按钮,该按钮会调用一个 VS Code 命令 - 聊天参与者提供的建议后续问题
- 聊天输入框,其中包含由聊天参与者的
description属性提供的占位符文本
创建聊天参与者
实现聊天参与者包含以下部分:
- 在扩展的
package.json文件中定义聊天参与者。 - 实现请求处理程序以处理用户的聊天提示并返回响应。
- (可选)实现聊天斜杠命令,为用户提供常用任务的快捷方式。
- (可选)定义建议的后续问题。
- (可选)实现参与者检测,使 VS Code 能够在用户未明确提及的情况下,自动将聊天请求路由到合适的聊天参与者。
您可以从一个基础示例项目开始。

1. 注册聊天参与者
创建聊天扩展的第一步是在 package.json 中注册它,并提供以下属性:
id:聊天参与者的唯一标识符,在package.json文件中定义。name:聊天参与者的短名称,用于聊天中的 @-提及。fullName:聊天参与者的全名,显示在响应的标题区域。description:对聊天参与者用途的简要说明,用作聊天输入框中的占位符文本。isSticky:一个布尔值,指示聊天参与者在回复后是否保留在聊天输入框中。
"contributes": {
"chatParticipants": [
{
"id": "chat-sample.my-participant",
"name": "my-participant",
"fullName": "My Participant",
"description": "What can I teach you?",
"isSticky": true
}
]
}
我们建议使用小写的 name 并使用标题大小写的 fullName,以与现有聊天参与者保持一致。获取更多关于聊天参与者命名规范的信息。
某些参与者名称已被保留。如果您使用了此类保留名称,VS Code 将显示您的聊天参与者的全限定名称(包括扩展 ID)。
2. 实现请求处理程序
使用 聊天参与者 API 实现聊天参与者。这包含以下步骤:
-
在扩展激活时,使用
vscode.chat.createChatParticipant创建参与者。提供您在
package.json中定义的 ID,以及指向您在下一步中实现的请求处理程序的引用。export function activate(context: vscode.ExtensionContext) { // Register the chat participant and its request handler const cat = vscode.chat.createChatParticipant('chat-sample.my-participant', handler); // Optionally, set some properties for @cat cat.iconPath = vscode.Uri.joinPath(context.extensionUri, 'cat.jpeg'); // Add the chat request handler here } -
在
activate函数中,定义vscode.ChatRequestHandler请求处理程序。请求处理程序负责处理 VS Code 聊天视图中的用户聊天请求。每当用户在聊天输入框中输入提示时,就会调用聊天请求处理程序。
const handler: vscode.ChatRequestHandler = async ( request: vscode.ChatRequest, context: vscode.ChatContext, stream: vscode.ChatResponseStream, token: vscode.CancellationToken ): Promise<ICatChatResult> => { // Chat request handler implementation goes here }; -
从
vscode.ChatRequest确定用户的意图。为了确定用户请求的意图,您可以参考
vscode.ChatRequest参数来访问用户的提示文本、命令和聊天位置。(可选)您可以利用语言模型来确定用户的意图,而不是使用传统的逻辑。作为
request对象的一部分,您会获得一个用户在聊天模型下拉菜单中选择的语言模型实例。了解如何在扩展中使用 语言模型 API。以下代码片段展示了首先使用命令,然后使用用户提示来确定用户意图的基本结构:
const handler: vscode.ChatRequestHandler = async ( request: vscode.ChatRequest, context: vscode.ChatContext, stream: vscode.ChatResponseStream, token: vscode.CancellationToken ): Promise<ICatChatResult> => { // Test for the `teach` command if (request.command == 'teach') { // Add logic here to handle the teaching scenario doTeaching(request.prompt, request.variables); } else { // Determine the user's intent const intent = determineUserIntent(request.prompt, request.variables, request.model); // Add logic here to handle other scenarios } }; -
添加逻辑以处理用户请求。
通常,聊天扩展会使用
request.model语言模型实例来处理请求。在这种情况下,您可以调整语言模型提示以匹配用户的意图。或者,您可以通过调用后端服务、使用传统编程逻辑或结合所有这些选项来实现扩展逻辑。例如,您可以调用网络搜索来收集额外信息,然后将其作为上下文提供给语言模型。
在处理当前请求时,您可能希望参考以前的聊天消息。例如,如果之前的响应返回了一个 C# 代码片段,用户当前的请求可能是“用 Python 提供这段代码”。了解如何使用聊天消息历史记录。
如果您想根据聊天输入的位置(聊天视图、快速聊天、内联聊天)以不同方式处理请求,可以使用
vscode.ChatRequest的location属性。例如,如果用户从终端内联聊天发送请求,您可能会查找 Shell 命令。而如果用户使用聊天视图,您可以返回更详尽的响应。 -
将聊天响应返回给用户。
处理完请求后,您必须在聊天视图中向用户返回响应。您可以使用流式传输来响应用户查询。
响应可以包含不同的内容类型:Markdown、图像、引用、进度、按钮和文件树。

扩展可以通过以下方式使用响应流:
stream.progress('Picking the right topic to teach...'); stream.markdown(`\`\`\`typescript const myStack = new Stack(); myStack.push(1); // pushing a number on the stack (or let's say, adding a fish to the stack) myStack.push(2); // adding another fish (number 2) console.log(myStack.pop()); // eating the top fish, will output: 2 \`\`\` So remember, Code Kitten, in a stack, the last fish in is the first fish out - which we tech cats call LIFO (Last In, First Out).`); stream.button({ command: 'cat.meow', title: vscode.l10n.t('Meow!'), arguments: [] });获取更多关于支持的聊天响应输出类型的信息。
在实践中,扩展通常会向语言模型发送请求。一旦收到语言模型的响应,它们可能会进一步处理,并决定是否应该向用户流式传输任何内容。VS Code 聊天 API 是基于流的,并与流式语言模型 API 兼容。这允许扩展持续报告进度和结果,旨在提供顺畅的用户体验。了解如何使用 语言模型 API。
3. 注册斜杠命令
聊天参与者可以贡献斜杠命令,这些命令是扩展提供的特定功能的快捷方式。用户可以通过 / 语法在聊天中引用斜杠命令,例如 /explain。
回答问题时的任务之一是确定用户意图。例如,VS Code 可以推断出“使用 Node.js Express Pug TypeScript 创建一个新工作区”意味着您想要一个新项目,但 @workspace /new Node.js Express Pug TypeScript 更明确、简洁且节省输入时间。如果您在聊天输入框中输入 /,VS Code 会提供已注册命令及其描述的列表。

聊天参与者可以通过在 package.json 中添加斜杠命令及其描述来贡献它们。
"contributes": {
"chatParticipants": [
{
"id": "chat-sample.cat",
"name": "cat",
"fullName": "Cat",
"description": "Meow! What can I teach you?",
"isSticky": true,
"commands": [
{
"name": "teach",
"description": "Pick at random a computer science concept then explain it in purfect way of a cat"
},
{
"name": "play",
"description": "Do whatever you want, you are a cat after all"
}
]
}
]
}
获取更多关于斜杠命令命名规范的信息。
4. 注册后续请求
在每次聊天请求后,VS Code 都会调用后续提供程序以获取建议的后续问题展示给用户。用户随后可以选择后续问题并立即将其发送给聊天扩展。使用 ChatFollowupProvider API 注册类型为 ChatFollowup 的后续提示。
以下代码片段展示了如何在聊天扩展中注册后续请求:
cat.followupProvider = {
provideFollowups(result: ICatChatResult, context: vscode.ChatContext, token: vscode.CancellationToken) {
if (result.metadata.command === 'teach') {
return [{
prompt: 'let us play',
label: vscode.l10n.t('Play with the cat')
} satisfies vscode.ChatFollowup];
}
}
};
后续问题应编写为问题或指令,而不仅仅是简洁的命令。
5. 实现参与者检测
为了让自然语言使用聊天参与者变得更容易,您可以实现参与者检测。参与者检测是一种自动将用户的问题路由到合适参与者的方法,而无需在提示中明确提及该参与者。例如,如果用户询问“如何为我的项目添加登录页面?”,问题会自动路由到 @workspace 参与者,因为它能够回答关于用户项目的问题。
VS Code 使用聊天参与者的描述和示例来确定将聊天提示路由到哪个参与者。您可以在扩展 package.json 文件中的 disambiguation 属性中指定此信息。disambiguation 属性包含检测类别的列表,每个类别都有描述和示例。
| 属性 | 描述 | 示例 |
|---|---|---|
category |
检测类别。如果参与者提供多种用途,您可以为每种用途设置一个类别。 |
|
描述 |
对此参与者适合的问题类型的详细描述。 |
|
examples |
代表性问题示例的列表。 |
|
您可以为整个聊天参与者、特定命令或两者的组合定义参与者检测。
以下代码片段展示了如何在参与者级别实现参与者检测。
"contributes": {
"chatParticipants": [
{
"id": "chat-sample.cat",
"fullName": "Cat",
"name": "cat",
"description": "Meow! What can I teach you?",
"disambiguation": [
{
"category": "cat",
"description": "The user wants to learn a specific computer science topic in an informal way.",
"examples": [
"Teach me C++ pointers using metaphors",
"Explain to me what is a linked list in a simple way",
"Can you explain to me what is a function in programming?"
]
}
]
}
]
}
同样,您也可以通过为 commands 属性中的一个或多个项目添加 disambiguation 属性,在命令级别配置参与者检测。
应用以下准则以提高扩展参与者检测的准确性:
- 具体明确:描述和示例应尽可能具体,以避免与其他参与者冲突。避免在参与者和命令信息中使用通用术语。
- 使用示例:示例应代表适合参与者的问题类型。使用同义词和变体来涵盖广泛的用户查询。
- 使用自然语言:描述和示例应以自然语言编写,就像向用户解释参与者一样。
- 测试检测:使用各种示例问题测试参与者检测,并验证是否与内置聊天参与者存在冲突。
内置聊天参与者在参与者检测中具有优先权。例如,在工作区文件上操作的聊天参与者可能会与内置的 @workspace 参与者冲突。
使用聊天消息历史记录
参与者可以访问当前聊天会话的消息历史记录。参与者只能访问提及过它的消息。history 项可以是 ChatRequestTurn 或 ChatResponseTurn。例如,使用以下代码片段检索用户在当前聊天会话中发送给您的参与者的所有先前请求:
const previousMessages = context.history.filter(h => h instanceof vscode.ChatRequestTurn);
历史记录不会自动包含在提示中,参与者需要自行决定在将消息传递给语言模型时是否希望添加历史记录作为额外上下文。
支持的聊天响应输出类型
要响应聊天请求,您需要使用 ChatRequestHandler 上的 ChatResponseStream 参数。
以下列表提供了聊天视图中聊天响应的输出类型。聊天响应可以组合多种不同的输出类型。
-
Markdown
渲染 Markdown 文本片段、简单文本或图像。您可以使用 CommonMark 规范中的任何 Markdown 语法。使用
ChatResponseStream.markdown方法并提供 Markdown 文本。代码片段示例
// Render Markdown text stream.markdown('# This is a title \n'); stream.markdown('This is stylized text that uses _italics_ and **bold**. '); stream.markdown('This is a [link](https://vscode.js.cn).\n\n'); stream.markdown(''); -
代码块
渲染支持 IntelliSense、代码格式化和将代码应用到活动编辑器的交互式控件的代码块。要显示代码块,请使用
ChatResponseStream.markdown方法并应用代码块的 Markdown 语法(使用反引号)。代码片段示例
// Render a code block that enables users to interact with stream.markdown('```bash\n'); stream.markdown('```ls -l\n'); stream.markdown('```'); -
命令链接
在聊天响应中内联渲染一个链接,用户可以选择该链接来调用 VS Code 命令。要显示命令链接,请使用
ChatResponseStream.markdown方法并使用链接的 Markdown 语法[link text](command:commandId),其中您在 URL 中提供命令 ID。例如,以下链接打开命令面板:[Command Palette](command:workbench.action.showCommands)。为了防止从服务加载 Markdown 文本时发生命令注入,您必须使用
isTrusted属性设置为受信任 VS Code 命令 ID 列表的vscode.MarkdownString对象。此属性对于启用命令链接是必需的。如果未设置isTrusted属性或命令未列出,则命令链接将无法工作。代码片段示例
// Use command URIs to link to commands from Markdown let markdownCommandString: vscode.MarkdownString = new vscode.MarkdownString( `[Use cat names](command:${CAT_NAMES_COMMAND_ID})` ); markdownCommandString.isTrusted = { enabledCommands: [CAT_NAMES_COMMAND_ID] }; stream.markdown(markdownCommandString);如果命令带有参数,您需要先对参数进行 JSON 编码,然后将 JSON 字符串编码为 URI 组件。然后,您将编码后的参数作为查询字符串附加到命令链接中。
// Encode the command arguments const encodedArgs = encodeURIComponent(JSON.stringify(args)); // Use command URIs with arguments to link to commands from Markdown let markdownCommandString: vscode.MarkdownString = new vscode.MarkdownString( `[Use cat names](command:${CAT_NAMES_COMMAND_ID}?${encodedArgs})` ); markdownCommandString.isTrusted = { enabledCommands: [CAT_NAMES_COMMAND_ID] }; stream.markdown(markdownCommandString); -
命令按钮
渲染一个调用 VS Code 命令的按钮。该命令可以是内置命令,也可以是您在扩展中定义的命令。使用
ChatResponseStream.button方法并提供按钮文本和命令 ID。代码片段示例
// Render a button to trigger a VS Code command stream.button({ command: 'my.command', title: vscode.l10n.t('Run my command') }); -
文件树
渲染一个允许用户预览单个文件的文件树控件。例如,在提议创建新工作区时显示工作区预览。使用
ChatResponseStream.filetree方法并提供文件树元素数组和文件的基本位置(文件夹)。代码片段示例
// Create a file tree instance var tree: vscode.ChatResponseFileTree[] = [ { name: 'myworkspace', children: [{ name: 'README' }, { name: 'app.js' }, { name: 'package.json' }] } ]; // Render the file tree control at a base location stream.filetree(tree, baseLocation); -
进度消息
在长时间运行的操作期间渲染进度消息,以向用户提供中间反馈。例如,报告多步操作中每一步的完成情况。使用
ChatResponseStream.progress方法并提供消息。代码片段示例
// Render a progress message stream.progress('Connecting to the database.'); -
参考
在引用列表中为外部 URL 或编辑器位置添加引用,以指示您使用哪些信息作为上下文。使用
ChatResponseStream.reference方法并提供引用位置。代码片段示例
const fileUri: vscode.Uri = vscode.Uri.file('/path/to/workspace/app.js'); // On Windows, the path should be in the format of 'c:\\path\\to\\workspace\\app.js' const fileRange: vscode.Range = new vscode.Range(0, 0, 3, 0); const externalUri: vscode.Uri = vscode.Uri.parse('https://vscode.js.cn'); // Add a reference to an entire file stream.reference(fileUri); // Add a reference to a specific selection within a file stream.reference(new vscode.Location(fileUri, fileRange)); // Add a reference to an external URL stream.reference(externalUri); -
内联引用
为 URI 或编辑器位置添加内联引用。使用
ChatResponseStream.anchor方法并提供锚点位置和可选标题。要引用符号(例如类或变量),您可以使用编辑器中的位置。代码片段示例
const symbolLocation: vscode.Uri = vscode.Uri.parse('location-to-a-symbol'); // Render an inline anchor to a symbol in the workspace stream.anchor(symbolLocation, 'MySymbol');
重要提示:图像和链接仅在源自受信任域列表中的域时才可用。获取更多关于 VS Code 中链接保护的信息。
实现工具调用
为了响应用户请求,聊天扩展可以调用语言模型工具。了解更多关于语言模型工具和工具调用流程的信息。
您可以通过两种方式实现工具调用:
- 使用
@vscode/chat-extension-utils库来简化在聊天扩展中调用工具的过程。 - 通过自行实现工具调用,这可以让您更好地控制工具调用过程。例如,执行额外的验证或在将工具响应发送给 LLM 之前以特定方式处理它们。
使用聊天扩展库实现工具调用
您可以使用 @vscode/chat-extension-utils 库来简化在聊天扩展中调用工具的过程。
在聊天参与者的 vscode.ChatRequestHandler 函数中实现工具调用。
-
确定当前聊天上下文的相关工具。您可以通过
vscode.lm.tools访问所有可用工具。以下代码片段展示了如何仅过滤具有特定标签的工具。
const tools = request.command === 'all' ? vscode.lm.tools : vscode.lm.tools.filter(tool => tool.tags.includes('chat-tools-sample')); -
使用
sendChatParticipantRequest将请求和工具定义发送给 LLM。const libResult = chatUtils.sendChatParticipantRequest( request, chatContext, { prompt: 'You are a cat! Answer as a cat.', responseStreamOptions: { stream, references: true, responseText: true }, tools }, token );ChatHandlerOptions对象具有以下属性:prompt:(可选)聊天参与者提示的指令。model:(可选)用于请求的模型。如果未指定,则使用聊天上下文中的模型。tools:(可选)请求需考虑的工具列表。requestJustification:(可选)描述进行该请求原因的字符串。responseStreamOptions:(可选)启用sendChatParticipantRequest以将响应流式传输回 VS Code。此外,您还可以选择启用引用和/或响应文本。
-
返回来自 LLM 的结果。这可能包含错误详细信息或工具调用元数据。
return await libResult.result;
此工具调用示例的完整源代码可在 VS Code 扩展示例存储库中找到。
自行实现工具调用
对于更高级的场景,您也可以自行实现工具调用。您可以选择使用 @vscode/prompt-tsx 库来构建 LLM 提示。通过自行实现工具调用,您可以更好地控制工具调用过程。例如,执行额外的验证或在将工具响应发送给 LLM 之前以特定方式处理它们。
查看在 VS Code 扩展示例存储库中使用 prompt-tsx 实现工具调用的完整源代码。
衡量成功
我们建议您通过为 Unhelpful(无帮助)用户反馈事件以及参与者处理的请求总数添加遥测日志来衡量参与者的成功与否。初始参与者成功指标可定义为:unhelpful_feedback_count / total_requests。
const logger = vscode.env.createTelemetryLogger({
// telemetry logging implementation goes here
});
cat.onDidReceiveFeedback((feedback: vscode.ChatResultFeedback) => {
// Log chat result feedback to be able to compute the success metric of the participant
logger.logUsage('chatResultFeedback', {
kind: feedback.kind
});
});
任何其他用户与您的聊天响应的交互都应被衡量为正面指标(例如,用户选择了在聊天响应中生成的按钮)。在使用 AI 时,通过遥测衡量成功至关重要,因为这是一种非确定性技术。进行实验、衡量并迭代改进您的参与者,以确保良好的用户体验。
准则和约定
准则
聊天参与者不应仅仅是问答机器人。在构建聊天参与者时,要发挥创造力,利用现有的 VS Code API 在 VS Code 中创建丰富的集成。用户也喜欢丰富便捷的交互,例如响应中的按钮、将用户带到聊天中参与者的菜单项。思考 AI 可以帮助用户的现实生活场景。
并不是每个扩展都有必要贡献聊天参与者。在聊天中拥有过多的参与者可能会导致糟糕的用户体验。当您想要控制整个提示(包括给语言模型的指令)时,聊天参与者是最好的选择。您可以重用精心制作的 Copilot 系统消息,并可以为其他参与者贡献上下文。
例如,语言扩展(如 C++ 扩展)可以通过其他多种方式做出贡献:
- 贡献能够将语言服务智能带入用户查询的工具。例如,C++ 扩展可以将
#cpp工具解析为工作区的 C++ 状态。这为 Copilot 语言模型提供了正确的 C++ 上下文,从而提高 Copilot 对 C++ 回答的质量。 - 贡献使用语言模型的智能操作(可选地结合传统语言服务知识),以提供出色的用户体验。例如,C++ 可能已经提供了“提取到方法”智能操作,它使用语言模型为新方法生成合适的默认名称。
如果聊天扩展即将执行昂贵的操作,或者即将编辑/删除无法撤销的内容,则应明确征求用户同意。为了获得出色的用户体验,我们不建议扩展贡献多个聊天参与者。每个扩展最多一个聊天参与者是一种在 UI 中可以很好扩展的简单模型。
聊天参与者命名规范
| 属性 | 描述 | 命名准则 |
|---|---|---|
id |
聊天参与者的全局唯一标识符 |
|
|
聊天参与者的名称,用户通过 @ 符号引用 |
|
fullName |
(可选)参与者的全名,显示为来自该参与者的响应标签 |
|
描述 |
(可选)聊天参与者功能的简短描述,显示为聊天输入框中或参与者列表中的占位符文本 |
|
在任何面向用户的元素(如属性、聊天响应或聊天用户界面)中引用聊天参与者时,建议不要使用 participant(参与者)一词,因为它是 API 的名称。例如,@cat 扩展可以称为“GitHub Copilot 的 Cat 扩展”。
斜杠命令命名规范
| 属性 | 描述 | 命名准则 |
|---|---|---|
|
斜杠命令名称,用户通过 / 符号引用 |
|
描述 |
(可选)斜杠命令功能的简短描述,显示在聊天输入框中或参与者和命令列表中 |
|
发布您的扩展
创建 AI 扩展后,您可以将其发布到 Visual Studio Marketplace
- 在发布到 VS Marketplace 之前,我们建议您阅读 Microsoft AI 工具和实践指南。这些指南提供了负责任地开发和使用 AI 技术的最佳实践。
- 通过发布到 VS Marketplace,您的扩展将遵循 GitHub Copilot 可扩展性可接受的开发和使用政策。
- 按照发布扩展中的描述上传到 Marketplace。
- 如果您的扩展已经提供了除聊天以外的功能,我们建议您不要在扩展清单中引入对 GitHub Copilot 的扩展依赖。这确保了不使用 GitHub Copilot 的扩展用户可以在无需安装 GitHub Copilot 的情况下使用非聊天功能。
通过 GitHub Apps 扩展 GitHub Copilot
或者,也可以通过创建在聊天视图中贡献聊天参与者的 GitHub App 来扩展 GitHub Copilot。GitHub App 由服务支持,并适用于所有 GitHub Copilot 表面,如 github.com、Visual Studio 或 VS Code。另一方面,GitHub Apps 不能完全访问 VS Code API。要了解更多关于通过 GitHub App 扩展 GitHub Copilot 的信息,请参阅 GitHub 文档。
使用语言模型
聊天参与者可以使用多种方式利用语言模型。一些参与者仅使用语言模型来获取自定义提示的答案,例如示例聊天参与者。其他参与者则更高级,表现得像自主代理,在语言模型的帮助下调用多个工具。这种高级参与者的一个例子是内置的 @workspace,它了解您的工作区并可以回答有关它的问题。在内部,@workspace 由多种工具提供支持:GitHub 的知识图谱,结合语义搜索、本地代码索引和 VS Code 的语言服务。