Skip to content

Add a per-chat config concept (ChatConfig) to complement session-scoped SessionConfig #335

Description

@TylerLeonhardt

Summary

AHP models config only at the session level. There is no per-chat equivalent, so config properties that are conceptually per-chat (approval posture — Claude permissionMode, Copilot autoApprove) end up shared across every chat in a session. This is surprising and security-relevant: enabling auto-approve/bypass in one chat silently grants it to sibling chats in the same session (potential privilege escalation).

Model and agent selection are already chat-scoped; config is the odd one out. This proposes adding a generic ChatConfig primitive so agents can mark individual config properties as chat-scoped.

Downstream consumer / motivation: microsoft/vscode#325826.

What AHP has today (session-only)

  • SessionState.config: SessionConfigState, the session/configChanged action, and SessionConfigPropertySchema — all session-level.
  • ChatState carries conversation state plus a few per-chat, non-conversation fields (workingDirectory, interactivity) — but no config bag and no chat/config* action.

So per-chat state is already an established pattern (ChatState.workingDirectory); per-chat config simply doesn't exist yet.

Proposal (additive, backward-compatible)

  1. ChatState.config?: SessionConfigState — an optional per-chat config bag, mirroring SessionState.config, sitting beside the existing per-chat fields.
  2. ChatConfigChangedAction{ type: ActionType.ChatConfigChanged /* 'chat/configChanged' */; config: Record<string, unknown>; replace?: boolean }, client-dispatchable, with a chatReducer case that merges/replaces state.config.values (mirror of the existing session/configChanged reducer).
  3. SessionConfigPropertySchema.chatScoped?: boolean — a per-property flag. Agents opt in individual properties (e.g. Claude permissionMode, Copilot autoApprove); everything else stays session-scoped.

Semantics

  • A chatScoped property resolves from the chat channel; non-chatScoped properties resolve from the session (unchanged).
  • Fully independent per chat (intended default): a chat's value is authoritative and seeded at chat creation from the create-time default — no live session→chat inheritance.
  • The default chat's channel is the session URI, so sessions with only a default chat are unchanged (low blast radius); only additional chats gain independent values.

Compatibility / versioning

All three additions are additive/optional:

  • An older host ignores chat/configChanged (config silently stays session-resolved).
  • An older client ignores chatScoped (treats the key as session-scoped).

MINOR protocol bump.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions