Skip to content

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.

MemberValue
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.

MemberValueDescription
Idle1Session is idle — no turn is active.
Error1 << 1Session ended with an error.
InProgress1 << 3A turn is actively streaming.
InputNeeded(1 << 3) | (1 << 4)A turn is in progress but blocked waiting for user input or tool confirmation.
IsRead1 << 5The client has viewed this session since its last modification.
IsArchived1 << 6The session has been archived by the client.

SessionState

Full state for a single session, loaded when a client subscribes to the session's URI.

FieldTypeRequiredDescription
summarySessionSummaryYesLightweight session metadata
lifecycleSessionLifecycleYesSession initialization state
creationErrorErrorInfoNoError details if creation failed
serverToolsToolDefinition[]NoTools provided by the server (agent host) for this session
activeClientSessionActiveClientNoThe client currently providing tools and interactive capabilities to this session
chatsChatSummary[]YesCatalog of chats in this session.
defaultChatURINoThe 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.
configSessionConfigStateNoSession configuration schema and current values
customizationsCustomization[]NoTop-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.
changesetsChangeset[]NoCatalogue 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.
_metaRecord<string, unknown>NoAdditional 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.

FieldTypeRequiredDescription
clientIdstringYesClient identifier (matches clientId from initialize)
displayNamestringNoHuman-readable client name (e.g. "VS Code")
toolsToolDefinition[]YesTools this client provides to the session
customizationsClientPluginCustomization[]NoPlugin 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.

FieldTypeDescription
uriURIProject URI
displayNamestringHuman-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. Promote InputNeeded whenever any chat in the session needs input, and promote Error whenever 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 raised InputNeeded).
  • 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.

FieldTypeRequiredDescription
resourceURIYesSession URI
providerstringYesAgent provider ID
titlestringYesSession title
statusSessionStatusYesCurrent session status
activitystringNoHuman-readable description of what the session is currently doing
createdAtnumberYesCreation timestamp
modifiedAtnumberYesLast modification timestamp
projectProjectInfoNoServer-owned project for this session
modelModelSelectionNoCurrently selected model
agentAgentSelectionNoCurrently selected custom agent.

Absent (undefined) means no custom agent is selected for this session — the session uses the provider's default behavior.
workingDirectoryURINoThe 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.
changesChangesSummaryNoAggregate 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.
annotationsAnnotationsSummaryNoLightweight summary of this session's inline annotations channel (ahp-session:/&lt;uuid&gt;/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.

FieldTypeRequiredDescription
additionsnumberNoTotal number of inserted lines across all changed files.
deletionsnumberNoTotal number of deleted lines across all changed files.
filesnumberNoNumber 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.

FieldTypeDescription
uriURIStable agent URI (matches an {@link AgentCustomization.uri}).

SessionConfigPropertySchema

A session configuration property descriptor.

Extends the generic {@link ConfigPropertySchema} with session-specific display extensions.

FieldTypeRequiredDescription
enumDynamicbooleanNoDisplay 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.
sessionMutablebooleanNoWhen true, the user may change this property after session creation

SessionConfigSchema

A JSON Schema object describing available session configuration metadata.

FieldTypeRequiredDescription
type'object'YesJSON Schema: always 'object'
propertiesRecord<string, SessionConfigPropertySchema>YesJSON Schema: property descriptors keyed by property id
requiredstring[]NoJSON 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.

FieldTypeDescription
schemaSessionConfigSchemaJSON Schema describing available configuration properties
valuesRecord<string, unknown>Current configuration values

ToolDefinition

Describes a tool available in a session, provided by either the server or the active client.

FieldTypeRequiredDescription
namestringYesUnique tool identifier
titlestringNoHuman-readable display name
descriptionstringNoDescription of what the tool does
inputSchema
{
  type: 'object';
  properties?: Record<string,
  object>;
  required?: string[];
}
NoJSON Schema defining the expected input parameters.

Optional because client-provided tools may not have formal schemas. Mirrors MCP Tool.inputSchema.
outputSchema
{
  type: 'object';
  properties?: Record<string,
  object>;
  required?: string[];
}
NoJSON Schema defining the structure of the tool's output.

Mirrors MCP Tool.outputSchema.
annotationsToolAnnotationsNoBehavioral hints about the tool. All properties are advisory.
_metaRecord<string, unknown>NoAdditional 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.

FieldTypeRequiredDescription
titlestringNoAlternate human-readable title
readOnlyHintbooleanNoTool does not modify its environment (default: false)
destructiveHintbooleanNoTool may perform destructive updates (default: true)
idempotentHintbooleanNoRepeated calls with the same arguments have no additional effect (default: false)
openWorldHintbooleanNoTool 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.

