Skip to content

Feedback from two AHP clients: Android (Kotlin SDK) and a local MCP bridge #556

Open

Description

Clients

  • Android: native Android client on com.microsoft.agenthostprotocol:agent-host-protocol:1.0.0. Negotiates 1.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)

A2. 1.1.0 features on 1.0.0-negotiated connections. [vscode-host] (Android)

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 archived boolean still appears on SessionChatSummary alongside status.

A4. session/ready isn't sent after createSession. [vscode-host] (both clients)

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 model is left out, the VS Code host keeps the chat's current model (changeModel runs 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.config contains keys outside the model's configSchema (for example reasoningEffort and vscode.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 before containsKey("content"), and TerminalState.lifecycle is required, so every terminal snapshot goes to SessionState.serializer() and throws.
  • Fix: check content first, or route to SessionState only when lifecycle is a string.

B2. Fields the host sends are declared only on sibling types. [spec] → generated SDKs (Android)

  • sessionMutable and chatMutable are declared only on SessionConfigPropertySchema. The host also sends them on RootState.config.schema.properties.*, which is typed as ConfigPropertySchema.
  • nonce and childEnablement are declared only on ClientPluginCustomization. The host reflects them back in SessionState.customizations and session/customizationUpdated, which are typed as PluginCustomization.
  • 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, AgentInfo and ActionEnvelope have no _meta.

B4. VS Code _meta fields worth promoting into the schema. [spec] (both clients)

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 scanning usage._meta["vscode.modelCall"].sdkSessionId across active chats. That fails before a session's first model call, for sub-agents (only an agentId), 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_ID of 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]

C3. The host doesn't record who sent a message. [spec]

C4. Approval settings can't be compared across providers. [spec]

  • autoApprove, permissionMode and codex.permissionsPreset have 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]

D. Behaviour worth documenting (local client)

We can share probe scripts and redacted wire captures for any item.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

under-discussionIssue is under discussion for relevance, priority, approach

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions