Skip to main content

流式会话事件

Copilot 代理执行的每个操作——思考、编写代码、运行工具——都会以 session 事件 的形式发出,供你订阅。 本指南是每个事件类型的字段级参考,因此你确切地知道在未读取 SDK 源的情况下预期的数据。

概述

设置在会话上的 streaming: true,SDK 会实时发出 临时 事件(增量、进度更新)以及 持久 事件(完整的消息、工具结果)。 所有事件共享一个公用信封,并携带一个载荷,其形状取决于事件 data

关系图:显示描述的过程的序列图。

概念Description
临时事件瞬时; 实时流传,但不持久保存到会话日志。 会话恢复时未重播。
持久化事件保存到磁盘上的会话事件日志。 恢复会话时重播。
Delta 事件临时数据流块(数据或推理)。 累积增量以生成完整内容。
parentId每个事件的parentId指向前一个事件,形成一个可以遍历的链表。

事件封装

无论类型如何,每个会话事件都包含以下字段:

领域类型Description
id
string (UUID v4)唯一事件标识符
timestamp
string (ISO 8601)创建事件时
parentIdstring | null链中上一个事件的 ID;对于第一个事件使用 null
ephemeralboolean?
true 用于暂时性事件; 缺失或 false 持久化事件
typestring事件类型鉴别器(请参阅下表)
dataobject特定于事件的有效负载

订阅事件

TypeScript
// All events
session.on((event) => {
    console.log(event.type, event.data);
});

// Specific event type — data is narrowed automatically
session.on("assistant.message_delta", (event) => {
    process.stdout.write(event.data.deltaContent);
});
Python
from copilot import CopilotClient
from copilot.generated.session_events import SessionEventType

client = CopilotClient()

session = None  # assume session is created elsewhere

def handle(event):
    if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
        print(event.data.delta_content, end="", flush=True)

# session.on(handle)
from copilot.generated.session_events import SessionEventType

def handle(event):
    if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
        print(event.data.delta_content, end="", flush=True)

session.on(handle)
Go
package main

import (
    "context"
    "fmt"
    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

func main() {
    ctx := context.Background()
    client := copilot.NewClient(nil)

    session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
        Model:     "gpt-4.1",
        Streaming: copilot.Bool(true),
        OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
            return &rpc.PermissionDecisionApproveOnce{}, nil
        },
    })

    session.On(func(event copilot.SessionEvent) {
        if d, ok := event.Data.(*copilot.AssistantMessageDeltaData); ok {
            fmt.Print(d.DeltaContent)
        }
    })
    _ = session
}
session.On(func(event copilot.SessionEvent) {
    if d, ok := event.Data.(*copilot.AssistantMessageDeltaData); ok {
        fmt.Print(d.DeltaContent)
    }
})
.NET
using GitHub.Copilot;

public static class StreamingEventsExample
{
    public static async Task Example(CopilotSession session)
    {
        session.On<SessionEvent>(evt =>
        {
            if (evt is AssistantMessageDeltaEvent delta)
            {
                Console.Write(delta.Data.DeltaContent);
            }
        });
    }
}
session.On<SessionEvent>(evt =>
{
    if (evt is AssistantMessageDeltaEvent delta)
    {
        Console.Write(delta.Data.DeltaContent);
    }
});
Java
// All events
session.on(event -> System.out.println(event.getType()));

// Specific event type — data is narrowed to the matching class
session.on(AssistantMessageDeltaEvent.class, event ->
    System.out.print(event.getData().deltaContent())
);

提示

(Python/Go) 这些 SDK 将所有可能的字段用作可选/可为 null 的单个 Data 类/结构。 只有下表中列出的字段会针对每个事件类型进行填充,其余字段会保持为None / nil

(.NET) .NET SDK 为每个事件使用单独的强类型数据类(例如,AssistantMessageDeltaData),因此每个类型上仅存在相关字段。

(TypeScript) TypeScript SDK 使用可辨别联合——当你匹配 event.type 时,data 负载会自动缩窄为正确的类型形状。

助理活动

这些事件跟踪代理程序的整个响应生命周期【从轮次开始,经过流式处理区块,直至最终消息】。

assistant.turn_start

代理开始处理轮次时发出。

数据字段类型必需Description
turnIdstring轮次标识符(通常是字符串化的轮次编号)
interactionIdstring
用于遥测关联的 CAPI 交互 ID

assistant.intent

短暂。 代理当前正在执行任务的简短描述,在其运行过程中不断更新。

