Skip to content

Latest commit

 

History

History
791 lines (589 loc) · 31.5 KB

File metadata and controls

791 lines (589 loc) · 31.5 KB

Streaming Session Events

Every action the Copilot agent takes — thinking, writing code, running tools — is emitted as a session event you can subscribe to. This guide is a field-level reference for each event type so you know exactly what data to expect without reading the SDK source.

Overview

When streaming: true is set on a session, the SDK emits ephemeral events in real time (deltas, progress updates) alongside persisted events (complete messages, tool results). All events share a common envelope and carry a data payload whose shape depends on the event type.

sequenceDiagram
    participant App as Your App
    participant SDK as SDK Session
    participant Agent as Copilot Agent

    App->>SDK: send({ prompt })
    SDK->>Agent: JSON-RPC

    Agent-->>SDK: assistant.turn_start
    SDK-->>App: event

    loop Streaming response
        Agent-->>SDK: assistant.message_delta (ephemeral)
        SDK-->>App: event
    end

    Agent-->>SDK: assistant.message
    SDK-->>App: event

    loop Tool execution
        Agent-->>SDK: tool.execution_start
        SDK-->>App: event
        Agent-->>SDK: tool.execution_complete
        SDK-->>App: event
    end

    Agent-->>SDK: assistant.turn_end
    SDK-->>App: event

    Agent-->>SDK: session.idle (ephemeral)
    SDK-->>App: event
Loading
Concept Description
Ephemeral event Transient; streamed in real time but not persisted to the session log. Not replayed on session resume.
Persisted event Saved to the session event log on disk. Replayed when resuming a session.
Delta event An ephemeral streaming chunk (text or reasoning). Accumulate deltas to build the complete content.
parentId chain Each event's parentId points to the previous event, forming a linked list you can walk.

Event Envelope

Every session event, regardless of type, includes these fields:

Field Type Description
id string (UUID v4) Unique event identifier
timestamp string (ISO 8601) When the event was created
parentId string | null ID of the previous event in the chain; null for the first event
ephemeral boolean? true for transient events; absent or false for persisted events
type string Event type discriminator (see tables below)
data object Event-specific payload

Subscribing to Events

Node.js / 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"
)

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

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

	session.On(func(event copilot.SessionEvent) {
		if event.Type == "assistant.message_delta" {
			fmt.Print(*event.Data.DeltaContent)
		}
	})
	_ = session
}
session.On(func(event copilot.SessionEvent) {
    if event.Type == "assistant.message_delta" {
        fmt.Print(*event.Data.DeltaContent)
    }
})
.NET
using GitHub.Copilot.SDK;

public static class StreamingEventsExample
{
    public static async Task Example(CopilotSession session)
    {
        session.On(evt =>
        {
            if (evt is AssistantMessageDeltaEvent delta)
            {
                Console.Write(delta.Data.DeltaContent);
            }
        });
    }
}
session.On(evt =>
{
    if (evt is AssistantMessageDeltaEvent delta)
    {
        Console.Write(delta.Data.DeltaContent);
    }
});

Tip (Python / Go): These SDKs use a single Data class/struct with all possible fields as optional/nullable. Only the fields listed in the tables below are populated for each event type — the rest will be None / nil.

Tip (.NET): The .NET SDK uses separate, strongly-typed data classes per event (e.g., AssistantMessageDeltaData), so only the relevant fields exist on each type.

Tip (TypeScript): The TypeScript SDK uses a discriminated union — when you match on event.type, the data payload is automatically narrowed to the correct shape.


Assistant Events

These events track the agent's response lifecycle — from turn start through streaming chunks to the final message.

assistant.turn_start

Emitted when the agent begins processing a turn.

Data Field Type Required Description
turnId string Turn identifier (typically a stringified turn number)
interactionId string CAPI interaction ID for telemetry correlation

assistant.intent

Ephemeral. Short description of what the agent is currently doing, updated as it works.

Data Field Type Required Description
intent string Human-readable intent (e.g., "Exploring codebase")

assistant.reasoning

Complete extended thinking block from the model. Emitted after reasoning is finished.

Data Field Type Required Description
reasoningId string Unique identifier for this reasoning block
content string The complete extended thinking text

assistant.reasoning_delta

Ephemeral. Incremental chunk of the model's extended thinking, streamed in real time.

Data Field Type Required Description
reasoningId string Matches the corresponding assistant.reasoning event
deltaContent string Text chunk to append to reasoning content

assistant.message

The assistant's complete response for this LLM call. May include tool invocation requests.