MemberValue
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}.

MemberValue
Loading'loading'
Loaded'loaded'
Degraded'degraded'
Error'error'

CustomizationLoadingState

Container is being loaded by the host.

FieldTypeDescription
kindCustomizationLoadStatus.Loading

CustomizationLoadedState

Container loaded successfully.

FieldTypeDescription
kindCustomizationLoadStatus.Loaded

CustomizationDegradedState

Container partially loaded but has warnings.

FieldTypeDescription
kindCustomizationLoadStatus.Degraded
messagestringHuman-readable description of the warning.

CustomizationErrorState

Container failed to load.

FieldTypeDescription
kindCustomizationLoadStatus.Error
messagestringHuman-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.

FieldTypeDescription
typeCustomizationType.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}.

FieldTypeRequiredDescription
noncestringNoOpaque 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.

FieldTypeDescription
typeCustomizationType.Directory
contentsChildCustomizationTypeWhich child customization type this directory holds.
writablebooleanWhether 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.

FieldTypeRequiredDescription
typeCustomizationType.AgentYes
descriptionstringNoShort description of what the agent specializes in and when to invoke it. Sourced from the agent file's frontmatter description.
_metaRecord<string, unknown>NoAdditional 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.

FieldTypeRequiredDescription
typeCustomizationType.SkillYes
descriptionstringNoShort description used for help text and auto-invocation matching. Sourced from the skill's frontmatter description.
disableModelInvocationbooleanNoWhen 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.

FieldTypeRequiredDescription
typeCustomizationType.PromptYes
descriptionstringNoShort 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.

FieldTypeRequiredDescription
typeCustomizationType.RuleYes
descriptionstringNoDescription of what the rule enforces.
alwaysApplybooleanNoWhen 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.
globsstring[]NoGlob 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.

FieldTypeDescription
typeCustomizationType.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.

FieldTypeRequiredDescription
typeCustomizationType.McpServerYes
enabledbooleanYesWhether this MCP server is currently enabled.
stateMcpServerStateYesCurrent lifecycle state of the MCP server.
channelURINoAn 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.
mcpAppMcpServerCustomizationAppsNoMCP 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.

FieldTypeDescription
capabilitiesAhpMcpUiHostCapabilitiesThe 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/list and tools/call to the MCP server. When listChanged is true, the host also forwards notifications/tools/list_changed.
  • {@link serverResources}: host proxies resources/read, resources/list, and resources/templates/list to the MCP server. When listChanged is true, the host also forwards notifications/resources/list_changed.
  • {@link logging}: host accepts notifications/message log entries from the App and forwards them via mcpNotification (and forwards logging/setLevel calls to the server).
  • {@link sampling}: host serves sampling/createMessage via mcpMethodCall. When sampling.tools is present, the host also accepts SEP-1577 tools / toolChoice / tool_use content blocks inside CreateMessageRequest.