数据字段类型必需Description
intentstring人类可读的意图(例如“浏览代码库”)

assistant.reasoning

完成从模型中提取的扩展思维块。 推理完成后发出。

数据字段类型必需Description
reasoningIdstring此推理块的唯一标识符
contentstring完整的扩展思维文本

assistant.reasoning_delta

短暂。 模型扩展推理的增量块,实时流式传输。

数据字段类型必需Description
reasoningIdstring匹配相应的 assistant.reasoning 事件
deltaContentstring要附加到推理内容的文本片段

assistant.message

此 LLM 呼叫的助理的完整响应。 可能包括工具调用请求。

数据字段类型必需Description
messageIdstring此消息的唯一标识符
contentstring助手的文本响应
toolRequestsToolRequest[]
助理拟进行的工具调用(请参阅下文)
reasoningOpaquestring
加密扩展思维(人类模型):会话绑定
reasoningTextstring
扩展思维中的可读推理文本
encryptedContentstring
加密推理内容(OpenAI 模型):会话绑定
phasestring
生成阶段(例如, "thinking" vs "response"
outputTokensnumber
来自 API 响应的实际输出令牌计数
interactionIdstring
用于遥测的 CAPI 交互 ID
parentToolCallIdstring
当此消息源自子代理时进行设置

** ToolRequest 领域:**

领域类型必需Description
toolCallIdstring此工具调用的唯一 ID
namestring工具名称(例如, "bash""edit""grep"
argumentsobject
用于工具的解析参数
type"function" | "custom"
调用类型;如果缺失,默认为"function"

assistant.message_delta

短暂。 助理文本响应的增量区块,实时流式传输。

数据字段类型必需Description
messageIdstring匹配相应的 assistant.message 事件
deltaContentstring要追加到消息的文本片段
parentToolCallIdstring
当由子代理发起时设定

assistant.turn_end

代理完成轮次时发出(所有工具执行完成,最终响应已传递)。

数据字段类型必需Description
turnIdstring匹配相应的 assistant.turn_start 事件

assistant.usage

短暂。 单个 API 调用的令牌使用情况和成本信息。

数据字段类型必需Description
modelstring模型标识符(例如 "gpt-4.1"
inputTokensnumber
消耗的输入令牌
outputTokensnumber
生成的输出令牌
cacheReadTokensnumber
从提示缓存中读取的令牌
cacheWriteTokensnumber
写入以提示缓存的令牌
costnumber
计费的模型乘数成本
durationnumber
API 调用持续时间(以毫秒为单位)
initiatorstring
触发此次调用的原因(例如 "sub-agent");如果是用户发起的,则为空
apiCallIdstring
提供程序的完成 ID(例如 chatcmpl-abc123
providerCallIdstring
GitHub请求跟踪 ID (x-github-request-id
parentToolCallIdstring
当使用情况源自子代理时进行设置
quotaSnapshotsRecord<string, QuotaSnapshot>
按配额标识符记录的每个配额的资源使用情况
copilotUsageCopilotUsage
API 中的分项令牌成本明细

assistant.streaming_delta

短暂。 低级别网络进度指示器 - 从流式处理 API 响应接收的总字节数。

数据字段类型必需Description
totalResponseSizeBytesnumber到目前为止收到的累积字节数

工具执行事件

这些事件跟踪每个工具调用的完整生命周期,从模型请求工具调用到执行和结束。

tool.execution_start

当工具开始执行时发出。

数据字段类型必需Description
toolCallIdstring此工具调用的唯一标识符
toolNamestring工具的名称(例如,"bash""edit"``"grep"
argumentsobject
传递给工具的已分析参数
mcpServerNamestring
MCP 服务器名称,当 MCP 服务器提供该工具时
mcpToolNamestring
MCP 服务器上的原始工具名称
parentToolCallIdstring
在子代理调用时设置

tool.execution_partial_result

短暂。 运行中工具的增量输出(例如 bash 的流式输出)。

数据字段类型必需Description
toolCallIdstring匹配相应的 tool.execution_start
partialOutputstring增量输出区块

tool.execution_progress

短暂。 由运行中的工具提供的人类可读的进度状态(例如 MCP 服务器进度通知)。

数据字段类型必需Description
toolCallIdstring匹配相应的 tool.execution_start
progressMessagestring进度状态消息

tool.execution_complete

当工具完成执行时发出 — 成功或出错。

数据字段类型必需Description
toolCallIdstring匹配相应的 tool.execution_start
successboolean执行是否成功
modelstring
生成此工具调用的模型
interactionIdstring
CAPI 交互标识
isUserRequestedboolean
true 当用户显式请求此工具调用时
resultResult
显示成功(请参阅下文)
error{ message, code? }
失败时显示
toolTelemetryobject
工具特定的遥测数据(例如,CodeQL 检查次数)
parentToolCallIdstring
在子代理调用时设置

** Result 领域:**

领域类型必需Description
contentstring发送到 LLM 的简洁结果(可能会因令牌效率而截断)
detailedContentstring
显示的完整结果,包括保留差异等完整细节
contentsContentBlock[]
结构化内容块(文本、终端、图像、音频、资源)

tool.user_requested

当用户显式请求工具调用(而不是由模型选择调用时)发出。

数据字段类型必需Description
toolCallIdstring此工具调用的唯一标识符
toolNamestring用户要调用的工具的名称
argumentsobject
函数调用的参数

会话生命周期事件

session.idle

短暂。 代理已完成所有处理,并已准备好下一条消息。 这是转弯已完全完成的信号。

数据字段类型必需Description
backgroundTasksBackgroundTasks
后台代理/shell 在代理变得空闲时仍然运行中

session.error

会话处理期间出错。

数据字段类型必需Description
errorTypestring错误类别(例如,"authentication"、、 "quota"``"rate_limit"
messagestring人类可读错误信息
stackstring
错误堆栈跟踪
statusCodenumber
来自上游请求的 HTTP 状态代码
providerCallIdstring
用于服务器端日志关联的 GitHub 请求跟踪 ID

session.compaction_start

上下文窗口压缩已经开始。 数据有效负载为空 ({}

session.compaction_complete

上下文窗口压缩已完成。

数据字段类型必需Description
successboolean压缩是否成功
errorstring
压缩失败时出现错误消息
preCompactionTokensnumber
压缩前的令牌
postCompactionTokensnumber
压缩后的令牌
preCompactionMessagesLengthnumber
压缩前的消息计数
messagesRemovednumber
已删除邮件
tokensRemovednumber
已删除令牌
summaryContentstring
LLM 生成的压缩历史记录摘要
checkpointNumbernumber
为恢复创建的检查点快照编号
checkpointPathstring
存储检查点的文件路径
compactionTokensUsed{ input, output, cachedInput }
压缩LLM调用中的令牌使用情况
requestIdstring
GitHub压缩调用的请求跟踪 ID

session.title_changed

短暂。 会话自动生成的标题已更新。

数据字段类型必需Description
titlestring新会话标题

session.context_changed

会话的工作目录或存储库上下文已更改。

数据字段类型必需Description
cwdstring当前工作目录
gitRootstring
Git 存储库根目录
repositorystring
"owner/name" 格式的存储库
branchstring
当前 Git 分支

session.usage_info

短暂。 上下文窗口利用率快照。

数据字段类型必需Description
tokenLimitnumber模型上下文窗口的最大标记数
currentTokensnumber上下文窗口中的当前标记
messagesLengthnumber对话中的当前消息计数

session.task_complete

代理已完成其分配的任务。

数据字段类型必需Description
summarystring
已完成任务的摘要

session.shutdown

会话已结束。

数据字段类型必需Description
shutdownType"routine" | "error"正常关闭或崩溃
errorReasonstring
shutdownType"error" 时的错误描述
totalPremiumRequestsnumber使用的高级 API 请求总数
totalApiDurationMsnumber累积 API 调用时间(以毫秒为单位)
sessionStartTimenumber会话启动时的 Unix 时间戳 (ms)
codeChanges{ linesAdded, linesRemoved, filesModified }代码更改的聚合指标
modelMetricsRecord<string, ModelMetric>按模型使用情况细分
currentModelstring
关闭时选择的模型

权限和用户输入事件

在继续操作之前,当代理需要用户批准或输入时,将发出这些事件。

permission.requested

短暂。 代理需要权限才能执行操作(运行命令、写入文件等)。

数据字段类型必需Description
requestIdstring使用该功能通过 session.respondToPermission() 进行响应
permissionRequestPermissionRequest正在请求的权限的详细信息

permissionRequest是一个区分联合体kind

kind关键字段Description
"shell"
fullCommandTextintentioncommands[]possiblePaths[]执行 shell 命令
"write"
fileNamediffintentionnewFileContents?写入/修改文件
"read"
pathintention读取文件或目录
"mcp"
serverNametoolNametoolTitleargs?readOnly调用 MCP 工具
"url"
urlintention获取 URL
"memory"
subjectfactcitations存储内存
"custom-tool"
toolNametoolDescriptionargs?调用自定义工具

所有 kind 变体均包含一个可选的 toolCallId 链接,其指向触发请求的工具调用。

permission.completed

短暂。 权限请求已解决。

数据字段类型必需Description
requestIdstring匹配相应的 permission.requested
result.kindstring其中之一:"approved"、、"denied-by-rules"``"denied-interactively-by-user""denied-no-approval-rule-and-could-not-request-from-user""denied-by-content-exclusion-policy"

user_input.requested

短暂。 代理正在向用户提问。

数据字段类型必需Description
requestIdstring使用该功能通过 session.respondToUserInput() 进行响应
questionstring向用户呈现的问题
choicesstring[]
用户的预定义选项
allowFreeformboolean
是否允许自由格式文本输入

user_input.completed

短暂。 解决了用户输入请求。

数据字段类型必需Description
requestIdstring匹配相应的 user_input.requested

elicitation.requested

短暂。 代理需要用户(MCP 引证协议)的结构化表单输入。

数据字段类型必需Description
requestIdstring使用该功能通过 session.respondToElicitation() 进行响应
messagestring所需信息的说明
mode"form"
引证模式(目前仅 "form"
requestedSchema{ type: "object", properties, required? }描述窗体字段的 JSON 架构

elicitation.completed

短暂。 已解析引证请求。

数据字段类型必需Description
requestIdstring匹配相应的 elicitation.requested

子代理和技能事件

subagent.started

自定义代理被调用为子代理。

数据字段类型必需Description
toolCallIdstring生成此子代理的父工具调用
agentNamestring子代理的内部名称
agentDisplayNamestring人工可读的显示名称
agentDescriptionstring子代理的作用说明

subagent.completed

一个子代理成功完成。

数据字段类型必需Description
toolCallIdstring匹配相应的 subagent.started
agentNamestring内部名称
agentDisplayNamestring显示名称

subagent.failed

子代理遇到错误。

数据字段类型必需Description
toolCallIdstring匹配相应的 subagent.started
agentNamestring内部名称
agentDisplayNamestring显示名称
errorstring错误消息

subagent.selected

已选择自定义代理(推断)来处理当前请求。

数据字段类型必需Description
agentNamestring所选代理的内部名称
agentDisplayNamestring显示名称
toolsstring[] | null此代理可用的工具名称; null 适用于所有工具

subagent.deselected

取消了自定义代理的选择,返回到默认代理。 数据有效负载为空 ({}

skill.invoked

为当前对话激活了技能。

数据字段类型必需Description
namestring技能名称
pathstringSKILL.md 定义的文件路径
contentstring将完整的技能内容注入到对话中
allowedToolsstring[]
此技能处于活动状态时自动批准的工具
pluginNamestring
插件的技术来源于
pluginVersionstring
插件版本

其他事件

abort

当前轮次已中止。

数据字段类型必需Description
reasonstring为什么轮次被中止 (例如, "user initiated"

user.message

用户发送了一条消息。 记录在会话时间线中。

数据字段类型必需Description
contentstring用户的消息内容
transformedContentstring
预处理后的转换版本
attachmentsAttachment[]
文件、目录、所选内容、blob 或 GitHub 引用附件
sourcestring
消息源标识符
agentModestring
代理模式:"interactive"、、"plan"``"autopilot""shell"
interactionIdstring
CAPI 交互标识

system.message

系统或开发人员提示已被注入对话。

数据字段类型必需Description
contentstring提示文本
role"system" | "developer"消息角色
namestring
源标识符
metadata{ promptVersion?, variables? }
提示模板元数据

external_tool.requested

短暂。 代理想要调用外部工具(由 SDK 使用者提供)。

数据字段类型必需Description
requestIdstring使用该功能通过 session.respondToExternalTool() 进行响应
sessionIdstring此请求所属的会话
toolCallIdstring此调用的工具 ID
toolNamestring外部工具的名称
argumentsobject
工具的参数

external_tool.completed

短暂。 解决了外部工具请求。

数据字段类型必需Description
requestIdstring匹配相应的 external_tool.requested

exit_plan_mode.requested

短暂。 代理已创建计划并想要退出计划模式。

数据字段类型必需Description
requestIdstring使用该功能通过 session.respondToExitPlanMode() 进行响应
summarystring计划摘要
planContentstring完整计划文件内容
actionsstring[]可用的用户操作(例如批准、编辑、拒绝)
recommendedActionstring建议的操作

exit_plan_mode.completed

短暂。 已解决退出计划模式请求。

数据字段类型必需Description
requestIdstring匹配相应的 exit_plan_mode.requested

command.queued

短暂。 斜杠命令已进入执行队列。

数据字段类型必需Description
requestIdstring使用该功能通过 session.respondToQueuedCommand() 进行响应
commandstring斜杠命令文本(例如, /help``/clear

command.completed

短暂。 已解析排队命令。

数据字段类型必需Description
requestIdstring匹配相应的 command.queued

快速参考:代理轮次流

典型的代理行为轮次按以下顺序触发事件:

assistant.turn_start          → Turn begins
├── assistant.intent          → What the agent plans to do (ephemeral)
├── assistant.reasoning_delta → Streaming thinking chunks (ephemeral, repeated)
├── assistant.reasoning       → Complete thinking block
├── assistant.message_delta   → Streaming response chunks (ephemeral, repeated)
├── assistant.message         → Complete response (may include toolRequests)
├── assistant.usage           → Token usage for this API call (ephemeral)
│
├── [If tools were requested:]
│   ├── permission.requested  → Needs user approval (ephemeral)
│   ├── permission.completed  → Approval result (ephemeral)
│   ├── tool.execution_start  → Tool begins
│   ├── tool.execution_partial_result  → Streaming tool output (ephemeral, repeated)
│   ├── tool.execution_progress        → Progress updates (ephemeral, repeated)
│   ├── tool.execution_complete        → Tool finished
│   │
│   └── [Agent loops: more reasoning → message → tool calls...]
│
assistant.turn_end            → Turn complete
session.idle                  → Ready for next message (ephemeral)

所有事件类型一目了然

事件类型临时类别关键数据字段
assistant.turn_start
助手
turnIdinteractionId?
assistant.intent助手intent
assistant.reasoning
助手
reasoningIdcontent
assistant.reasoning_delta助手
reasoningIddeltaContent
assistant.streaming_delta助手totalResponseSizeBytes
assistant.message
助手
messageIdcontenttoolRequests?outputTokens?phase?
assistant.message_delta助手
messageIddeltaContentparentToolCallId?
assistant.turn_end
助手turnId
assistant.usage助手
modelinputTokens?outputTokens?cost?duration?
tool.user_requested
工具
toolCallIdtoolNamearguments?
tool.execution_start
工具
toolCallIdtoolNamearguments?mcpServerName?
tool.execution_partial_result工具
toolCallIdpartialOutput
tool.execution_progress工具
toolCallIdprogressMessage
tool.execution_complete
工具
toolCallIdsuccessresult?error?
session.idleSessionbackgroundTasks?
session.error
Session
errorTypemessagestatusCode?
session.compaction_start
Session
(空)
session.compaction_complete
Session
successpreCompactionTokens?summaryContent?
session.title_changedSessiontitle
session.context_changed
Session
cwdgitRoot?repository?branch?
session.usage_infoSession
tokenLimitcurrentTokensmessagesLength
session.task_complete
Sessionsummary?
session.shutdown
Session
shutdownTypecodeChangesmodelMetrics
permission.requested许可
requestIdpermissionRequest
permission.completed许可
requestIdresult.kind
user_input.requested用户输入
requestIdquestionchoices?
user_input.completed用户输入requestId
elicitation.requested用户输入
requestIdmessagerequestedSchema
elicitation.completed用户输入requestId
subagent.started
子代理
toolCallIdagentNameagentDisplayName
subagent.completed
子代理
toolCallIdagentNameagentDisplayName
subagent.failed
子代理
toolCallIdagentNameerror
subagent.selected
子代理
agentNameagentDisplayNametools
subagent.deselected
子代理
(空)
skill.invoked
技能
namepathcontentallowedTools?
abort
控件reason
user.message
User
contentattachments?agentMode?
system.message
系统
contentrole
external_tool.requested外部工具
requestIdtoolNamearguments?
external_tool.completed外部工具requestId
command.queued命令
requestIdcommand
command.completed命令requestId
exit_plan_mode.requested计划模式
requestIdsummaryplanContentactions
exit_plan_mode.completed计划模式requestId