Data Field Type Required Description
messageId string Unique identifier for this message
content string The assistant's text response
toolRequests ToolRequest[] Tool calls the assistant wants to make (see below)
reasoningOpaque string Encrypted extended thinking (Anthropic models); session-bound
reasoningText string Readable reasoning text from extended thinking
encryptedContent string Encrypted reasoning content (OpenAI models); session-bound
phase string Generation phase (e.g., "thinking" vs "response")
outputTokens number Actual output token count from the API response
interactionId string CAPI interaction ID for telemetry
parentToolCallId string Set when this message originates from a sub-agent

ToolRequest fields:

Field Type Required Description
toolCallId string Unique ID for this tool call
name string Tool name (e.g., "bash", "edit", "grep")
arguments object Parsed arguments for the tool
type "function" | "custom" Call type; defaults to "function" when absent

assistant.message_delta

Ephemeral. Incremental chunk of the assistant's text response, streamed in real time.

Data Field Type Required Description
messageId string Matches the corresponding assistant.message event
deltaContent string Text chunk to append to the message
parentToolCallId string Set when originating from a sub-agent

assistant.turn_end

Emitted when the agent finishes a turn (all tool executions complete, final response delivered).

Data Field Type Required Description
turnId string Matches the corresponding assistant.turn_start event

assistant.usage

Ephemeral. Token usage and cost information for an individual API call.

Data Field Type Required Description
model string Model identifier (e.g., "gpt-4.1")
inputTokens number Input tokens consumed
outputTokens number Output tokens produced
cacheReadTokens number Tokens read from prompt cache
cacheWriteTokens number Tokens written to prompt cache
cost number Model multiplier cost for billing
duration number API call duration in milliseconds
initiator string What triggered this call (e.g., "sub-agent"); absent for user-initiated
apiCallId string Completion ID from the provider (e.g., chatcmpl-abc123)
providerCallId string GitHub request tracing ID (x-github-request-id)
parentToolCallId string Set when usage originates from a sub-agent
quotaSnapshots Record<string, QuotaSnapshot> Per-quota resource usage, keyed by quota identifier
copilotUsage CopilotUsage Itemized token cost breakdown from the API

assistant.streaming_delta

Ephemeral. Low-level network progress indicator — total bytes received from the streaming API response.

Data Field Type Required Description
totalResponseSizeBytes number Cumulative bytes received so far

Tool Execution Events

These events track the full lifecycle of each tool invocation — from the model requesting a tool call through execution to completion.

tool.execution_start

Emitted when a tool begins executing.

Data Field Type Required Description
toolCallId string Unique identifier for this tool call
toolName string Name of the tool (e.g., "bash", "edit", "grep")
arguments object Parsed arguments passed to the tool
mcpServerName string MCP server name, when the tool is provided by an MCP server
mcpToolName string Original tool name on the MCP server
parentToolCallId string Set when invoked by a sub-agent

tool.execution_partial_result

Ephemeral. Incremental output from a running tool (e.g., streaming bash output).

Data Field Type Required Description
toolCallId string Matches the corresponding tool.execution_start
partialOutput string Incremental output chunk

tool.execution_progress

Ephemeral. Human-readable progress status from a running tool (e.g., MCP server progress notifications).

Data Field Type Required Description
toolCallId string Matches the corresponding tool.execution_start
progressMessage string Progress status message

tool.execution_complete

Emitted when a tool finishes executing — successfully or with an error.

Data Field Type Required Description
toolCallId string Matches the corresponding tool.execution_start
success boolean Whether execution succeeded
model string Model that generated this tool call
interactionId string CAPI interaction ID
isUserRequested boolean true when the user explicitly requested this tool call
result Result Present on success (see below)
error { message, code? } Present on failure
toolTelemetry object Tool-specific telemetry (e.g., CodeQL check counts)
parentToolCallId string Set when invoked by a sub-agent

Result fields:

Field Type Required Description
content string Concise result sent to the LLM (may be truncated for token efficiency)
detailedContent string Full result for display, preserving complete content like diffs
contents ContentBlock[] Structured content blocks (text, terminal, image, audio, resource)

tool.user_requested

Emitted when the user explicitly requests a tool invocation (rather than the model choosing to call one).

Data Field Type Required Description
toolCallId string Unique identifier for this tool call
toolName string Name of the tool the user wants to invoke
arguments object Arguments for the invocation

Session Lifecycle Events

session.idle

Ephemeral. The agent has finished all processing and is ready for the next message. This is the signal that a turn is fully complete.

Data Field Type Required Description
backgroundTasks BackgroundTasks Background agents/shells still running when the agent became idle

session.error

An error occurred during session processing.

Data Field Type Required Description
errorType string Error category (e.g., "authentication", "quota", "rate_limit")
message string Human-readable error message
stack string Error stack trace
statusCode number HTTP status code from the upstream request
providerCallId string GitHub request tracing ID for server-side log correlation

session.compaction_start

Context window compaction has begun. Data payload is empty ({}).

session.compaction_complete

Context window compaction finished.

