Qwen Code Auto Mode 深度指南:LLM 分类器驱动的工具调用审批机制与配置实战
2026/9/14 4:26:21 网站建设 项目流程

Qwen Code Auto Mode 深度指南:LLM 分类器驱动的工具调用审批机制与配置实战

【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code

Auto Mode(自动模式)是 Qwen Code 五种审批模式中介于 Auto-Edit 与 YOLO 之间的"智能审批"层:它用一个 LLM 分类器逐次评估每一次工具调用,自动放行安全操作、拦截风险操作,让长时间自主会话既不被频繁打断,又不至于完全失控。本文以 auto-mode.md 为骨架,结合仓库源码(autoMode.ts、classifier.ts、system-prompt.ts 等)展开,完整覆盖 Auto Mode 的三层判定流程、硬规则优先级、hints 配置、回退机制与故障排查,读者读完可独立配置并调优 Auto Mode。

从五种审批模式看 Auto Mode 的定位

Qwen Code 提供五种权限模式(见 approval-mode.md),Auto Mode 的定位是"Auto-Edit 太保守、YOLO 太危险"时的中间档:

模式文件编辑Shell 命令适用场景风险
Plan❌ 只读分析❌ 不执行代码探索、复杂变更规划、安全审查最低
Ask Permissions✅ 需手动批准✅ 需手动批准陌生代码库、关键系统、教学协作
Auto-Edit✅ 自动批准❌ 需手动批准日常开发、重构、安全自动化
Auto✅ 分类器评估✅ 分类器评估长时间自主会话、信任项目、无人值守任务
YOLO✅ 自动批准✅ 自动批准受信任个人项目、CI/CD、批量处理最高

Auto Mode 默认是开箱即用的模式。会话中可按Shift+Tab(Windows 为 Tab)循环切换模式(plan → default → auto-edit → auto → yolo),状态栏会实时显示当前模式。也可以用命令切换:/approval-mode auto;若希望新会话默认进入 Auto Mode,在.qwen/settings.json中设置:

// .qwen/settings.json { "tools": { "approvalMode": "auto" } }

首次进入 Auto Mode 时会弹出一条说明信息,关闭后会在用户设置中写入ui.autoModeAcknowledged: true,之后不再重复出现。

三层判定:acceptEdits 快路径、安全工具白名单与 LLM 分类器

当会话处于 Auto Mode 且 Agent 尝试执行某个工具时,Qwen Code 会按顺序走三层过滤器。三层过滤只会在权限管理器(L4)判定为'default'(无规则命中)时触发;用户显式写了ask规则时快路径被跳过,用户意图优先。核心编排逻辑集中在 evaluateAutoMode。

第一层:acceptEdits 快路径

edit/write_file而言,只要目标路径位于当前工作区内,就直接自动批准,不调用分类器(passesAcceptEditsFastPath)。

例外情况:写入 Qwen Code 自身的"自修改面"和"持久化面"的调用,即使在工作区内也会被强制送进分类器。源码中以两组正则定义这些路径(autoMode.ts):

  • 自修改面SELF_MODIFICATION_PATH_PATTERNS):.qwen/settings*.jsonQWEN.mdAGENTS.md.qwen/qwen.local.md.qwen/rules/.qwen/commands/.qwen/agents/.qwen/skills/.qwen/hooks/.qwen/fork-profiles/.mcp.json,以及通过getAllMemoryFilenames()获得的配置上下文文件名;
  • 持久化面PERSISTENCE_PATH_PATTERNS):.git/(git 配置与钩子)、.husky/package.json.npmrcMakefile/GNUmakefile.justfileTaskfile.yml.github/workflows/——这些文件会被后续工具链当作可执行代码读取,一旦被静默改写风险极高。

源码还会解析符号链接(fs.realpathSync):指向受保护路径的 symlink 会被解析后一并拒绝。Shell 命令通过cd && bash -lc '...'或重定向等方式触及这些路径时同样会进入分类器——shouldForceAutoModeReviewForAllow 会从命令中解析出虚拟edit/write_file操作、重定向目标(> file)以及tar -Cpatch --outputcurl -o等写盘参数做路径校验(hasRawProtectedRedirect、hasRawProtectedWriteCommand)。

