Skip to content

ACP session/set_mode("plan") returns success but does not enforce plan mode behavior #1806

@kaizhou-lab

Description

@kaizhou-lab

Summary

When using the ACP protocol (qwen --acp), calling session/set_mode with modeId: "plan" returns a successful response {"modeId": "plan"}, but subsequent session/prompt calls still allow the agent to perform file edits and command execution — the plan mode restriction is not actually enforced.

Environment

  • Qwen Code version: 0.9.1 (qwen --version)
  • OS: macOS (Darwin 24.6.0)
  • Node.js: v25.1.0

Steps to Reproduce

  1. Start Qwen in ACP mode:

    qwen --acp
  2. Send initialize:

    {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{"fs":{"readTextFile":true,"writeTextFile":true}}}}
  3. The initialize response correctly reports plan mode as available:

    {
      "modes": {
        "currentModeId": "default",
        "availableModes": [
          {"id": "plan", "name": "Plan", "description": "Analyze only, do not modify files or execute commands"},
          {"id": "default", "name": "Default", "description": "Require approval for file edits or shell commands"},
          {"id": "auto-edit", "name": "Auto Edit", "description": "Automatically approve file edits"},
          {"id": "yolo", "name": "YOLO", "description": "Automatically approve all tools"}
        ]
      }
    }
  4. Create a session:

    {"jsonrpc":"2.0","id":2,"method":"session/new","params":{"cwd":".","mcpServers":[]}}
  5. Switch to plan mode:

    {"jsonrpc":"2.0","id":3,"method":"session/set_mode","params":{"sessionId":"<session-id>","modeId":"plan"}}
  6. Response confirms the mode change:

    {"jsonrpc":"2.0","id":3,"result":{"modeId":"plan"}}
  7. Send a prompt that would normally trigger file modifications:

    {"jsonrpc":"2.0","id":4,"method":"session/prompt","params":{"sessionId":"<session-id>","prompt":[{"type":"text","text":"Create a hello.py file"}]}}

Expected Behavior

After session/set_mode("plan") succeeds, the agent should operate in read-only / analysis-only mode:

  • No file edits (write, replace, create, delete)
  • No command execution (shell commands)
  • Agent should only analyze, plan, and provide suggestions without performing any modifications

This matches the initialize response description: "Analyze only, do not modify files or execute commands".

Actual Behavior

After session/set_mode("plan") returns success, the agent still proposes and executes file edits and commands as if it were in default mode. The mode switch is acknowledged at the protocol level but not enforced at the behavior level.

Context

We are building AionUi, a GUI for CLI AI agents including Qwen Code. We integrate with Qwen via the ACP protocol and rely on session/set_mode to provide mode switching in the UI.

  • Claude Code: session/set_mode("plan") works correctly — the agent switches to read-only behavior.
  • Qwen Code: session/set_mode("plan") returns success but behavior does not change.

Our full call chain (all returning success):

AionUi UI → IPC bridge → AcpAgentManager.setMode("plan")
  → AcpAgent.setMode("plan")
  → AcpConnection.setSessionMode("plan")
  → JSON-RPC: session/set_mode { sessionId, modeId: "plan" }
  ← Response: { modeId: "plan" }  ✅
  → Next prompt: agent still performs edits  ❌

Additional Notes

  • session/set_mode("yolo") and session/set_mode("auto-edit") have the same potential issue — they return success but we haven't deeply verified their behavior enforcement yet.
  • The interactive CLI (qwen without --acp) does enforce plan mode correctly via Shift+Tab, so the mode logic exists in the codebase — it may just not be wired up in the ACP code path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions