Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/features/custom-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,8 @@ By default, all custom agents are available for automatic selection (`infer: tru

When a sub-agent runs, the parent session emits lifecycle events. Subscribe to these events to build UIs that visualize agent activity.

Sub-agent-originated session events share the parent session stream and include envelope-level `agentId`. Root/main agent events and session-level events omit `agentId`, so renderers can keep the parent response separate from sub-agent traces by checking the event envelope.

### Event types

| Event | Emitted when | Data |
Expand Down
44 changes: 38 additions & 6 deletions docs/features/streaming-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Every session event, regardless of type, includes these fields:
| `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 |
| `agentId` | `string?` | Sub-agent instance ID for sub-agent-originated events; absent for root/main agent and session-level events |
| `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 |
Expand Down Expand Up @@ -217,6 +218,35 @@ session.on(AssistantMessageDeltaEvent.class, event ->
> [!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.

## Render only the parent agent response

Sub-agent events share the parent session stream and include envelope-level `agentId`. Root/main agent events and session-level events omit `agentId`, so main-chat renderers can ignore assistant events where `agentId` is set and route those events to traces or progress UI instead.

<details open>
<summary><strong>Node.js / TypeScript</strong></summary>
Comment thread
loganrosen marked this conversation as resolved.
Outdated

```typescript
session.on("assistant.message_delta", (event) => {
if (!event.agentId) process.stdout.write(event.data.deltaContent);
});
```

</details>
<details>
<summary><strong>Python</strong></summary>

```python
from copilot.session_events import SessionEventType

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

session.on(handle)
```

</details>

## Assistant events

These events track the agent's response lifecycle—from turn start through streaming chunks to the final message.
Expand Down Expand Up @@ -271,7 +301,7 @@ The assistant's complete response for this LLM call. May include tool invocation
| `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 |
| `parentToolCallId` | `string` | | Deprecated. Use envelope-level `agentId` for sub-agent attribution |

**`ToolRequest` fields:**

Expand All @@ -290,7 +320,7 @@ Ephemeral. Incremental chunk of the assistant's text response, streamed in real
|------------|------|----------|-------------|
| `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 |
| `parentToolCallId` | `string` | | Deprecated. Use envelope-level `agentId` for sub-agent attribution |

### `assistant.turn_end`

Expand All @@ -317,7 +347,7 @@ Ephemeral. Token usage and cost information for an individual API call.
| `apiCallId` | `string` | | Completion ID from the provider (e.g., `chatcmpl-abc123`) |
| `apiEndpoint` | `"/chat/completions" \| "/v1/messages" \| "/responses" \| "ws:/responses"` | | API endpoint used for the model call; useful for observability and cost attribution. `ws:/responses` is the websocket variant of the responses API |
| `providerCallId` | `string` | | GitHub request tracing ID (`x-github-request-id`) |
| `parentToolCallId` | `string` | | Set when usage originates from a sub-agent |
| `parentToolCallId` | `string` | | Deprecated. Use envelope-level `agentId` for sub-agent attribution |
| `quotaSnapshots` | `Record<string, QuotaSnapshot>` | | Per-quota resource usage, keyed by quota identifier |
| `copilotUsage` | `CopilotUsage` | | Itemized token cost breakdown from the API |

Expand All @@ -344,7 +374,7 @@ Emitted when a tool begins executing.
| `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 |
| `parentToolCallId` | `string` | | Deprecated. Use envelope-level `agentId` for sub-agent attribution |

### `tool.execution_partial_result`

Expand Down Expand Up @@ -378,7 +408,7 @@ Emitted when a tool finishes executing—successfully or with an error.
| `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 |
| `parentToolCallId` | `string` | | Deprecated. Use envelope-level `agentId` for sub-agent attribution |

**`Result` fields:**

Expand Down Expand Up @@ -789,6 +819,8 @@ session.idle → Ready for next message (ephemeral)

## All event types at a glance

This table lists key `data` payload fields. For sub-agent attribution, use the envelope-level `agentId`.

| Event Type | Ephemeral | Category | Key Data Fields |
|------------|-----------|----------|-----------------|
| `assistant.turn_start` | | Assistant | `turnId`, `interactionId?` |
Expand All @@ -797,7 +829,7 @@ session.idle → Ready for next message (ephemeral)
| `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.message_delta` | ✅ | Assistant | `messageId`, `deltaContent` |
| `assistant.turn_end` | | Assistant | `turnId` |
| `assistant.usage` | ✅ | Assistant | `model`, `apiEndpoint?`, `inputTokens?`, `outputTokens?`, `cost?`, `duration?` |
| `tool.user_requested` | | Tool | `toolCallId`, `toolName`, `arguments?` |
Expand Down
Loading