Data Field Type Required Description
success boolean Whether compaction succeeded
error string Error message if compaction failed
preCompactionTokens number Tokens before compaction
postCompactionTokens number Tokens after compaction
preCompactionMessagesLength number Message count before compaction
messagesRemoved number Messages removed
tokensRemoved number Tokens removed
summaryContent string LLM-generated summary of compacted history
checkpointNumber number Checkpoint snapshot number created for recovery
checkpointPath string File path where the checkpoint was stored
compactionTokensUsed { input, output, cachedInput } Token usage for the compaction LLM call
requestId string GitHub request tracing ID for the compaction call

session.title_changed

Ephemeral. The session's auto-generated title was updated.

Data Field Type Required Description
title string New session title

session.context_changed

The session's working directory or repository context changed.

Data Field Type Required Description
cwd string Current working directory
gitRoot string Git repository root
repository string Repository in "owner/name" format
branch string Current git branch

session.usage_info

Ephemeral. Context window utilization snapshot.

Data Field Type Required Description
tokenLimit number Maximum tokens for the model's context window
currentTokens number Current tokens in the context window
messagesLength number Current message count in the conversation

session.task_complete

The agent has completed its assigned task.

Data Field Type Required Description
summary string Summary of the completed task

session.shutdown

The session has ended.

Data Field Type Required Description
shutdownType "routine" | "error" Normal shutdown or crash
errorReason string Error description when shutdownType is "error"
totalPremiumRequests number Total premium API requests used
totalApiDurationMs number Cumulative API call time in milliseconds
sessionStartTime number Unix timestamp (ms) when the session started
codeChanges { linesAdded, linesRemoved, filesModified } Aggregate code change metrics
modelMetrics Record<string, ModelMetric> Per-model usage breakdown
currentModel string Model selected at shutdown time

Permission & User Input Events

These events are emitted when the agent needs approval or input from the user before continuing.

permission.requested

Ephemeral. The agent needs permission to perform an action (run a command, write a file, etc.).

Data Field Type Required Description
requestId string Use this to respond via session.respondToPermission()
permissionRequest PermissionRequest Details of the permission being requested

The permissionRequest is a discriminated union on kind:

kind Key Fields Description
"shell" fullCommandText, intention, commands[], possiblePaths[] Execute a shell command
"write" fileName, diff, intention, newFileContents? Write/modify a file
"read" path, intention Read a file or directory
"mcp" serverName, toolName, toolTitle, args?, readOnly Call an MCP tool
"url" url, intention Fetch a URL
"memory" subject, fact, citations Store a memory
"custom-tool" toolName, toolDescription, args? Call a custom tool

All kind variants also include an optional toolCallId linking back to the tool call that triggered the request.

permission.completed

Ephemeral. A permission request was resolved.

Data Field Type Required Description
requestId string Matches the corresponding permission.requested
result.kind string One of: "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

Ephemeral. The agent is asking the user a question.

Data Field Type Required Description
requestId string Use this to respond via session.respondToUserInput()
question string The question to present to the user
choices string[] Predefined choices for the user
allowFreeform boolean Whether free-form text input is allowed

user_input.completed

Ephemeral. A user input request was resolved.

Data Field Type Required Description
requestId string Matches the corresponding user_input.requested

elicitation.requested

Ephemeral. The agent needs structured form input from the user (MCP elicitation protocol).

Data Field Type Required Description
requestId string Use this to respond via session.respondToElicitation()
message string Description of what information is needed
mode "form" Elicitation mode (currently only "form")
requestedSchema { type: "object", properties, required? } JSON Schema describing the form fields

elicitation.completed

Ephemeral. An elicitation request was resolved.

Data Field Type Required Description
requestId string Matches the corresponding elicitation.requested

Sub-Agent & Skill Events

subagent.started

A custom agent was invoked as a sub-agent.

Data Field Type Required Description
toolCallId string Parent tool call that spawned this sub-agent
agentName string Internal name of the sub-agent
agentDisplayName string Human-readable display name
agentDescription string Description of what the sub-agent does

subagent.completed

A sub-agent finished successfully.

Data Field Type Required Description
toolCallId string Matches the corresponding subagent.started
agentName string Internal name
agentDisplayName string Display name

subagent.failed

A sub-agent encountered an error.

Data Field Type Required Description
toolCallId string Matches the corresponding subagent.started
agentName string Internal name
agentDisplayName string Display name
error string Error message

subagent.selected

A custom agent was selected (inferred) to handle the current request.

Data Field Type Required Description
agentName string Internal name of the selected agent
agentDisplayName string Display name
tools string[] | null Tool names available to this agent; null for all tools

subagent.deselected

A custom agent was deselected, returning to the default agent. Data payload is empty ({}).

skill.invoked

A skill was activated for the current conversation.