第二层:安全工具白名单

只读与元数据类内置工具直接自动批准,不调用分类器。白名单定义于 SAFE_TOOL_ALLOWLIST,包括:read_filezoom_imagegrepgloblslsptool_searchtodo_writestructured_output,以及ask_user_questionexit_plan_modeenter_plan_modecron_listtask_stop

值得注意的刻意排除项:send_message不在白名单中——它会向另一个运行中的 Agent 注入任意文本作为新指令,分类器必须看到目的地与消息内容,以判断跨 Agent 消息是否在诱导对端执行破坏性动作。MCP 工具(mcp__*)也一律不在白名单内,因为它们是第三方代码,无法静态信任。

第三层:两阶段 LLM 分类器

其余所有调用(Shell 命令、网络抓取、子 Agent 派生、工作区外编辑、MCP 工具)进入两阶段分类器,实现在 classifier.ts 的 classifyAction:

  • Stage 1(快速判定):仅输出{ shouldBlock }maxOutputTokens=256,temperature=0,约 300ms。若shouldBlock为 false 直接放行;
  • Stage 2(思考复核):仅当 Stage 1 判定 block 时运行。使用 chain-of-thought 复查以降低 Stage 1 的误杀率,可把 Stage 1 的 block 降级为 allow,block 时输出用户可见的reason

两个阶段的超时与思考配置可通过permissions.autoMode.classifier调优,源码默认值分别为STAGE1_TIMEOUT_MS = 10_000STAGE2_TIMEOUT_MS = 30_000(classifier.ts)。Stage 2 默认关闭 provider 级 thinking(thinkingConfig.includeThoughts: false),但thinking输出字段仍会携带模型的普通文本推理。

分类器复用你配置的fast model/model --fast查看/设置)。若未配置 fast model,则回退使用主会话模型。分类器产出的reason在注入主模型工具错误信息前会经过 sanitizeClassifierReason 清洗:剥除<...>伪标签(迭代最多 8 轮防重叠绕过)、折叠空白、截断至 200 字符,防止恶意分类器输出冒充系统消息注入主 Agent。

[!tip] 权限系统检测为只读的 Shell 命令(如lscatgit log)在到达分类器之前就会被自动批准。设置permissions.autoMode.classifyAllShell: true可覆盖此行为,强制所有 Shell 命令都经过分类器——详见下文"强制分类所有 Shell 命令"。

硬规则仍然优先:deny / allow / ask 的边界

