Repository navigation
Description
Clients
- Android: native Android client on
com.microsoft.agenthostprotocol:agent-host-protocol:1.0.0. Negotiates1.0.0. Tested against the VS Code host over Dev Tunnels. - agent-mesh: TypeScript MCP server that is a raw JSON-RPC AHP client of the local VS Code agent host (named pipe, negotiates
1.1.0). It lets sessions list, read, message, consult (side chat), spawn, fork, configure and supervise each other.
Environment: VS Code 1.144.0, host protocol 1.1.0. Findings were observed live and checked against this repo at v1.0.0 and main, and against src/vs/platform/agentHost on main. Each item is tagged with its layer and the client(s) that observed it. Where an issue already exists, we link it rather than repeat it.
A. VS Code host
A1. subscribe ignores SubscribeView.turns, and fetchTurns is a stub. [vscode-host] (Android, confirmed in source)
- The spec side landed in Add lazy chat turn paging #300. In
protocolServerHandler.ts, the state-channelsubscribehandler never readsparams.view, andfetchTurnsonly sendschat/turnsLoadedwithturns: []. With"view": {"turns": 10}the host returns every retained turn in one frame withturnsNextCursor: null. - Over Dev Tunnels:
- a long text chat arrived as one ~9.8M-character frame after ~13 s;
- a screenshot-heavy chat (>26 MiB) never arrived.
- Related: Remote agent host: large chat history exceeds tunnel gateway frame limit and causes terminal timeout vscode#339997 (frame cap), Agent host gateway: accept frames up to 100 MiB and close peers on errors vscode#345181 (raises the gateway limit to 100 MiB), agentHost: add windowed delivery and TCP forwarding vscode#341812 (windowed delivery; state subscriptions not yet migrated), Agents window: switching to a chat on a remote agent host takes seconds (up to ~26s) vscode#344521 (slow remote chat open).
- Raising the frame cap lets these snapshots through but doesn't shrink them. Ask: honour
view.turns, setturnsNextCursor, and implementfetchTurns.
A2. 1.1.0 features on 1.0.0-negotiated connections. [vscode-host] (Android)
- The client offers
["1.0.0","0.9.0"]and negotiates1.0.0. The host still sendschat/configChanged('1.1.0'inregistry.ts, from chat: per-chat config so approvals in one chat no longer change every chat #527),chatMutableandChatState.config. 1.0.0 SDKs decodechat/configChangedas an unknown action. - Ask: filter actions and fields by the negotiated version. Related: Actions added after the v0.9.0 release are registered as 0.9.0 #491.
A3. Other things sent on the AHP socket that aren't AHP 1.0.0. [vscode-host] (Android)
- Raw MCP
{"method":"notifications/tools/list_changed"}frames arrive on the AHP WebSocket (26 in one 60 s window while MCP and customization state was changing). - The pre-1.0.0
archivedboolean still appears onSessionChatSummaryalongsidestatus.
A4. session/ready isn't sent after createSession. [vscode-host] (both clients)
- +1 to AHP 1.0 createSession does not emit session/ready until the first turn vscode#332831; still present on 1.144.0. Clients that wait for
readytime out. - Also consider returning
defaultChatfromcreateSession, and acceptinginitialMessagethe waycreateChatdoes.
A5. listSessions order and filters. [vscode-host] (both clients)
- Results come back in id or creation order, though the spec says they SHOULD come most-recently-modified first.
- There are no filters (status, modified-since, project or working directory, provider), so clients fetch every page.
A6. A missing message.agent means "no custom agent" (spec), but a missing model keeps the chat's model. [spec] / [vscode-host] (both clients)
- We first read the agent reset as a host bug. It matches the spec (
Message.agent: "Absent means no custom agent"), as Keep a chat's custom agent when another session sends it a message vscode#345120 explains, so both clients now resend the agent on every turn. - The trap is the asymmetry: when
modelis left out, the VS Code host keeps the chat's current model (changeModelruns only when a model applies), while the spec says "the agent host's default model applies". Ask: document that clients should resend both on every turn, or make the two fields behave the same.
A7. Model config read back from a turn includes host-internal keys. [vscode-host] (both clients)
turn.message.model.configcontains keys outside the model'sconfigSchema(for examplereasoningEffortandvscode.modelConfiguration.<key>.source). Sending it back with an effort change contradicts the change.
B. Spec and SDKs
B1. Kotlin SnapshotStateSerializer decodes terminal snapshots as SessionState. [kotlin-sdk] (Android; v1.0.0 and main)
containsKey("lifecycle")is checked beforecontainsKey("content"), andTerminalState.lifecycleis required, so every terminal snapshot goes toSessionState.serializer()and throws.- Fix: check
contentfirst, or route toSessionStateonly whenlifecycleis a string.
B2. Fields the host sends are declared only on sibling types. [spec] → generated SDKs (Android)
sessionMutableandchatMutableare declared only onSessionConfigPropertySchema. The host also sends them onRootState.config.schema.properties.*, which is typed asConfigPropertySchema.nonceandchildEnablementare declared only onClientPluginCustomization. The host reflects them back inSessionState.customizationsandsession/customizationUpdated, which are typed asPluginCustomization.- Typed SDKs drop all four. Ask: declare them on the types the host uses, or stop sending them there.
B3. Types with no _meta. [spec] (both clients)
ChatSummary,SessionChatSummary,AgentInfoandActionEnvelopehave no_meta.
B4. VS Code _meta fields worth promoting into the schema. [spec] (both clients)
- git state on sessions:
_meta.git.*, and_meta.gitData.<folder>.*for multi-root; _meta["vscode.external"], used by the Agents panel's default filter;_meta.vscode.skill.argumentHint;_vscodeEditAttributionon tool results;- tool-call
mcpServerName/mcpToolName/subagentAgentName(+1 to Clarify interoperable association of an MCP tool call with its original server tool name #525).
C. Identity, trust and agent-to-agent use
These come from the local MCP client.
C1. Session-started processes can't tell which AHP session they belong to. [vscode-host] / [spec]
- MCP servers and hooks get only the SDK id (
COPILOT_AGENT_SESSION_ID). We map it to a session by scanningusage._meta["vscode.modelCall"].sdkSessionIdacross active chats. That fails before a session's first model call, for sub-agents (only anagentId), and for non-Copilot providers. - Seen live on 2026-11-01: in a continued session, every turn (the running one included) carried an older SDK session's id, while the session's MCP servers got the newer
COPILOT_AGENT_SESSION_IDof the SDK session actually writing events. So the mapping breaks exactly when sessions are continued. - Ask: give the session and chat URIs to session-started processes, or put them in each MCP tool call's
_meta.
C2. The connection token can't be scoped. [spec] / [vscode-host]
- One
connectionToken(sent as?tkn=in the URL) can approve tools, start turns and dispose any session. Related: Agent Host: dispatchAction does validate not whether clients can dispatch that action vscode#332434 (dispatchActiondoesn't check whether the client may dispatch that action type). - Ask:
- grants scoped by capability or session at
initialize; - a host rule that a session can't answer its own
inputNeeded; - the token sent in a header or subprotocol rather than the URL.
- grants scoped by capability or session at
C3. The host doesn't record who sent a message. [spec]
- The VS Code host already accepts and stores
origin.kind: "agent"onchat/turnStarted(see Support authorized client submission of non-user messages #542 and Allow non-user input through existing chat actions #551). But which client or session sent the message is only in client-written_meta, which anyone can forge. - Ask: the host stamps the sending
clientId/clientInfo(and the session, if known) on stored messages.
C4. Approval settings can't be compared across providers. [spec]
autoApprove,permissionModeandcodex.permissionsPresethave no shared ranking, so "a child session never gets more autonomy than its parent" needs per-provider hard-coding.- Ask: a rank annotation in the schema, or a normalised effective approval level.
C5. Client-contributed tools disappear on disconnect. [spec] / [vscode-host]
- Tools added with
session/activeClientSetvanish when the client disconnects, so only a long-lived process can keep them available. Related:ToolDefinitionhas no way for a client to scope a tool away from tool-spawned chats #446 and RFC: Observable client services with requests and zero-ack notifications #470.
D. Behaviour worth documenting (local client)
- Steering. A mid-turn steering message to a Copilot session ran as the next turn. +1 to Steering consumed as a new turn ends the running turn with a
chat/turnCompletethat looks like the agent finished #550. - Event delivery. Root notifications arrive without subscribing to
ahp-root://, but action echoes reach only subscribers. "All chats idle" has no event, so clients poll. Ask: document the delivery rules, and send a summary change event when a chat's status changes. - Logs channel.
ahp-otlp://logs/{level}is advertised, butresourceReadon it fails;subscribeworks but has no history.
We can share probe scripts and redacted wire captures for any item.
Activity