Session Channel
Reference for the ahp-session:/<uuid> channel — per-session state, the turn lifecycle, tool-call state machine, attachments, pending messages, input requests, and per-session customizations. See Session Channel specification for the wire-level overview.
JSON Schema: state.schema.json
State Types
SessionLifecycle
Session initialization state.
| Member | Value |
|---|---|
Creating | 'creating' |
Ready | 'ready' |
CreationFailed | 'creationFailed' |
SessionStatus
Bitset of summary-level session status flags.
Use bitwise checks instead of equality for non-terminal activity. For example, status & SessionStatus.InProgress matches both ordinary in-progress turns and turns that are paused waiting for input.
| Member | Value | Description |
|---|---|---|
Idle | 1 | Session is idle — no turn is active. |
Error | 1 << 1 | Session ended with an error. |
InProgress | 1 << 3 | A turn is actively streaming. |
InputNeeded | (1 << 3) | (1 << 4) | A turn is in progress but blocked waiting for user input or tool confirmation. |
IsRead | 1 << 5 | The client has viewed this session since its last modification. |
IsArchived | 1 << 6 | The session has been archived by the client. |
SessionState
Full state for a single session, loaded when a client subscribes to the session's URI.
| Field | Type | Required | Description |
|---|---|---|---|
summary | SessionSummary | Yes | Lightweight session metadata |
lifecycle | SessionLifecycle | Yes | Session initialization state |
creationError | ErrorInfo | No | Error details if creation failed |
serverTools | ToolDefinition[] | No | Tools provided by the server (agent host) for this session |
activeClient | SessionActiveClient | No | The client currently providing tools and interactive capabilities to this session |
chats | ChatSummary[] | Yes | Catalog of chats in this session. |
defaultChat | URI | No | The chat that receives input when the user addresses the session without selecting a specific chat. This is a UI routing hint, not a hierarchy marker — chats remain equal peers at the protocol level. Hosts MAY change this over the session's lifetime. |
config | SessionConfigState | No | Session configuration schema and current values |
customizations | Customization[] | No | Top-level customizations active in this session. Always one of the {@link Customization} variants: - Container customizations ({@link PluginCustomization}, {@link DirectoryCustomization}) whose children — agents, skills, prompts, rules, hooks, MCP servers — live in each container's {@link ContainerCustomizationBase.children | children} array. - Top-level {@link McpServerCustomization} entries the host surfaces directly (for example a globally-configured MCP server that isn't bundled in a plugin or directory). MCP servers may also appear as children of a container.Client-published plugins arrive via {@link SessionActiveClient.customizations | activeClient.customizations} and the host propagates them into this list (typically with the container's clientId set and children populated). Clients publish in container shape only; bare MCP servers at the top level are server-originated. |
changesets | Changeset[] | No | Catalogue of changesets the server can produce for this session. Each entry advertises a subscribable view of file changes (uncommitted, session-wide, per-turn, etc.) and the URI template the client expands before subscribing. See {@link Changeset} for the full shape and {@link /guide/changesets | Changesets} for an overview of the model. |
_meta | Record<string, unknown> | No | Additional provider-specific metadata for this session. Clients MAY look for well-known keys here to provide enhanced UI. For example, a git key may provide extra git metadata about the session's workingDirectory. |
SessionActiveClient
The client currently providing tools and interactive capabilities to a session.
Only one client may be active per session at a time. The server SHOULD automatically unset the active client if that client disconnects.
| Field | Type | Required | Description |
|---|---|---|---|
clientId | string | Yes | Client identifier (matches clientId from initialize) |
displayName | string | No | Human-readable client name (e.g. "VS Code") |
tools | ToolDefinition[] | Yes | Tools this client provides to the session |
customizations | ClientPluginCustomization[] | No | Plugin customizations this client contributes to the session. Clients publish in Open Plugins format — i.e. always container-shaped plugins. They MAY synthesize virtual plugins in memory and rely on the host to expand them into concrete children inside {@link SessionState.customizations}. |
ProjectInfo
Server-owned project metadata for a session.
| Field | Type | Description |
|---|---|---|
uri | URI | Project URI |
displayName | string | Human-readable project name |
SessionSummary
Lightweight catalog entry summarizing one session. Surfaced via {@link RootChannelCommands.listSessions | root/listSessions} and root/sessionAdded/root/sessionSummaryChanged notifications.
Aggregation across chats. Once a session contains more than one chat, several SessionSummary fields are derived from the underlying {@link SessionState.chats | chat catalog}. Producers SHOULD follow these rules so clients that only consume the session summary (e.g. a session list) still see meaningful state:
status: take the activity bits (Idle/InProgress/InputNeeded/Error— bits 0–4) from the {@link SessionState.defaultChat | default chat} when present, else from the most recently modified chat. PromoteInputNeededwhenever any chat in the session needs input, and promoteErrorwhenever any chat is in an error state — both override the default-chat bits. The orthogonal flag bits (IsRead,IsArchived) remain session-scoped.activity: mirror the activity string of the default chat, or of the chat currently driving the promoted status bits when a non-default chat wins (e.g. the chat that raisedInputNeeded).modifiedAt: the max of all chats'modifiedAt.model/agent: the session-level selection. Per-chat overrides are surfaced on individual {@link ChatSummary} entries, not aggregated up.workingDirectory: the session-level default. Individual chats MAY override via {@link ChatSummary.workingDirectory}; aggregating these up is meaningless and SHOULD NOT be attempted.changes: optional roll-up across all chats. Producers MAY sum the per-chat changeset stats or report the most expensive chat's stats — whichever is cheaper for the host to compute.
Sessions with a single chat trivially satisfy all of the above (the chat's values pass through unchanged). The rules only matter once a session carries multiple chats.
| Field | Type | Required | Description |
|---|---|---|---|
resource | URI | Yes | Session URI |
provider | string | Yes | Agent provider ID |
title | string | Yes | Session title |
status | SessionStatus | Yes | Current session status |
activity | string | No | Human-readable description of what the session is currently doing |
createdAt | number | Yes | Creation timestamp |
modifiedAt | number | Yes | Last modification timestamp |
project | ProjectInfo | No | Server-owned project for this session |
model | ModelSelection | No | Currently selected model |
agent | AgentSelection | No | Currently selected custom agent. Absent ( undefined) means no custom agent is selected for this session — the session uses the provider's default behavior. |
workingDirectory | URI | No | The default working directory URI for this session. Individual chats MAY override via {@link ChatSummary.workingDirectory | their own workingDirectory}; this field acts as the fallback for any chat that does not. |
changes | ChangesSummary | No | Aggregate summary of file changes associated with this session. Servers may populate this to give clients a quick at-a-glance view of the session's footprint (e.g., for list rendering) without requiring the client to subscribe to a changeset. |
annotations | AnnotationsSummary | No | Lightweight summary of this session's inline annotations channel (ahp-session:/<uuid>/annotations). Surfaced so badge UI can render annotation / entry counts without subscribing. Absent when the session does not expose an annotations channel. |
ChangesSummary
Aggregate counts describing the file changes associated with a session.
All fields are optional so servers can populate only the metrics they cheaply have available.
| Field | Type | Required | Description |
|---|---|---|---|
additions | number | No | Total number of inserted lines across all changed files. |
deletions | number | No | Total number of deleted lines across all changed files. |
files | number | No | Number of files that have changes. |
AgentSelection
A selected custom agent for a session.
The uri identifies a specific custom agent (matching an {@link AgentCustomization.uri | AgentCustomization.uri} exposed via the session's effective customizations). Consumers resolve the agent's display name by looking up uri in the session's customization tree.
A session with no agent selected uses the provider's default behavior.
| Field | Type | Description |
|---|---|---|
uri | URI | Stable agent URI (matches an {@link AgentCustomization.uri}). |
SessionConfigPropertySchema
A session configuration property descriptor.
Extends the generic {@link ConfigPropertySchema} with session-specific display extensions.
| Field | Type | Required | Description |
|---|---|---|---|
enumDynamic | boolean | No | Display extension: when true, the full set of allowed values is too large to enumerate statically. The client SHOULD use sessionConfigCompletions to fetch matching values based on user input. Any values in enum are seed/recent values for initial display. |
sessionMutable | boolean | No | When true, the user may change this property after session creation |
SessionConfigSchema
A JSON Schema object describing available session configuration metadata.
| Field | Type | Required | Description |
|---|---|---|---|
type | 'object' | Yes | JSON Schema: always 'object' |
properties | Record<string, SessionConfigPropertySchema> | Yes | JSON Schema: property descriptors keyed by property id |
required | string[] | No | JSON Schema: list of required property ids |
SessionConfigState
Live session configuration metadata.
The schema describes the available configuration properties and the values contain the current value for each resolved property.
| Field | Type | Description |
|---|---|---|
schema | SessionConfigSchema | JSON Schema describing available configuration properties |
values | Record<string, unknown> | Current configuration values |
ToolDefinition
Describes a tool available in a session, provided by either the server or the active client.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique tool identifier |
title | string | No | Human-readable display name |
description | string | No | Description of what the tool does |
inputSchema | | No | JSON Schema defining the expected input parameters. Optional because client-provided tools may not have formal schemas. Mirrors MCP Tool.inputSchema. |
outputSchema | | No | JSON Schema defining the structure of the tool's output. Mirrors MCP Tool.outputSchema. |
annotations | ToolAnnotations | No | Behavioral hints about the tool. All properties are advisory. |
_meta | Record<string, unknown> | No | Additional provider-specific metadata. Mirrors the MCP _meta convention. |
ToolAnnotations
Behavioral hints about a tool. All properties are advisory and not guaranteed to faithfully describe tool behavior.
Mirrors MCP ToolAnnotations from the Model Context Protocol specification.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | No | Alternate human-readable title |
readOnlyHint | boolean | No | Tool does not modify its environment (default: false) |
destructiveHint | boolean | No | Tool may perform destructive updates (default: true) |
idempotentHint | boolean | No | Repeated calls with the same arguments have no additional effect (default: false) |
openWorldHint | boolean | No | Tool may interact with external entities (default: true) |
CustomizationType
Discriminant for the kind of customization.
Top-level entries in {@link SessionState.customizations} and {@link AgentInfo.customizations} are either container customizations ({@link CustomizationType.Plugin | Plugin} or {@link CustomizationType.Directory | Directory}) or {@link CustomizationType.McpServer | McpServer} entries surfaced directly by the host. The remaining types appear only as children of a container.
| Member | Value |
|---|---|
Plugin | 'plugin' |
Directory | 'directory' |
Agent | 'agent' |
Skill | 'skill' |
Prompt | 'prompt' |
Rule | 'rule' |
Hook | 'hook' |
McpServer | 'mcpServer' |
ChildCustomizationType
Customization types that appear as children of a {@link PluginCustomization} or {@link DirectoryCustomization}.
CustomizationType.Agent | CustomizationType.Skill | CustomizationType.Prompt | CustomizationType.Rule | CustomizationType.Hook | CustomizationType.McpServer
CustomizationLoadStatus
Discriminant values for {@link CustomizationLoadState}.
| Member | Value |
|---|---|
Loading | 'loading' |
Loaded | 'loaded' |
Degraded | 'degraded' |
Error | 'error' |
CustomizationLoadingState
Container is being loaded by the host.
| Field | Type | Description |
|---|---|---|
kind | CustomizationLoadStatus.Loading |
CustomizationLoadedState
Container loaded successfully.
| Field | Type | Description |
|---|---|---|
kind | CustomizationLoadStatus.Loaded |
CustomizationDegradedState
Container partially loaded but has warnings.
| Field | Type | Description |
|---|---|---|
kind | CustomizationLoadStatus.Degraded | |
message | string | Human-readable description of the warning. |
CustomizationErrorState
Container failed to load.
| Field | Type | Description |
|---|---|---|
kind | CustomizationLoadStatus.Error | |
message | string | Human-readable error message. |
CustomizationLoadState
Discriminated load state for a container customization ({@link PluginCustomization} or {@link DirectoryCustomization}).
CustomizationLoadingState | CustomizationLoadedState | CustomizationDegradedState | CustomizationErrorState
PluginCustomization
An Open Plugins plugin.
| Field | Type | Description |
|---|---|---|
type | CustomizationType.Plugin |
ClientPluginCustomization
A {@link PluginCustomization} as published by a client. Extends the server-facing shape with an opaque nonce so the host can detect when the client's view of a plugin has changed and re-parse only as needed.
Clients SHOULD include a nonce. Server-side fields like {@link ContainerCustomizationBase.children | children} and {@link ContainerCustomizationBase.load | load} are typically left absent on publication and populated by the host when the resolved plugin appears in {@link SessionState.customizations}.
| Field | Type | Required | Description |
|---|---|---|---|
nonce | string | No | Opaque version token used by the host to detect changes. |
DirectoryCustomization
A directory the host watches for this session.
Presence in the customization list signals that the host may discover customizations from this directory. When writable is true, clients MAY persist new customizations into the directory using resourceWrite; the host will then surface the resulting child via the customization actions.
The directory may not yet exist on disk.
| Field | Type | Description |
|---|---|---|
type | CustomizationType.Directory | |
contents | ChildCustomizationType | Which child customization type this directory holds. |
writable | boolean | Whether clients may write into this directory. |
AgentCustomization
A custom agent contributed by a plugin or directory.
Mirrors the Open Plugins agent format: a markdown file with YAML frontmatter, where the body is the agent's system prompt.
| Field | Type | Required | Description |
|---|---|---|---|
type | CustomizationType.Agent | Yes | |
description | string | No | Short description of what the agent specializes in and when to invoke it. Sourced from the agent file's frontmatter description. |
_meta | Record<string, unknown> | No | Additional provider-specific metadata for this custom agent. Mirrors the MCP _meta convention. |
SkillCustomization
A skill contributed by a plugin or directory.
Covers both Open Plugins skill formats — the skills/ directory layout (one subdirectory per skill, each with a SKILL.md) and the flatter commands/ directory of slash-command skills.
| Field | Type | Required | Description |
|---|---|---|---|
type | CustomizationType.Skill | Yes | |
description | string | No | Short description used for help text and auto-invocation matching. Sourced from the skill's frontmatter description. |
disableModelInvocation | boolean | No | When true, only the user can invoke this skill — the agent will not auto-invoke it. Sourced from the command skill's frontmatter disable-model-invocation flag. |
PromptCustomization
A prompt contributed by a plugin or directory.
| Field | Type | Required | Description |
|---|---|---|---|
type | CustomizationType.Prompt | Yes | |
description | string | No | Short description of what the prompt does. |
RuleCustomization
A rule contributed by a plugin or directory.
Mirrors the Open Plugins rule format: a markdown file (e.g. .mdc) whose body is injected into context while the rule is active. This type also covers tool-specific "instruction" formats (e.g. VS Code Copilot's .github/instructions/*.md), which differ only in naming — they share the same semantics of description, optional always-on activation, and optional glob scoping.
| Field | Type | Required | Description |
|---|---|---|---|
type | CustomizationType.Rule | Yes | |
description | string | No | Description of what the rule enforces. |
alwaysApply | boolean | No | When true, the rule is always active (subject to globs if any). When false or absent, the agent or user decides whether to apply the rule. |
globs | string[] | No | Glob patterns the rule applies to. When present, the rule is only active for matching files. |
HookCustomization
A hook manifest contributed by a plugin or directory.
| Field | Type | Description |
|---|---|---|
type | CustomizationType.Hook |
McpServerCustomization
An MCP server contributed by a plugin or directory.
When the server is declared inline in the containing plugin manifest, uri points at the manifest file and {@link CustomizationBase.range | range} narrows it to the declaration's span.
The MCP server customization also reflects its current status.
| Field | Type | Required | Description |
|---|---|---|---|
type | CustomizationType.McpServer | Yes | |
enabled | boolean | Yes | Whether this MCP server is currently enabled. |
state | McpServerState | Yes | Current lifecycle state of the MCP server. |
channel | URI | No | An mcp://-protocol channel the client uses to side-channel traffic into the upstream MCP server itself. The channel is NOT a fresh raw MCP connection: it piggybacks on the AHP transport and skips the MCP initialize sequence.The agent host MAY only serve a subset of MCP on this channel; the served subset is described by domain-specific capabilities such as those in {@link McpServerCustomizationApps.capabilities}. The channel URI SHOULD be stable across the server's lifetime, but the agent host MAY change it (for example across a restart) and MAY only expose it while the server is in {@link McpServerStatus.Ready | Ready}. Absence means no side-channel is currently available. |
mcpApp | McpServerCustomizationApps | No | MCP App support. This property SHOULD be advertised for MCP servers which support apps. |
McpServerCustomizationApps
Information from the agent host needed to render MCP Apps served by this MCP server.
| Field | Type | Description |
|---|---|---|
capabilities | AhpMcpUiHostCapabilities | The subset of MCP App HostCapabilities the AHP host can satisfy for Views backed by this server. The client feeds these straight through into the hostCapabilities of the ui/initialize response delivered to the View. |
AhpMcpUiHostCapabilities
The subset of MCP App HostCapabilities an AHP host can derive from the upstream MCP server (and from AHP's own forwarding plumbing). Advertised on {@link McpServerCustomizationApps.capabilities} so clients can pass it through into the hostCapabilities of the ui/initialize response delivered to an MCP App View.
Field names mirror the MCP Apps spec exactly, so the AHP-side producer can pass them straight through into the hostCapabilities of the ui/initialize response delivered to the View.
Capabilities outside this set (openLinks, downloadFile, sandbox, experimental) are decided locally by whichever AHP client renders the View and are NOT part of this AHP-level advertisement — only the server-derived subset is.
An agent host MUST only advertise a capability when it actually accepts the corresponding methods/notifications on the mcp:// channel:
- {@link serverTools}: host proxies
tools/listandtools/callto the MCP server. WhenlistChangedistrue, the host also forwardsnotifications/tools/list_changed. - {@link serverResources}: host proxies
resources/read,resources/list, andresources/templates/listto the MCP server. WhenlistChangedistrue, the host also forwardsnotifications/resources/list_changed. - {@link logging}: host accepts
notifications/messagelog entries from the App and forwards them viamcpNotification(and forwardslogging/setLevelcalls to the server). - {@link sampling}: host serves
sampling/createMessageviamcpMethodCall. Whensampling.toolsis present, the host also accepts SEP-1577tools/toolChoice/tool_usecontent blocks insideCreateMessageRequest.
| Field | Type | Required | Description |
|---|---|---|---|
serverTools | | No | Producer proxies the MCP tools/* methods to the upstream server. |
serverResources | | No | Producer proxies the MCP resources/* methods to the upstream server. |
logging | Record<string, never> | No | Producer accepts notifications/message log entries from the App via mcpNotification. |
sampling | | No | Producer serves sampling/createMessage via mcpMethodCall. |
ChildCustomization
Child customizations that live inside a {@link PluginCustomization} or {@link DirectoryCustomization}.
AgentCustomization | SkillCustomization | PromptCustomization | RuleCustomization | HookCustomization | McpServerCustomization
Customization
A top-level customization active in a session. Either a container ({@link PluginCustomization} or {@link DirectoryCustomization}) whose leaf customizations live in its {@link ContainerCustomizationBase.children | children} array, or a bare {@link McpServerCustomization} surfaced directly by the host.
PluginCustomization | DirectoryCustomization | McpServerCustomization
McpServerStatus
Discriminant for the {@link McpServerState} union.
| Member | Value | Description |
|---|---|---|
Starting | 'starting' | Server has been registered but is not yet running. |
Ready | 'ready' | Server is running and serving requests. |
AuthRequired | 'authRequired' | Server is reachable but requires additional authentication before it can start, or before it can serve a particular request. Carries the RFC 9728 Protected Resource Metadata the client needs to obtain a token; the client then pushes the token via the existing authenticate command. |
Error | 'error' | Server failed to start, crashed, or otherwise transitioned to a fatal error. |
Stopped | 'stopped' | Server has been shut down. |
McpAuthRequiredReason
Why an MCP server is currently in the {@link McpServerStatus.AuthRequired} state. Mirrors the three failure modes defined by the MCP authorization spec.
| Member | Value | Description |
|---|---|---|
Required | 'required' | No token has been provided yet (HTTP 401, no prior token). |
Expired | 'expired' | A previously valid token expired or was revoked (HTTP 401). |
InsufficientScope | 'insufficientScope' | Step-up auth: a token is present but its scopes are insufficient for the requested operation (HTTP 403 with WWW-Authenticate: Bearer error="insufficient_scope").Unlike {@link Required} and {@link Expired} — which typically surface before any tool work is in flight — InsufficientScope is almost always triggered by an MCP request issued mid-turn (a tools/call, resources/read, etc.). The host SHOULD pair the {@link McpServerAuthRequiredState} transition with {@link SessionStatus.InputNeeded} on {@link SessionSummary.status | the session} so the activity becomes visible at the session-summary level, and clients SHOULD watch for this kind on any {@link McpServerCustomization | MCP server} backing a running tool call so they can present an explicit "grant more access" affordance tied to the blocked tool call. |
McpServerStartingState
Server is registered with the host but has not yet started.
| Field | Type | Description |
|---|---|---|
kind | McpServerStatus.Starting |
McpServerReadyState
Server is running and serving requests.
| Field | Type | Description |
|---|---|---|
kind | McpServerStatus.Ready |
McpServerAuthRequiredState
Server is reachable but cannot serve requests until the client authenticates. Mirrors the discovery flow defined by RFC 9728 (Protected Resource Metadata) and the OAuth 2.1 / RFC 6750 challenge semantics required by the MCP authorization spec.
Clients react to this state by calling the existing authenticate command with the {@link ProtectedResourceMetadata.resource | resource} carried here. There is no notify/authRequired notification for MCP servers — the action stream is the single source of truth.
When the transition is triggered by a request issued during a turn — most commonly {@link McpAuthRequiredReason.InsufficientScope | InsufficientScope} surfacing mid-tool-call — the host SHOULD also raise {@link SessionStatus.InputNeeded} on the session so the block is visible at the summary level. Clients SHOULD watch this status on any MCP server backing a running tool call and surface an explicit affordance (e.g. a "grant additional access" prompt) tied to that tool call, rather than relying on the user to notice the customization’s status badge.
| Field | Type | Required | Description |
|---|---|---|---|
kind | McpServerStatus.AuthRequired | Yes | |
reason | McpAuthRequiredReason | Yes | Why authentication is required. |
resource | ProtectedResourceMetadata | Yes | RFC 9728 Protected Resource Metadata. The resource field is the canonical MCP server URI per RFC 8707, used as the OAuth resource indicator. authorization_servers is REQUIRED by the MCP authorization spec. |
requiredScopes | string[] | No | Scopes required for the current challenge, parsed from the WWW-Authenticate: Bearer scope="…" header (or scopes_supported fallback). Authoritative for the next authorization request — clients MUST NOT assume any subset/superset relationship to resource.scopes_supported. |
description | string | No | Human-readable hint, typically from the OAuth error_description. |
McpServerErrorState
Server failed to start, crashed, or otherwise transitioned to a non-recoverable error. Use {@link McpServerStatus.AuthRequired} for authentication failures.
| Field | Type | Description |
|---|---|---|
kind | McpServerStatus.Error | |
error | ErrorInfo | Error details. |
McpServerStoppedState
Server has been shut down. The host MAY remove the server from the session entirely shortly after this state.
| Field | Type | Description |
|---|---|---|
kind | McpServerStatus.Stopped |
McpServerState
Discriminated union of all MCP server lifecycle states. Discriminated by kind (a {@link McpServerStatus} value).
McpServerStartingState | McpServerReadyState | McpServerAuthRequiredState | McpServerErrorState | McpServerStoppedState
Actions
Mutate SessionState. Scoped to a session URI via the enclosing ActionEnvelope.channel.
JSON Schema: actions.schema.json
session/ready
Session backend initialized successfully.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionReady |
session/creationFailed
Session backend failed to initialize.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionCreationFailed | |
error | ErrorInfo | Error details |
session/chatAdded
A chat was added to this session's catalog. Upsert semantics: if a chat with the same summary.resource already exists, the existing entry is replaced.
Mirrors the root-channel root/sessionAdded notification.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionChatAdded | |
summary | ChatSummary | The full summary of the newly added (or upserted) chat. |
session/chatRemoved
A chat was removed from this session's catalog. No-op when no entry matches.
Mirrors the root-channel root/sessionRemoved notification.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionChatRemoved | |
chat | URI | The URI of the chat to remove. |
session/chatUpdated
One existing chat's summary fields changed.
Partial-update semantics: only fields present in changes are written; omitted fields are preserved. Identity fields (resource) MUST NOT be carried in changes. No-op when no entry with chat exists — clients SHOULD then wait for a {@link SessionChatAddedAction | session/chatAdded}.
Mirrors the root-channel root/sessionSummaryChanged notification.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionChatUpdated | |
chat | URI | The URI of the chat whose summary changed. |
changes | Partial<ChatSummary> | Mutable summary fields that changed; omitted fields are unchanged. Identity fields ( resource) never change and MUST be omitted by senders; receivers SHOULD ignore them if present. |
session/defaultChatChanged
The default chat input-routing hint for this session changed.
| Field | Type | Required | Description |
|---|---|---|---|
type | ActionType.SessionDefaultChatChanged | Yes | |
defaultChat | URI | No | New default chat URI, or undefined to clear the hint. |
session/titleChanged
Session title updated. Fired by the server when the title is auto-generated from conversation, or dispatched by a client to rename a session.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionTitleChanged | |
title | string | New title |
session/modelChanged
Model changed for this session.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionModelChanged | |
model | ModelSelection | New model selection |
session/agentChanged
Custom agent selection changed for this session.
Omitting agent (or setting it to undefined) clears the selection and resets the session to no selected custom agent (provider default behavior).
When a turn is currently active, the server MUST defer the change until the active turn completes, then apply it for the next turn (same rule as {@link SessionModelChangedAction | session/modelChanged}).
| Field | Type | Required | Description |
|---|---|---|---|
type | ActionType.SessionAgentChanged | Yes | |
agent | AgentSelection | No | New agent selection, or undefined to clear the selection and reset the session to no selected custom agent. |
session/isReadChanged
The read state of the session changed.
Dispatched by a client to mark a session as read (e.g. after viewing it) or unread (e.g. after new activity since the client last looked at it).
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionIsReadChanged | |
isRead | boolean | Whether the session has been read |
session/isArchivedChanged
The archived state of the session changed.
Dispatched by a client to archive a session (e.g. the task is complete) or to unarchive it.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionIsArchivedChanged | |
isArchived | boolean | Whether the session is archived |
session/activityChanged
The activity description of the session changed.
Dispatched by the server to indicate what the session is currently doing (e.g. running a tool, thinking). Clear activity by setting it to undefined.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionActivityChanged | |
activity | string | undefined | Human-readable description of current activity, or undefined to clear |
session/changesetsChanged
The {@link Changeset | catalogue of changesets} the agent host advertises for this session changed. Replaces {@link SessionState.changesets | state.changesets} entirely (full-replacement semantics) — set to undefined to clear the catalogue.
Producers dispatch this whenever entries are added or removed. The fan-out happens through this action so observers see catalogue mutations in the same {@link ChangesetAction | per-changeset} action stream they already follow for file-level updates.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionChangesetsChanged | |
changesets | Changeset[] | undefined | New catalogue, or undefined to clear it |
session/serverToolsChanged
Server tools for this session have changed.
Full-replacement semantics: the tools array replaces the previous serverTools entirely.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionServerToolsChanged | |
tools | ToolDefinition[] | Updated server tools list (full replacement) |
session/activeClientChanged
The active client for this session has changed.
A client dispatches this action with its own SessionActiveClient to claim the active role, or with null to release it. The server SHOULD reject if another client is already active. The server SHOULD automatically dispatch this action with activeClient: null when the active client disconnects.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionActiveClientChanged | |
activeClient | SessionActiveClient | null | The new active client, or null to unset |
session/activeClientToolsChanged
The active client's tool list has changed.
Full-replacement semantics: the tools array replaces the active client's previous tools entirely. The server SHOULD reject if the dispatching client is not the current active client.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionActiveClientToolsChanged | |
tools | ToolDefinition[] | Updated client tools list (full replacement) |
session/customizationsChanged
The session's customizations have changed.
Full-replacement semantics: the customizations array replaces the previous customizations entirely.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionCustomizationsChanged | |
customizations | Customization[] | Updated customization list (full replacement). |
session/customizationToggled
A client toggled a container customization on or off.
Targets a top-level container (plugin or directory) by id. Only containers have an enabled flag; children are always active when their container is enabled. Is a no-op when no matching container is found.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionCustomizationToggled | |
id | string | The id of the container to toggle. |
enabled | boolean | Whether to enable or disable the container. |
session/customizationUpdated
Upserts a top-level customization (plugin or directory).
The reducer locates the existing entry by customization.id:
- If found, the entry is replaced entirely with
customization, including itschildrenarray. To preserve existing children, the host must include them on the payload. - If not found, the entry is appended.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionCustomizationUpdated | |
customization | Customization | The customization to upsert (matched by customization.id). |
session/customizationRemoved
Removes a customization by id.
Searches every container and its children for the entry. If the entry is a container, its children are removed with it. Is a no-op when no matching id is found.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionCustomizationRemoved | |
id | string | The id of the customization to remove. |
session/mcpServerStateChanged
Updates the runtime fields of an existing {@link McpServerCustomization} — narrow alternative to {@link SessionCustomizationUpdatedAction} for the high-frequency starting ↔ ready ↔ authRequired transitions.
Locates the target entry by id, searching both the top-level customization list and the children array of every container. Replaces the entry's {@link McpServerCustomization.state | state} and {@link McpServerCustomization.channel | channel} (full-replacement semantics: omit channel to clear an existing channel URI). Other fields of the customization are preserved.
Is a no-op when no matching McpServerCustomization is found. To update any other field (name, icons, mcpApp capabilities, etc.) use {@link SessionCustomizationUpdatedAction} instead.
When the transition is to {@link McpServerStatus.AuthRequired} because of a request issued mid-turn, the host SHOULD also raise {@link SessionStatus.InputNeeded} on the session — see {@link McpServerAuthRequiredState} for the rationale.
| Field | Type | Required | Description |
|---|---|---|---|
type | ActionType.SessionMcpServerStateChanged | Yes | |
id | string | Yes | The id of the {@link McpServerCustomization} to update. |
state | McpServerState | Yes | The new lifecycle state. |
channel | URI | No | Updated mcp:// side-channel URI. Full-replacement: omit to clear an existing channel (typical when leaving {@link McpServerStatus.Ready | Ready}). |
session/configChanged
Client changed a mutable config value mid-session.
Only properties with sessionMutable: true in the config schema may be changed. The server validates and broadcasts the action; the reducer merges the new values into state.config.values.
| Field | Type | Required | Description |
|---|---|---|---|
type | ActionType.SessionConfigChanged | Yes | |
config | Record<string, unknown> | Yes | Updated config values |
replace | boolean | No | When true, replaces all config values instead of merging |
session/metaChanged
The session's _meta side-channel changed. Replaces state._meta entirely (full-replacement semantics). Producers SHOULD merge any keys they wish to preserve into the new value before dispatching.
| Field | Type | Description |
|---|---|---|
type | ActionType.SessionMetaChanged | |
_meta | Record<string, unknown> | undefined | New _meta payload, or undefined to clear it |
Commands
JSON Schema: commands.schema.json
createSession
| Property | Value |
|---|---|
| Direction | Client → Server |
| Type | Request |
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
channel | URI | Yes | Session URI (client-chosen, e.g. ahp-session:/<uuid>) |
provider | string | No | Agent provider ID |
model | ModelSelection | No | Model selection (ID and optional model-specific configuration) |
agent | AgentSelection | No | Initial custom agent selection for the new session. Omit to start the session with no custom agent selected (provider default). |
workingDirectory | URI | No | Working directory for the session |
fork | SessionForkSource | No | Fork from an existing session. The new session is populated with content from the source session up to and including the specified turn's response. |
config | Record<string, unknown> | No | Agent-specific configuration values collected via resolveSessionConfig. Keys and values correspond to the schema returned by the server. |
activeClient | SessionActiveClient | No | Eagerly claim the active client role for the new session. When provided, the server initializes the session with this client as the active client, equivalent to dispatching a session/activeClientChanged action immediately after creation. The clientId MUST match the clientId the creating client supplied in initialize. |
Result: null on success.
disposeSession
Disposes a session and cleans up server-side resources.
The server broadcasts a root/sessionRemoved notification to all clients.
| Property | Value |
|---|---|
| Direction | Client → Server |
| Type | Request |
Parameters:
No parameters.
Result: null on success.
fetchTurns
Fetches historical turns for a chat. Used for lazy loading of conversation history.
| Property | Value |
|---|---|
| Direction | Client → Server |
| Type | Request |
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
channel | URI | Yes | Chat URI |
before | string | No | Turn ID to fetch before (exclusive). Omit to fetch from the most recent turn. |
limit | number | No | Maximum number of turns to return. Server MAY impose its own upper bound. |
Result:
| Field | Type | Description |
|---|---|---|
turns | Turn[] | The requested turns, ordered oldest-first |
hasMore | boolean | Whether more turns exist before the returned range |
Example:
// Client → Server (fetch the 20 most recent turns)
{ "jsonrpc": "2.0", "id": 8, "method": "fetchTurns",
"params": { "channel": "ahp-chat:/<uuid>", "limit": 20 } }
// Server → Client
{ "jsonrpc": "2.0", "id": 8, "result": {
"turns": [ { "id": "t1", ... }, { "id": "t2", ... } ],
"hasMore": true
}}
// Client → Server (fetch 20 turns before t1)
{ "jsonrpc": "2.0", "id": 9, "method": "fetchTurns",
"params": { "channel": "ahp-chat:/<uuid>", "before": "t1", "limit": 20 } }completions
Requests completion items for a partially-typed input (e.g. a user message the user is currently composing). Used to power @-mention pickers, file/symbol references, and similar inline-completion experiences.
Servers SHOULD treat this command as best-effort and return promptly. The client SHOULD debounce calls to avoid flooding the server with requests on every keystroke.
| Property | Value |
|---|---|
| Direction | Client → Server |
| Type | Request |
Parameters:
| Field | Type | Description |
|---|---|---|
kind | CompletionItemKind | What kind of completion is being requested. |
channel | URI | The chat URI the completion is being requested for. |
text | string | The complete text of the input being completed (e.g. the full user message text typed so far). |
offset | number | The character offset within text at which the completion is requested, measured in UTF-16 code units. MUST satisfy 0 <= offset <= text.length. |
Result:
| Field | Type | Description |
|---|---|---|
items | CompletionItem[] | The completion items, in the order the server suggests displaying them. |
Example:
// User has typed "look at
---