Auto Mode不会取代硬性权限规则。在分类器运行之前:

  • permissions.deny规则直接以规则自身的 reason 拦截动作,分类器根本看不到该调用;
  • 带具体 specifier 的permissions.allow规则(如Bash(git status)Read(./docs/**))仍然绕过分类器直接放行——例外是当调用解析到受保护的自修改/持久化路径时,Auto Mode 会重新把调用送进分类器复核。这样一条Bash(*)的 allow 规则不可能静默变成改写 Qwen Code 设置、命令、钩子、技能或 MCP 服务器的通行证;
  • permissions.ask规则即使在 Auto Mode 下也强制要求手动确认。

在分类器层之前还有一道确定性防线:破坏性命令正则硬拦截(L5.2.5)。对 shell-like 工具,isDestructiveCommand 会结合最近的用户 prompt 与 cwd 做正则级硬判,命中即返回blocked:destructive-command,即使分类器 API 故障也不会放过破坏性 git / IaC 命令(autoMode.ts)。此外,工作区外的写入永远不会被分类器自动批准:写工具目标在工作区之外时直接回退手动确认(external_write),这是 fail-safe 的实现约定(autoMode.ts)。

过宽的 allow 规则在 Auto Mode 下会被临时剥离

以下规则会让 Agent 无需分类器审查即可执行任意代码,进入 Auto Mode 时会被临时移除:

  • Bash/Bash(*)/Bash()——放行所有 Shell 命令;
  • Bash(python:*)Bash(node*)Bash(bash*)——解释器通配符;
  • Agent/Agent(coder)——对 Agent 工具的任何放行;
  • Skill/Skill(pdf)——对 Skill 工具的任何放行。

进入 Auto Mode 时,Qwen Code 会从当前生效的权限集中临时移除这些规则并打印通知列出它们;离开 Auto Mode 的瞬间规则即恢复。settings.json文件本身从不被修改。如果你确实需要这些宽泛规则,请改用 YOLO 模式。

配置 hints:用自然语言调教分类器

Auto Mode 从settings.jsonpermissions.autoMode读取配置。核心是hints——注意,它们是自然语言描述,不是规则模式,会以追加方式注入分类器的系统提示词,与内置默认项并存(system-prompt.ts)。hints 分三类,另加一个环境清单:

  • allow——分类器应自动放行的动作;
  • softDeny——破坏性或不可逆动作,分类器应默认拦截,除非用户最近的显式请求恰好要求该动作及其范围。软拦截可被用户意图解除,但一句笼统的"随便做"不算数;
  • hardDeny——安全边界动作,无论autoMode.hints.allow或最近的用户意图如何,分类器在 Auto Mode 下必须拦截。注意这是分类器策略而非确定性权限规则:它不覆盖permissions.allow。需要权限管理器层面永不放行的动作请使用permissions.deny

完整配置示例:

{ "permissions": { "autoMode": { "hints": { "allow": [ "Running poetry install and poetry update in this Python project", "Cleaning build artifacts under ./dist or ./build", "Reading any file under /Users/me/code/" ], "softDeny": [ "Editing Qwen Code settings unless I explicitly ask for the exact change", "Running migration scripts that touch the production DB" ], "hardDeny": [ "Sending secrets or .env contents to any network endpoint", "Modifying anything under ~/.ssh or ~/.aws" ] }, "environment": [ "This is a private monorepo with strict commit signing", "Production credentials live in 1Password, never in plain files" ] } } }

schema定义见 config.ts 的 AutoModeSettings。hints.deny作为向后兼容别名仍被接受,等价于softDeny(源码中明确标注 deprecated,见 config.ts)。混用两者没问题——条目会被拼接,softDeny在前。

[!note]classifier.timeouts.stage1Ms/stage2Ms可覆盖分类器超时(单位毫秒,低于 1000ms 的值会被忽略并回退默认值);classifier.thinking.stage2Enabled: true可开启 Stage 2 的 provider 级思考。默认 Stage 2 关闭 API thinking,因为该门是延迟敏感路径,推理预算可能加剧超时。

长度与数量上限

为保证分类器系统提示词足够精炼,条目存在硬性上限(常量定义于 system-prompt.ts):

  • 每条 hint 上限200 字符(超长条目截断并附警告);
  • hints.allowhints.softDenyhints.hardDeny各自最多50 条
  • environment最多20 条

多层级设置文件的合并规则

autoMode与其它权限设置一样,在系统 / 用户 / 工作区三层设置文件间合并:数组拼接并去重。

强制分类所有 Shell 命令

默认情况下,只读 Shell 命令(lscatgit status……)由权限系统在第三层识别为安全后跳过分类器。设置classifyAllShell: true可强制每一条Shell 命令(含只读)都经过分类器:

{ "permissions": { "autoMode": { "classifyAllShell": true } } }

适合生产或高安全环境做纵深防御:即使是看似无害的命令也要先被分类器审查。代价是额外延迟(每条只读 Shell 调用约 300ms),并且依赖分类器可用性——分类器 API 不可达时,只读 Shell 命令也会要求手动批准。实现见 shouldClassifyAllShellForAutoMode,仅影响 shell-like 工具(run_shell_commandmonitor);read_filegrep_searchgloblist_directory等内置只读工具不受影响,仍走快路径白名单。

解读分类结果:被拦截时发生了什么

当分类器拦截某个动作时,工具调用会以如下错误失败:

  • Blocked by auto mode policy: <reason>——分类器判定动作不安全,reason 来自 Stage 2。

该消息之后紧跟一行指引,告知 Agent:被拒绝的那个具体动作不得通过其它工具、shell 间接执行、生成脚本、别名、符号链接、配置变更、钩子、命令文件、MCP 配置、编码载荷或等价路径完成。无关的安全工作和确实更安全的替代方案仍被允许——只有"用不同表面达成同一被拒意图"才会被拦截。该指引文本定义于 AUTO_MODE_DENIAL_GUIDANCE,并通过 formatClassifierBlockMessage 统一注入,保证调度器与 ACP 两条路径行为一致。

如果被拒动作确实必要,Agent 应当停下来向你请求显式批准,而不是绕道规避。这一点与分类器系统提示词中的 Denied Tool Calls 规则保持一致。

分类器 reason 的语言

分类器 reason 由 LLM 生成且不做翻译。如果你希望得到非英文 reason,可在permissions.autoMode.environment中加入类似Respond reasons in Chinese的 hint。

回退到手动批准:防卡死设计

Auto Mode 内置了防止"卡死"的保护机制,由 denialTracking.ts 的状态机实现:

  • 分类器 API 不可达 / 超时 / 超出上下文窗口 / 返回无效响应:当前动作立即回退到手动批准。确认弹窗会推荐 Default Mode,并提供Switch to Default Mode and allow once(切换仅影响当前运行时会话,不改变已保存设置)、Allow once 与 Reject 三个选项;
  • 连续 3 次策略拦截consecutive_block):下一次工具调用回退到标准手动批准弹窗。这覆盖了"Agent 反复尝试某个被禁命令的微小变体"的场景;
  • 连续 2 次 unavailableconsecutive_unavailable,分类器 API 故障):后续调用跳过已知损坏的分类器,直接走手动批准。第一次 unavailable 已经会询问用户;该阈值避免反复等待分类器重试。

会话仍保持在 Auto Mode,除非你显式选择切换选项——只有回退的那一次调用走手动批准。当你批准回退调用或切换模式时,计数器重置。所有回退 reason 与提示文案集中在 autoMode.ts 与 formatDenialFallbackMessage。

如果频繁触发回退,最可能的原因是分类器 API 故障或 hints 需要调优。排查期间可切换到 Default Mode:/approval-mode default

故障排查

"Auto mode keeps blocking my commands"(Auto Mode 一直拦截我的命令)

查看错误信息中的 reason。如果分类器对你的场景过于保守,在permissions.autoMode.hints.allow中用自然语言添加描述该模式的条目,例如:

  • "Building Docker images for this project (docker build ...)"
  • "Running database migrations against the local test DB"

"Auto mode classifier unavailable"(分类器不可用)

分类器 API 无响应。可能原因:

  • 你与模型端点之间存在网络问题;
  • 配置的 fast model 已不可用——检查/model --fast
  • 会话转录过长,超出 fast model 的上下文窗口。

排查期间切回 Default Mode:/approval-mode default

"Falling back to manual approval"(回退到手动批准)

命中了 3 次连续拦截或 2 次连续不可用保护。像平常一样批准或拒绝弹窗即可;一次批准的回退之后连续计数会重置。

"分类器能看到我 prompt 里的敏感数据"

工具输入在到达分类器前会经过每个工具的toAutoClassifierInput方法做投影(per-tool 投影)。长编辑内容、web fetch 的 prompt、子 Agent 的 prompt 会被截断。工具结果(文件内容、网页内容)永远不会发给分类器——只有用户文本和助手工具调用会经过。

如果某个工具暴露了你希望脱敏的字段,可提交 issue 并附上工具名;投影按工具逐个收紧。

数据边界:什么会到达分类器

分类器只看到每个工具toAutoClassifierInput投影暴露的内容(autoMode.md 中的 FAQ 与 classifier-transcript.ts 的实现一致):

工具分类器看到的内容
read_file等只读工具不调用(走快路径白名单)
edit/write_file文件路径 + 旧/新内容各 300 字符预览,完整内容不转发
run_shell_command完整命令(分类器必须评估它)
web_fetch仅 URL,prompt 字段不转发
agent子 Agent 类型 + 完整 prompt(分类器需识别诱导子 Agent 破坏的注入攻击)
mcp__*服务器名、工具名、服务器自报注解、调用参数(有界截断)

工具结果(工具返回的实际内容)会从分类器转录中完全剥离。历史动作每条上限 4,000 字符、总计 40,000 字符(MAX_HISTORICAL_ACTION_CHARS/MAX_HISTORICAL_ACTIONS_TOTAL_CHARS,见 classifier-transcript.ts),保留最新的、更早的只留工具名。

MCP 参数转发细节:每个字符串值/键截断至 2,000 字符,名称截断至 200 字符,整个载荷共享 16,000 字符预算(按分类器收到的 pretty-printed 形式计量),嵌套/条目数有上限;每次截断都在原位标记(…[truncated N chars][omitted: …])并附带arguments_truncated: true/name_truncated: true标志,让分类器不会把省略误认为"不存在"。这些参数本就是主模型已生成、准备发给该服务器的内容,转发给同一模型配置下的分类器不构成新的泄露;若分类器运行在不同的 provider上,可设permissions.autoMode.mcp.forwardArguments: false恢复仅工具名的投影——此时大多数 MCP 调用会被保守拦截。

局限性

  • 不可离线运行:分类器依赖一次 LLM 调用;
  • 慢路径有额外延迟:白名单 + acceptEdits 覆盖大多数调用无延迟,但一次run_shell_command通常增加约 300ms(快速分类路径)或约 3-5s(带思考复核的慢路径);
  • 不能替代deny规则:分类器是尽力而为。确定永远不该运行的命令请写入permissions.deny
  • MCP 工具按参数而非已验证行为判定:第三方 MCP 工具(mcp__*)永远不在快路径白名单;来自未标记trust: true服务器的每次调用都会带着服务器名、工具名、服务器自报注解(readOnlyHint/destructiveHint/idempotentHint/openWorldHint)和有界参数副本进入分类器,且分类器被告知这些注解未经核实。它无法看到服务器实际执行了什么,因此"误导性的工具名 + 无害参数"仍可能通过。若你信任某个具体 MCP 工具,添加permissions.allow: ["mcp__server__tool"]让它完全绕过分类器(实现见 mcp-tool.ts 的 toAutoClassifierInput)。

常见问题

Auto Mode 会把我的代码发给第三方吗?

不会引入新端点。Auto Mode 复用你现有的模型配置——与主 Agent 同一端点。如果你把 Qwen Code 配置为自托管模型,分类器也跑在该端点上。

我的 secrets /.env内容会到达分类器吗?

只读工具根本不调用分类器;edit/write_file只转发 300 字符预览;工具结果被完全剥离。唯一必须转发全文的是run_shell_command的命令和agent的 prompt(这正是分类器要判断的对象)。

如何关闭首次进入的信息提示?

它每个用户设置文件只显示一次。关闭后用户设置中会写入ui.autoModeAcknowledged: true

与 Auto-Edit 有何区别?

Auto-Edit 只自动批准文件编辑,Shell 命令仍然询问。Auto Mode 用分类器同时自动批准安全的 Shell 命令与其它工具调用,同时拦截风险操作。

与 YOLO 有何区别?

YOLO 不经过任何审查自动批准一切。Auto Mode 有分类器在环,会拦截风险动作。

小结

Auto Mode 是 Qwen Code 在"流畅性"与"安全性"之间的工程化折中:三层过滤器把最常见的调用(工作区内编辑、只读工具)挡在分类器之外换取零延迟,把真正有风险的调用交给两阶段 LLM 分类器做细粒度判断;硬规则优先、过宽 allow 剥离、破坏性命令正则硬拦截、工作区外写入强制手动确认等机制共同构成了"分类器出错也不会失控"的兜底。对长时间自主会话、无人值守任务与受信任项目,理解 autoMode.ts 与 classifier.ts 的实现细节,有助于写出贴合团队策略的 hints 配置,让分类器的放行与拦截行为真正符合你的预期。

【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询