Skip to content

API and session event schema contracts

The copilot-cli-pkg/schemas/ directory is worth documenting as its own contract surface. It is not just descriptive metadata: the package ships these schema files, the SDK generated types point back to them, and app.js implements the runtime behavior that those contracts describe.

This page cross-checks the two schema files against the bundled runtime and the generated SDK artifacts.

Source anchors

app.js is bundled/minified, so semantic aliases below describe runtime roles. Minified anchors are searchable strings or generated symbols for this analyzed artifact.

Semantic aliasMinified anchorLocationRole
API schema contractapi.schema.jsoncopilot-cli-pkg/schemas/JSON-RPC method catalog consumed by SDK code generation.
Session event schema contractsession-events.schema.jsoncopilot-cli-pkg/schemas/Discriminated union for persisted/forwarded session event objects.
Generated RPC client surfacecreateServerRpc, createSessionRpc, registerClientSessionApiHandlerscopilot-sdk/generated/rpc.d.ts, copilot-sdk/index.jsTyped request wrappers and client-session handler registration generated from api.schema.json.
Generated event surfaceSessionEvent, SessionEventType, SessionEventPayloadcopilot-sdk/generated/session-events.d.ts, copilot-sdk/types.d.tsTyped event union generated from session-events.schema.json.
Session event notificationSESSION_EVENT:"session.event", Tee.SESSION_EVENTapp.js 6063, 6100JSON-RPC notification carrying schema-shaped events to clients.
Runtime event envelopeemitInternal, emitEphemeralapp.js 4471Builds id, timestamp, parentId, optional ephemeral, and optional agentId.
Event forwarder/replaysetupSessionEventForwardingapp.js 6100Routes live events, replays non-ephemeral history, and emits lifecycle updates.

Source files and generated surfaces

SourceContract roleCross-check anchor
copilot-cli-pkg/schemas/api.schema.jsonJSON-RPC method catalog for server-scoped, session-scoped, and client-session APIs.copilot-cli-pkg/copilot-sdk/generated/rpc.d.ts is marked Generated from: api.schema.json; copilot-cli-pkg/copilot-sdk/index.js contains the generated createServerRpc, createSessionRpc, and registerClientSessionApiHandlers implementations.
copilot-cli-pkg/schemas/session-events.schema.jsonDiscriminated union for session event objects emitted, persisted, replayed, and forwarded to clients.copilot-cli-pkg/copilot-sdk/generated/session-events.d.ts is marked Generated from: session-events.schema.json; copilot-cli-pkg/copilot-sdk/types.d.ts re-exports SessionEvent.
copilot-cli-pkg/package.jsonPackaging boundary.The files list includes schemas/**/*, so the schemas are shipped with the package.
copilot-cli-pkg/app.jsRuntime implementation for event emission, JSON-RPC notifications, shell notifications, session replay, and remote export.Search anchors: SESSION_EVENT:"session.event", emitInternal, setupSessionEventForwarding, setShellNotifier, and RemoteSessionExporter.

Contract flow

flowchart TD
ApiSchema["schemas/api.schema.json"] --> RpcTypes["copilot-sdk/generated/rpc.d.ts"]
RpcTypes --> RpcClient["createServerRpc / createSessionRpc"]
RpcClient --> JsonRpc["JSON-RPC requests"]
JsonRpc --> RuntimeHandlers["app.js server and session handlers"]
EventSchema["schemas/session-events.schema.json"] --> EventTypes["copilot-sdk/generated/session-events.d.ts"]
RuntimeHandlers --> SessionState["event-sourced session state"]
SessionState --> Emit["emit / emitEphemeral"]
Emit --> Forwarder["setupSessionEventForwarding"]
Forwarder --> SdkClient["SDK client onEvent handlers"]
Forwarder --> RemoteExporter["Mission Control exporter"]

api.schema.json

api.schema.json describes 86 JSON-RPC methods across three owner groups:

GroupCountDirectionMain responsibility
server16Client → CLI serverProcess/session-independent calls such as handshake, model/tool listing, MCP/skill discovery/config, sessionFs.setProvider, and session fork.
session60Client → active sessionCalls that require sessionId, such as model/mode/name/plan/workspace APIs, skills/MCP/extensions, tool and command responses, UI elicitation, permissions, shell execution, history, usage, and remote toggles.
clientSession10CLI server → SDK clientDelegated sessionFs.* calls implemented by the client-provided session filesystem provider.

The schema marks 32 methods as experimental and one method, connect, as internal. Those flags are preserved in the generated TypeScript declarations as comments such as @experimental and @internal. The sessionFs.* reverse-call implementation behind the clientSession group is documented in SessionFs provider and state-file lifecycle.

Method inventory

GroupMethods
serverping, connect, models.list, tools.list, account.getQuota, mcp.config.list, mcp.config.add, mcp.config.update, mcp.config.remove, mcp.config.enable, mcp.config.disable, mcp.discover, skills.config.setDisabledSkills, skills.discover, sessionFs.setProvider, sessions.fork
sessionsession.suspend, session.auth.getStatus, session.model.getCurrent, session.model.switchTo, session.mode.get, session.mode.set, session.name.get, session.name.set, session.plan.read, session.plan.update, session.plan.delete, session.workspaces.getWorkspace, session.workspaces.listFiles, session.workspaces.readFile, session.workspaces.createFile, session.instructions.getSources, session.fleet.start, session.agent.list, session.agent.getCurrent, session.agent.select, session.agent.deselect, session.agent.reload, session.tasks.startAgent, session.tasks.list, session.tasks.promoteToBackground, session.tasks.cancel, session.tasks.remove, session.tasks.sendMessage, session.skills.list, session.skills.enable, session.skills.disable, session.skills.reload, session.mcp.list, session.mcp.enable, session.mcp.disable, session.mcp.reload, session.mcp.oauth.login, session.plugins.list, session.extensions.list, session.extensions.enable, session.extensions.disable, session.extensions.reload, session.tools.handlePendingToolCall, session.commands.list, session.commands.invoke, session.commands.handlePendingCommand, session.commands.respondToQueuedCommand, session.ui.elicitation, session.ui.handlePendingElicitation, session.permissions.handlePendingPermissionRequest, session.permissions.setApproveAll, session.permissions.resetSessionApprovals, session.log, session.shell.exec, session.shell.kill, session.history.compact, session.history.truncate, session.usage.getMetrics, session.remote.enable, session.remote.disable
clientSessionsessionFs.readFile, sessionFs.writeFile, sessionFs.appendFile, sessionFs.exists, sessionFs.stat, sessionFs.mkdir, sessionFs.readdir, sessionFs.readdirWithTypes, sessionFs.rm, sessionFs.rename

SDK generation check

The generated SDK files are the clearest consumer of this schema:

  • copilot-sdk/generated/rpc.d.ts declares typed request/result shapes and factory APIs.
  • copilot-sdk/index.js contains generated request wrappers. For example, createServerRpc() sends models.list, tools.list, MCP config methods, skill discovery, and sessions.fork; createSessionRpc() injects sessionId and sends the session.* methods; registerClientSessionApiHandlers() registers incoming sessionFs.* request handlers.

When cross-checking against app.js, exact string matching is useful but not sufficient. The bundled/minified server code only exposes some RPC names verbatim, while the generated SDK wrapper contains the full schema method list. Treat app.js as the runtime implementation and copilot-sdk/generated/rpc.d.ts / copilot-sdk/index.js as the canonical generated client surface.

session-events.schema.json

session-events.schema.json defines a discriminated union rooted at #/definitions/SessionEvent. A script-assisted inventory found 99 concrete event type strings; 40 of those event definitions are explicitly ephemeral-only in the schema.

Every event has the same envelope pattern:

FieldRuntime meaning
idUUID-like unique event identifier generated at emit time.
timestampISO timestamp generated at emit time.
parentIdPrevious persistent event ID, forming the chronological event chain. The first event uses null.
ephemeralTransient event marker. Ephemeral events are forwarded/projected but are not appended to the persistent event array and are skipped during replay.
agentIdSub-agent instance attribution. Root/main-agent events omit it.
typeDiscriminator string such as assistant.message, tool.execution_start, or session.start.
dataType-specific payload.

Event family inventory

FamilyExamplesNotes
Session lifecycle/statesession.start, session.resume, session.idle, session.shutdown, session.title_changed, session.mode_changed, session.model_change, session.warning, session.errorDrives timeline state, metadata updates, resume behavior, and lifecycle notifications.
Assistant/modelassistant.turn_start, assistant.message_start, assistant.message_delta, assistant.message, assistant.reasoning_delta, assistant.reasoning, assistant.usage, model.call_failure, abortCaptures both durable assistant messages and transient streaming/progress deltas.
Tools and permissionstool.execution_start, tool.execution_progress, tool.execution_partial_result, tool.execution_complete, tool.user_requested, permission.requested, permission.completedMatches built-in/external tool pipelines and permission prompts.
User and UI callbacksuser.message, user_input.requested, user_input.completed, elicitation.requested, elicitation.completed, exit_plan_mode.requested, exit_plan_mode.completed, auto_mode_switch.requested, auto_mode_switch.completedBridges runtime prompts back to SDK/host clients.
External clients and commandsexternal_tool.requested, external_tool.completed, command.execute, command.queued, command.completed, commands.changedUsed by SDK tools, extension-owned commands, and queued command execution.
MCP, skills, extensionsmcp.oauth_required, mcp.oauth_completed, session.mcp_servers_loaded, session.mcp_server_status_changed, skill.invoked, session.skills_loaded, session.extensions_loaded, session.custom_agents_updatedMirrors integration/configuration state.
Subagents/taskssubagent.started, subagent.completed, subagent.failed, subagent.selected, subagent.deselected, session.background_tasks_changed, session.task_completeProvides task/subagent attribution and progress.
Attachments/resourcesfile, directory, selection, github_reference, blob, image, audio, resource, resource_link, terminal, text, objectNormalizes attachment/resource blocks used in messages and tool results.
Compaction/history/remotesession.compaction_start, session.compaction_complete, session.snapshot_rewind, session.truncation, session.handoff, session.remote_steerable_changedSupports history mutation, handoff, checkpoint/rewind, and remote session state.
System notifications/hookssystem.message, system.notification, hook.start, hook.end, instruction_discovered, new_inbox_message, shell_completed, shell_detached_completed, agent_completed, agent_idlePowers UI notifications, hook lifecycle output, and shell/task completion notices.

app.js runtime cross-check

The runtime behavior in app.js lines up with the schema shape:

Runtime anchorWhat it confirms
SESSION_EVENT:"session.event", SESSION_LIFECYCLE:"session.lifecycle", SHELL_OUTPUT:"shell.output", SHELL_EXIT:"shell.exit"app.js has JSON-RPC notification constants for session events, session lifecycle events, and shell streaming notifications.
emitInternalBuilds the event envelope with type, data, id, timestamp, parentId, optional ephemeral, and optional agentId. Non-ephemeral events are appended to the session event array and update lastEventId.
emit / emitEphemeralPersistent and transient event emission split. Streaming deltas such as assistant.message_start, assistant.message_delta, assistant.reasoning_delta, and assistant.streaming_delta are emitted through the ephemeral path.
setupSessionEventForwardingSubscribes to session.on("*"), sends session.event notifications, handles special routing for external_tool.requested and command.execute, filters subagent streaming events by interested connection, broadcasts session.updated lifecycle updates for non-ephemeral events, and replays only non-ephemeral existing events.
setShellNotifierWires shell output/exit callbacks to shell.output and shell.exit notifications.
RemoteSessionExporterBuffers/batches session events for Mission Control, redacts secrets before upload, and advances the last uploaded marker using non-ephemeral event IDs. Backfill upload code also filters out ephemeral events.

A literal string scan cross-checked all 99 event type strings from session-events.schema.json in app.js. This is a stronger match than the API method string scan because session event discriminators are emitted directly by the runtime.

Request and event sequence

sequenceDiagram
participant Sdk as SDK client
participant Rpc as JSON-RPC connection
participant Runtime as app.js runtime
participant Session as Event-sourced session
participant Ui as SDK/UI subscriber
participant Remote as Mission Control exporter
Sdk->>Rpc: session.* request from generated wrapper
Rpc->>Runtime: dispatch method with sessionId
Runtime->>Session: mutate/query session state
Session->>Session: emit or emitEphemeral
Session-->>Runtime: wildcard event callback
Runtime-->>Ui: session.event notification
Runtime-->>Ui: session.lifecycle session.updated when persistent
Runtime-->>Remote: buffered event export
Note over Runtime,Remote: Ephemeral events are forwarded live but skipped for replay/backfill markers

Questions this chapter answers

This chapter is the schema map for questions such as:

  • Which SDK calls are stable versus experimental?
  • Which methods are scoped to a session and therefore require sessionId?
  • Which events are durable history versus live-only UI/progress events?
  • How does an event become a JSON-RPC session.event notification?
  • Why do some schema RPC method names appear in generated SDK code but not as easy-to-find literals in the minified app.js bundle?

Created and maintained by Yingting Huang.