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
-
Start Qwen in ACP mode:
-
Send initialize:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{"fs":{"readTextFile":true,"writeTextFile":true}}}}
-
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"}
]
}
}
-
Create a session:
{"jsonrpc":"2.0","id":2,"method":"session/new","params":{"cwd":".","mcpServers":[]}}
-
Switch to plan mode:
{"jsonrpc":"2.0","id":3,"method":"session/set_mode","params":{"sessionId":"<session-id>","modeId":"plan"}}
-
Response confirms the mode change:
{"jsonrpc":"2.0","id":3,"result":{"modeId":"plan"}}
-
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.
Summary
When using the ACP protocol (
qwen --acp), callingsession/set_modewithmodeId: "plan"returns a successful response{"modeId": "plan"}, but subsequentsession/promptcalls still allow the agent to perform file edits and command execution — the plan mode restriction is not actually enforced.Environment
qwen --version)Steps to Reproduce
Start Qwen in ACP mode:
Send
initialize:{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{"fs":{"readTextFile":true,"writeTextFile":true}}}}The
initializeresponse 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"} ] } }Create a session:
{"jsonrpc":"2.0","id":2,"method":"session/new","params":{"cwd":".","mcpServers":[]}}Switch to plan mode:
{"jsonrpc":"2.0","id":3,"method":"session/set_mode","params":{"sessionId":"<session-id>","modeId":"plan"}}Response confirms the mode change:
{"jsonrpc":"2.0","id":3,"result":{"modeId":"plan"}}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:This matches the
initializeresponse 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_modeto provide mode switching in the UI.session/set_mode("plan")works correctly — the agent switches to read-only behavior.session/set_mode("plan")returns success but behavior does not change.Our full call chain (all returning success):
Additional Notes
session/set_mode("yolo")andsession/set_mode("auto-edit")have the same potential issue — they return success but we haven't deeply verified their behavior enforcement yet.qwenwithout--acp) does enforce plan mode correctly viaShift+Tab, so the mode logic exists in the codebase — it may just not be wired up in the ACP code path.