Skip to content

feat: add !model command for runtime model switching via session/set_model (Kiro backend) #185

@sh14y

Description

@sh14y

Summary

Add a !model Discord command that lets users list and switch the underlying LLM model for the current ACP session at runtime, without restarting the bot or recreating the session.

Motivation

Kiro CLI's ACP server already exposes multiple models (Claude Opus 4.6 / Sonnet 4.6 / Haiku 4.5 / Auto). Today openab pins whatever Kiro chose at session/new time and there is no in-Discord way to change it. Different tasks benefit from different models (e.g. Opus for hard reasoning, Haiku for cheap quick replies, Auto when you don't care). Letting users switch in-thread keeps the workflow inside Discord.

ACP protocol verification

Verified against Kiro CLI v1.29.3:

  1. session/new response now includes a models object:
    {
      "result": {
        "sessionId": "...",
        "models": {
          "currentModelId": "auto",
          "availableModels": [
            { "modelId": "auto",               "name": "Auto",      "description": "..." },
            { "modelId": "claude-opus-4.6",    "name": "Opus 4.6",  "description": "..." },
            { "modelId": "claude-sonnet-4.6",  "name": "Sonnet 4.6","description": "..." },
            { "modelId": "claude-haiku-4.5",   "name": "Haiku 4.5", "description": "..." }
          ]
        }
      }
    }
  2. session/set_model JSON-RPC method accepted:
    { "method": "session/set_model",
      "params": { "sessionId": "...", "modelId": "claude-opus-4.6" } }
    → { "result": {} }

Proposed command design

Inside an allowed channel/thread:

Input Behavior
!model List all available models, marking the current one
!model opus Switch to claude-opus-4.6
!model sonnet Switch to claude-sonnet-4.6
!model haiku Switch to claude-haiku-4.5
!model auto Switch back to auto-routing
!model <id> Accept any exact modelId from availableModels
!model <unknown> Reply with error + available list

Aliases (opus, sonnet, haiku, auto) are resolved client-side; otherwise the exact modelId is forwarded.

Models marked [Deprecated] or [Internal] in their description are filtered out of the list.

Implementation outline

  • New ModelInfo { model_id, name, description } in src/acp/connection.rs
  • AcpConnection gains current_model: String and available_models: Vec<ModelInfo>
  • session_new() parses the models block from the response
  • New AcpConnection::session_set_model(model_id) and resolve_model_alias(input)
  • Handler::message() intercepts messages whose prompt starts with !model and dispatches via pool.with_connection

Backend scope

This is currently wired against the Kiro ACP backend (which is the only one I've validated session/set_model on). Other backends that don't implement the method will simply error on switch and report _(no models reported by agent — backend may not support model switching)_ when listing.

PR with the implementation will follow this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions