Originally published on IndieSeek.
Qwen Code 0.22: shrink the tool surface before enabling auto approvals
Quick answer
Qwen Code v0.22.0 makes one built-in tool safer by default and one approval mode easier to reach from SDKs. list_directory is now opt-in: it is not registered or sent to the model unless you enable tools.listDirectory.enabled or explicitly include it in coreTools. Python and Java SDK startup options now accept auto, matching the CLI and TypeScript SDK. In that mode, an LLM classifier evaluates each tool call and automatically approves actions it classifies as safe while blocking risky ones.
These changes do not make auto a least-privilege policy. Qwen has three different control layers: which tools are registered, which calls skip confirmation, and where an approved call can execute. Treat them separately, inspect the actual tool surface, and keep default approval until harmless negative canaries pass.
Who this is for
This guide is for teams embedding Qwen Code through the CLI, Python, Java, or TypeScript SDK and searching for a safe alternative to --yolo. It is especially useful with local OpenAI-compatible backends, custom agents, MCP servers, or unattended repository jobs where extra tool schemas and ambiguous approvals create real operational risk.
If the repository itself may be untrusted, pair this rollout with the Qwen workspace-trust checklist. Workspace trust decides which project configuration may load; this article decides which tools the running agent can see and how their calls are approved.
What changed in 0.22—and what did not
| Layer | Stable v0.22.0 behavior |
What it does not prove |
|---|---|---|
| Tool registration |
list_directory is off by default; settings or coreTools can restore it |
That every filesystem tool is disabled, or that non-core tools are covered |
| Invocation approval | Python and Java SDKs accept auto; an LLM classifier evaluates calls |
A deterministic allowlist, human approval, or safe execution |
| Runtime containment | Qwen's own Autofix workflow binds a pulled sandbox image to its digest | That every user-created Qwen sandbox or runner has equivalent isolation |
The distinction matters because stable TypeScript SDK documentation describes coreTools as a registration allowlist, while allowedTools and permissions.allow bypass confirmation for matching calls. Qwen's stable permission-manager tests also show that MCP, Skill, Agent, and several synthetic tools are separate from the built-in coreTools surface. A short list of core tools is therefore a useful reduction, not proof that the complete session has only those capabilities.
Use a three-layer authority matrix
| Question | Control to inspect | Evidence to keep |
|---|---|---|
| Can the model see this tool? |
coreTools, tools.listDirectory.enabled, disabled tools, extension/MCP registration |
/tools capture plus outbound tool-name list |
| Can this call run without asking? | Approval mode, permissions.allow, permissions.ask, permissions.deny, SDK callback |
Tool name, redacted arguments, rule matched, decision source |
| What can an approved call reach? | Sandbox, workspace boundary, process identity, filesystem/network policy | Disposable write/read probes and denied neighboring action |
Never use evidence from one row to certify another. A hidden tool might still be reachable through MCP. A visible tool can still require approval. An auto-approved call can still be confined—or dangerously unconstrained—by the host runtime.
A six-step rollout workflow
1. Pin the exact executable
Run /about and record the reported Qwen Code version, commit when available, runtime, model/provider, approval mode, sandbox state, and workspace. This guide was checked against stable tag v0.22.0, commit 1c3a385d9bc83e0b2a1ce5a24454ce1d090595fb. Do not use a nightly build to claim stable behavior.
2. Start with a small registered core
Use a disposable repository and default approval. A canary session can start with:
qwen --approval-mode default --core-tools read_file,grep_search,glob
Confirm /tools does not show list_directory, editing, or shell execution. Then deliberately ask for a directory listing and verify Qwen uses glob or reports that list_directory is unavailable. If the workflow truly needs the old tool, enable it explicitly and repeat the inventory; do not restore it merely to silence a prompt.
3. Verify the outbound schema, not only the UI
A public issue filed against exact 0.22.0 reports one setup where /tools looked reduced but the local OpenAI-compatible backend still received the full built-in tools array. This is one user report, not a universal finding, but it gives a valuable canary: capture only outbound tool names through a recording proxy or provider debug log and compare them with /tools. Redact arguments, prompts, credentials, paths, and file content.
If the two inventories disagree, stay in interactive mode. Do not treat a settings file or a smaller UI list as sufficient proof.
4. Test approval separately
Keep the registered tool set fixed and compare default with auto using harmless calls:
- Read a known fixture inside the disposable workspace.
- Request a write to a disposable file and record whether the call asks, is approved, or is blocked.
- Request an obviously out-of-scope neighboring action without using a real secret or destructive command.
- Add an explicit deny for that neighboring action and prove it remains denied.
auto is a classifier decision, so require the audit record to say decision_source=classifier. Do not rewrite it as policy allow or human approved.
5. Run seven canaries
-
list_directoryis absent by default. - Explicit opt-in restores it and a restart makes the change observable.
- A built-in tool omitted from
coreToolsis unavailable to the session. - The outbound tool-name inventory matches the intended registered surface.
-
defaultprompts for the disposable write. -
autorecords its classifier decision without silently becomingyolo. - The same denied neighboring action stays denied in both modes.
For MCP, Skills, and custom agents, add separate inventory and denial tests. They are not automatically certified by the built-in-core canaries. Use the MCP safe-replay checklist when a permitted call can change external state.
6. Promote by action class
Start with read-only repository exploration. Add bounded edits only after rollback and diff review work. Keep shell, network writes, publishing, billing, deployment, secrets, and destructive filesystem actions on explicit human approval or deterministic policy. A sandbox reduces consequences; it does not make a classifier an authority to spend money, publish content, or destroy state.
Decision tree
Is the tool required for this task?
no -> do not register it
yes -> can its scope be reduced further?
yes -> narrow core/MCP registration and inventory again
Does the call change state or cross a trust boundary?
yes -> explicit human or deterministic approval
no -> run harmless default-mode canary
did schema, decision, and containment evidence agree?
no -> keep interactive and fix the boundary
yes -> consider a bounded auto-mode pilot
Common mistakes
- Treating
permissions.allowas proof that unlisted schemas were never sent. - Calling
auto“safe mode” or a deterministic allowlist. - Assuming
coreToolscovers MCP, Skills, custom agents, and every synthetic tool. - Enabling
list_directorybecause an old prompt names it, without checking whetherglobalready completes the task. - Testing with real credentials, production repositories, or destructive commands.
- Calling Qwen's Autofix digest binding a guarantee for every user sandbox.
- Recording only the final tool result and losing the version, registered surface, matched rule, and decision source.
Copyable acceptance record
qwen_version / commit / install_channel / runtime:
workspace / provider / model / sandbox:
registered_core_tools / mcp_tools / skill_tools / agent_tools:
outbound_tool_names_match_inventory: yes | no | not-observable
approval_mode / permission_rules / sdk_callback:
canary / tool / redacted_scope / expected / actual:
decision_source: human | deterministic-rule | classifier | none
containment_result / denied_neighbor / rollback_result:
promotion: hold | read-only | bounded-edit | human-required
FAQ
Is auto safer than yolo?
It is more selective: auto uses an LLM classifier, while yolo automatically approves all tool calls. But selective does not mean deterministic or sufficient for high-impact actions. Keep explicit approval for sensitive state changes.
Why is list_directory disabled if Qwen can still inspect files?
The release says glob covers directory listing in most cases, so removing the near-duplicate tool reduces prompt and selection surface. It is not a general filesystem-access switch; other read tools still exist.
Should I use permissions.allow or coreTools to shrink schemas?
For stable v0.22.0, treat coreTools as the built-in registration allowlist and permissions.allow as invocation auto-approval. Then verify the actual outbound tool names. Do not rely on naming or migration text alone.
Sources
- Qwen Code stable
v0.22.0release - Qwen Code PR #9424: make
list_directoryopt-in - Qwen Code PR #9003: Python and Java SDK support for
auto - Qwen Code
v0.22.0TypeScript SDK permission documentation - Qwen Code
v0.22.0settings reference - Qwen Code issue #9827: exact-version schema-surface report
- Qwen Code PR #9527: Autofix sandbox-image digest binding
Read the maintained version on IndieSeek.
Top comments (0)