FieldTypeRequiredDescription
serverTools
{
  listChanged?: boolean;
}
NoProducer proxies the MCP tools/* methods to the upstream server.
serverResources
{
  listChanged?: boolean;
}
NoProducer proxies the MCP resources/* methods to the upstream server.
loggingRecord<string, never>NoProducer accepts notifications/message log entries from the App via mcpNotification.
sampling
{
  tools?: Record<string,
  never>;
}
NoProducer 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.

MemberValueDescription
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.

MemberValueDescription
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.

FieldTypeDescription
kindMcpServerStatus.Starting

McpServerReadyState

Server is running and serving requests.

FieldTypeDescription
kindMcpServerStatus.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.

FieldTypeRequiredDescription
kindMcpServerStatus.AuthRequiredYes
reasonMcpAuthRequiredReasonYesWhy authentication is required.
resourceProtectedResourceMetadataYesRFC 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.
requiredScopesstring[]NoScopes 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.
descriptionstringNoHuman-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.

FieldTypeDescription
kindMcpServerStatus.Error
errorErrorInfoError details.

McpServerStoppedState

Server has been shut down. The host MAY remove the server from the session entirely shortly after this state.

FieldTypeDescription
kindMcpServerStatus.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.

FieldTypeDescription
typeActionType.SessionReady

session/creationFailed

Session backend failed to initialize.

FieldTypeDescription
typeActionType.SessionCreationFailed
errorErrorInfoError 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.

FieldTypeDescription
typeActionType.SessionChatAdded
summaryChatSummaryThe 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.

FieldTypeDescription
typeActionType.SessionChatRemoved
chatURIThe 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.

FieldTypeDescription
typeActionType.SessionChatUpdated
chatURIThe URI of the chat whose summary changed.
changesPartial<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.

FieldTypeRequiredDescription
typeActionType.SessionDefaultChatChangedYes
defaultChatURINoNew 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.

FieldTypeDescription
typeActionType.SessionTitleChanged
titlestringNew title

session/modelChanged

Model changed for this session.

FieldTypeDescription
typeActionType.SessionModelChanged
modelModelSelectionNew 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}).

FieldTypeRequiredDescription
typeActionType.SessionAgentChangedYes
agentAgentSelectionNoNew 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).

FieldTypeDescription
typeActionType.SessionIsReadChanged
isReadbooleanWhether 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.

FieldTypeDescription
typeActionType.SessionIsArchivedChanged
isArchivedbooleanWhether 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.

FieldTypeDescription
typeActionType.SessionActivityChanged
activitystring | undefinedHuman-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.

FieldTypeDescription
typeActionType.SessionChangesetsChanged
changesetsChangeset[] | undefinedNew 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.

FieldTypeDescription
typeActionType.SessionServerToolsChanged
toolsToolDefinition[]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.

FieldTypeDescription
typeActionType.SessionActiveClientChanged
activeClientSessionActiveClient | nullThe 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.

FieldTypeDescription
typeActionType.SessionActiveClientToolsChanged
toolsToolDefinition[]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.

FieldTypeDescription
typeActionType.SessionCustomizationsChanged
customizationsCustomization[]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.

FieldTypeDescription
typeActionType.SessionCustomizationToggled
idstringThe id of the container to toggle.
enabledbooleanWhether 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 its children array. To preserve existing children, the host must include them on the payload.
  • If not found, the entry is appended.
FieldTypeDescription
typeActionType.SessionCustomizationUpdated
customizationCustomizationThe 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.

FieldTypeDescription
typeActionType.SessionCustomizationRemoved
idstringThe 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 startingreadyauthRequired 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.

FieldTypeRequiredDescription
typeActionType.SessionMcpServerStateChangedYes
idstringYesThe id of the {@link McpServerCustomization} to update.
stateMcpServerStateYesThe new lifecycle state.
channelURINoUpdated 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.

FieldTypeRequiredDescription
typeActionType.SessionConfigChangedYes
configRecord<string, unknown>YesUpdated config values
replacebooleanNoWhen 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.

FieldTypeDescription
typeActionType.SessionMetaChanged
_metaRecord<string, unknown> | undefinedNew _meta payload, or undefined to clear it

Commands

JSON Schema: commands.schema.json

createSession

PropertyValue
DirectionClient → Server
TypeRequest

Parameters:

FieldTypeRequiredDescription
channelURIYesSession URI (client-chosen, e.g. ahp-session:/&lt;uuid&gt;)
providerstringNoAgent provider ID
modelModelSelectionNoModel selection (ID and optional model-specific configuration)
agentAgentSelectionNoInitial custom agent selection for the new session.

Omit to start the session with no custom agent selected (provider default).
workingDirectoryURINoWorking directory for the session
forkSessionForkSourceNoFork from an existing session. The new session is populated with content from the source session up to and including the specified turn's response.
configRecord<string, unknown>NoAgent-specific configuration values collected via resolveSessionConfig. Keys and values correspond to the schema returned by the server.
activeClientSessionActiveClientNoEagerly 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.

PropertyValue
DirectionClient → Server
TypeRequest

Parameters:

No parameters.

Result: null on success.


fetchTurns

Fetches historical turns for a chat. Used for lazy loading of conversation history.

PropertyValue
DirectionClient → Server
TypeRequest

Parameters:

FieldTypeRequiredDescription
channelURIYesChat URI
beforestringNoTurn ID to fetch before (exclusive). Omit to fetch from the most recent turn.
limitnumberNoMaximum number of turns to return. Server MAY impose its own upper bound.

Result:

FieldTypeDescription
turnsTurn[]The requested turns, ordered oldest-first
hasMorebooleanWhether more turns exist before the returned range

Example:

jsonc
// 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.

PropertyValue
DirectionClient → Server
TypeRequest

Parameters:

FieldTypeDescription
kindCompletionItemKindWhat kind of completion is being requested.
channelURIThe chat URI the completion is being requested for.
textstringThe complete text of the input being completed (e.g. the full user message text typed so far).
offsetnumberThe character offset within text at which the completion is requested, measured in UTF-16 code units. MUST satisfy 0 &lt;= offset &lt;= text.length.

Result:

FieldTypeDescription
itemsCompletionItem[]The completion items, in the order the server suggests displaying them.

Example:

jsonc
// User has typed "look at

---

Released under the MIT License.