Data Field Type Required Description
name string Skill name
path string File path to the SKILL.md definition
content string Full skill content injected into the conversation
allowedTools string[] Tools auto-approved while this skill is active
pluginName string Plugin the skill originated from
pluginVersion string Plugin version

Other Events

abort

The current turn was aborted.

Data Field Type Required Description
reason string Why the turn was aborted (e.g., "user initiated")

user.message

The user sent a message. Recorded for the session timeline.

Data Field Type Required Description
content string The user's message text
transformedContent string Transformed version after preprocessing
attachments Attachment[] File, directory, selection, or GitHub reference attachments
source string Message source identifier
agentMode string Agent mode: "interactive", "plan", "autopilot", or "shell"
interactionId string CAPI interaction ID

system.message

A system or developer prompt was injected into the conversation.

Data Field Type Required Description
content string The prompt text
role "system" | "developer" Message role
name string Source identifier
metadata { promptVersion?, variables? } Prompt template metadata

external_tool.requested

Ephemeral. The agent wants to invoke an external tool (one provided by the SDK consumer).

Data Field Type Required Description
requestId string Use this to respond via session.respondToExternalTool()
sessionId string Session this request belongs to
toolCallId string Tool call ID for this invocation
toolName string Name of the external tool
arguments object Arguments for the tool

external_tool.completed

Ephemeral. An external tool request was resolved.

Data Field Type Required Description
requestId string Matches the corresponding external_tool.requested

exit_plan_mode.requested

Ephemeral. The agent has created a plan and wants to exit plan mode.

Data Field Type Required Description
requestId string Use this to respond via session.respondToExitPlanMode()
summary string Summary of the plan
planContent string Full plan file content
actions string[] Available user actions (e.g., approve, edit, reject)
recommendedAction string Suggested action

exit_plan_mode.completed

Ephemeral. An exit plan mode request was resolved.

Data Field Type Required Description
requestId string Matches the corresponding exit_plan_mode.requested

command.queued

Ephemeral. A slash command was queued for execution.

Data Field Type Required Description
requestId string Use this to respond via session.respondToQueuedCommand()
command string The slash command text (e.g., /help, /clear)

command.completed

Ephemeral. A queued command was resolved.

Data Field Type Required Description
requestId string Matches the corresponding command.queued

Quick Reference: Agentic Turn Flow

A typical agentic turn emits events in this order:

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)

All Event Types at a Glance

Event Type Ephemeral Category Key Data Fields
assistant.turn_start Assistant turnId, interactionId?
assistant.intent Assistant intent
assistant.reasoning Assistant reasoningId, content
assistant.reasoning_delta Assistant reasoningId, deltaContent
assistant.streaming_delta Assistant totalResponseSizeBytes
assistant.message Assistant messageId, content, toolRequests?, outputTokens?, phase?
assistant.message_delta Assistant messageId, deltaContent, parentToolCallId?
assistant.turn_end Assistant turnId
assistant.usage Assistant model, inputTokens?, outputTokens?, cost?, duration?
tool.user_requested Tool toolCallId, toolName, arguments?
tool.execution_start Tool toolCallId, toolName, arguments?, mcpServerName?
tool.execution_partial_result Tool toolCallId, partialOutput
tool.execution_progress Tool toolCallId, progressMessage
tool.execution_complete Tool toolCallId, success, result?, error?
session.idle Session backgroundTasks?
session.error Session errorType, message, statusCode?
session.compaction_start Session (empty)
session.compaction_complete Session success, preCompactionTokens?, summaryContent?
session.title_changed Session title
session.context_changed Session cwd, gitRoot?, repository?, branch?
session.usage_info Session tokenLimit, currentTokens, messagesLength
session.task_complete Session summary?
session.shutdown Session shutdownType, codeChanges, modelMetrics
permission.requested Permission requestId, permissionRequest
permission.completed Permission requestId, result.kind
user_input.requested User Input requestId, question, choices?
user_input.completed User Input requestId
elicitation.requested User Input requestId, message, requestedSchema
elicitation.completed User Input requestId
subagent.started Sub-Agent toolCallId, agentName, agentDisplayName
subagent.completed Sub-Agent toolCallId, agentName, agentDisplayName
subagent.failed Sub-Agent toolCallId, agentName, error
subagent.selected Sub-Agent agentName, agentDisplayName, tools
subagent.deselected Sub-Agent (empty)
skill.invoked Skill name, path, content, allowedTools?
abort Control reason
user.message User content, attachments?, agentMode?
system.message System content, role
external_tool.requested External Tool requestId, toolName, arguments?
external_tool.completed External Tool requestId
command.queued Command requestId, command
command.completed Command requestId
exit_plan_mode.requested Plan Mode requestId, summary, planContent, actions
exit_plan_mode.completed Plan Mode requestId