芥末
发布于 2025-09-18 / 0 阅读
0
0

Qwen Code 的 Agentic Coding 机制:Prompt、工具调用与任务管理如何协同工作

Agentic Coding(智能体式编码)和普通代码补全的区别,不在于模型能不能写出某段函数,而在于它能不能围绕一个目标持续工作。

传统的 AI(人工智能)编码助手更像“建议生成器”:开发者提出一个局部问题,模型返回一段代码或解释。Agentic Coding 更像“任务执行器”:开发者给出目标,智能体需要理解项目、拆解任务、调用工具、修改文件、运行测试,并在失败后继续调整方案。

Qwen Code 就是这种模式下的 CLI(Command Line Interface,命令行界面)工具。它修改自 Gemini CLI,并针对 Qwen3-Coder 系列模型增强了解析器和工具支持,目标是让模型在真实软件工程任务中不仅能“回答”,还能“执行”。

可以把 Qwen Code 理解成四个部分的组合:

flowchart TD
    U[用户目标] --> C[Qwen Code CLI]
    C --> P[系统 Prompt:角色、规则、工作流]
    C --> M[Qwen3-Coder 模型]
    M --> T[工具注册表 ToolRegistry]

    T --> F[文件工具:读写、搜索、编辑]
    T --> S[Shell 工具:构建、测试、命令执行]
    T --> W[Web 工具:搜索、抓取网页]
    T --> D[TodoWriteTool:任务规划与进度追踪]
    T --> MCP[MCP 工具:外部服务能力]

    F --> M
    S --> M
    W --> M
    D --> M
    MCP --> M

    M --> C
    C --> U

系统 Prompt 决定模型“应该怎么做”,工具系统决定模型“能够做什么”,任务管理机制让模型在多步骤工作中不容易跑偏,测试和标准检查则负责把结果拉回到可验证状态。


1. Qwen Code 解决的核心问题

软件工程任务通常不是单步问题。

例如“把认证模块从 urllib 重构为 requests”看起来只是替换网络库,实际执行时至少涉及这些动作:

  1. 找到认证逻辑所在文件。
  2. 阅读现有实现,理解调用方式和异常处理。
  3. 查找测试文件,判断是否有安全网。
  4. 检查依赖配置,确认 requests 是否已经存在。
  5. 修改代码。
  6. 删除旧依赖或无用 import。
  7. 运行代码检查和测试。
  8. 如果失败,根据错误继续修复。

普通对话模型可以生成修改建议,但很难稳定完成完整闭环。Qwen Code 的做法是把“软件工程任务”转成一个受约束的循环:

flowchart LR
    A[理解需求] --> B[制定计划]
    B --> C[调用工具收集上下文]
    C --> D[修改代码或文件]
    D --> E[运行构建、测试、Lint、类型检查]
    E --> F{是否通过}
    F -- 是 --> G[形成稳定检查点]
    F -- 否 --> H[分析错误并调整计划]
    H --> C

这个循环的关键不只是模型能力,还包括 Prompt 对行为的约束:什么时候该查文件、什么时候该问用户、什么时候必须验证、什么时候不能擅自扩大范围。


2. 系统 Prompt:把模型约束成“工程智能体”

Qwen Code 的内置 Prompt 主要定义在 prompts.ts 中。它不是简单告诉模型“你是一个编程助手”,而是把角色、规范、工具使用、任务管理、安全要求、Git 行为等全部写成操作规则。

可以抽象成这几层:

flowchart TD
    P[Qwen Code System Prompt]
    P --> R[Role:角色定位]
    P --> C[Core Mandates:核心工程规范]
    P --> TM[Task Management:任务管理]
    P --> WF[Primary Workflows:主要工作流]
    P --> OG[Operational Guidelines:操作指南]
    P --> SB[Sandbox:沙箱环境提示]
    P --> Git[Git Repository:版本控制规则]
    P --> EX[Examples:示例行为]

2.1 Role:先定义“它是谁”

角色定义的作用是给模型一个稳定身份:Qwen Code 是由阿里巴巴开发的交互式 CLI 智能体,专门处理软件工程任务,目标是在安全和高效的前提下帮助用户。

这类角色 Prompt 不负责具体流程,但它会影响模型整体倾向:

  • 面向软件工程,而不是泛泛聊天。
  • 使用工具完成任务,而不是只输出文字。
  • 安全优先,不能随意破坏用户系统。
  • 需要遵守后续规则,而不是自由发挥。

一个简化后的角色描述可以写成这样:

You are Qwen Code, an interactive CLI agent for software engineering tasks.
Your goal is to help users safely and efficiently by following the given rules
and using available tools.

真正重要的不是这几句话本身,而是后面配套的工程规则。


3. Core Mandates:让模型像项目成员一样改代码

代码智能体最容易犯的错误,是只按自己熟悉的方式写代码,而忽略当前项目已有约定。Qwen Code 的核心规范主要就是防止这种问题。

规范要求解决的问题
遵循项目约定修改前先看周围代码、测试和配置避免引入和项目风格不一致的实现
不假设依赖存在使用库或框架前检查配置文件和已有 import避免写出本地无法运行的代码
模仿风格和结构命名、格式、类型、架构模式都贴近现有代码避免“能跑但不像这个项目的代码”
理解局部上下文修改函数、类、import 前先看关联代码避免破坏模块边界和调用关系
少写注释注释解释“为什么”,不重复“做了什么”避免用注释替代清晰代码
主动完成隐含步骤用户要求修 bug 时,合理执行测试等后续动作避免只做表面修改
遇到范围扩张要确认超出明确需求的大动作不能擅自执行避免智能体过度发挥
文件路径使用绝对路径调工具前把相对路径解析到项目根目录下避免工具调用失败或改错文件
不随意回滚除非用户要求或自身修改导致错误,否则不回退代码避免覆盖用户已有工作

这些规则把“写代码”变成“融入现有工程”。例如模型想使用某个库时,不能因为这个库常见就直接写进去,而要先检查:

package.json
requirements.txt
Cargo.toml
build.gradle
邻近文件的 import
项目已有配置

这种约束非常重要。软件工程中的正确性不只取决于代码片段本身,还取决于它是否符合项目依赖、框架选择、测试方式和团队习惯。


4. TodoWriteTool:把长任务拆成可追踪的状态机

大模型的上下文窗口有限,多步骤任务很容易出现两类问题:

  • 任务做到一半忘了还剩什么。
  • 遇到错误后偏离最初目标。

Qwen Code 使用 TodoWriteTool 管理任务清单。它不是普通备忘录,而是让智能体把计划显式外部化。复杂任务开始时,模型需要把目标拆成多个待办项,并在执行过程中不断更新状态。

一个任务通常有三种状态:

状态含义
pending已规划,尚未开始
in_progress正在处理
completed已完成

任务管理流程可以表示为:

stateDiagram-v2
    [*] --> pending: 创建待办事项
    pending --> in_progress: 开始处理
    in_progress --> completed: 完成并验证
    in_progress --> pending: 发现新子任务
    completed --> [*]

例如用户要求“运行构建并修复所有类型错误”,智能体不应该直接开始盲改,而应先形成任务列表:

1. Run the build
2. Collect type errors
3. Fix type error #1
4. Fix type error #2
5. ...
6. Re-run build

每修完一个错误,就立即把对应任务标记为 completed,而不是等全部完成后一次性更新。这样做有两个好处:

  1. 用户能看到任务进度。
  2. 模型能持续对齐当前目标,减少遗漏。

对“新增使用量统计并支持导出”这类更大的需求,任务拆解会更明显:

1. 调研项目中已有 telemetry / metrics 代码
2. 设计指标采集结构
3. 实现核心统计逻辑
4. 实现多格式导出
5. 补充测试
6. 运行项目验证命令

Todo 机制本质上是在给智能体增加一个外部工作记忆。


5. 软件工程任务工作流:边做边理解,而不是等完全理解

Qwen Code 处理修 bug、加功能、重构、解释代码等任务时,遵循一个迭代式工作流。

flowchart TD
    A[Plan:基于已有信息制定初步计划]
    B[Implement:一边实现一边收集必要上下文]
    C[Adapt:遇到新信息后更新计划和 Todo]
    D[Verify Tests:运行项目测试]
    E[Verify Standards:运行构建、Lint、类型检查]

    A --> B
    B --> C
    C --> B
    B --> D
    D --> E
    E --> F{发现问题?}
    F -- 是 --> C
    F -- 否 --> G[稳定结果]

这里有一个很实用的原则:不要等到掌握所有信息才开始。软件项目很大时,完全理解再动手成本很高。更合理的方式是先制定一个粗略计划,然后在实施过程中用工具补齐上下文。

5.1 Plan:先有方向

对于简单任务,计划可以很短。对于复杂任务,需要使用 TodoWriteTool 记录。

例如:

目标:把 src/auth.py 中的 urllib 调用重构为 requests

计划:
1. 查找认证模块相关测试
2. 检查 requests 是否是项目依赖
3. 修改 src/auth.py
4. 运行 lint 和测试

5.2 Implement:工具优先,不靠猜

实现阶段会用到代码搜索、文件读取、批量读取、编辑、Shell 等工具。

常见工具组合如下:

目的工具
找文件GlobTool
搜关键字GrepTool
读单个文件ReadFileTool
批量读文件ReadManyFilesTool
修改文件EditTool
写新文件WriteFileTool
执行命令ShellTool

模型遇到不确定问题时,应该调用工具确认,而不是凭经验补全。例如测试命令不能直接假设是 npm test,需要查看 READMEpackage.json 或已有 CI 配置。

5.3 Adapt:发现新信息后调整计划

开发任务经常在执行中变化。

例如模型本来只准备改一个文件,但搜索后发现认证逻辑拆在多个模块里;或者测试失败暴露出调用方也依赖旧异常类型。这时应该更新 Todo,而不是硬按最初计划继续。

新增任务:
- 更新调用方对 AuthError 的处理
- 补充 requests 超时异常测试

5.4 Verify:验证不是可选项

Qwen Code 的工作流把验证拆成两类:

验证类型例子目的
测试验证pytestnpm run testgo test ./...确认功能行为正确
标准验证tscnpm run lintruff check .确认类型、格式、静态规则没有破坏

关键点是:命令必须来自项目本身,不能假设标准命令一定存在。


6. 新应用工作流:先确认方案,再进入实现

当用户要求从零实现一个新应用时,Qwen Code 的行为会更谨慎,因为新应用往往涉及技术栈、交互方式、视觉风格和平台选择。

它的流程可以表示为:

sequenceDiagram
    participant U as 用户
    participant Q as Qwen Code
    participant T as TodoWriteTool
    participant FS as 文件与命令工具

    U->>Q: 描述要实现的新应用
    Q->>Q: 分析功能、平台、约束、用户体验
    Q-->>U: 提出高层方案和技术栈
    U-->>Q: 批准或修改方案
    Q->>T: 把方案拆成待办事项
    Q->>FS: 创建项目、写代码、生成占位资源
    Q->>FS: 构建并检查编译错误
    Q-->>U: 给出启动方式并请求反馈

如果用户没有指定关键技术,Qwen Code 会倾向使用一组默认选择:

应用类型默认倾向
前端网站React + JavaScript/TypeScript + Bootstrap CSS,结合 Material Design 思路
后端 APINode.js + Express.js,或 Python + FastAPI
全栈应用Next.js,或 Python 后端搭配 React/Vue 前端
CLI 工具Python 或 Go
跨端移动应用Compose Multiplatform 或 Flutter
Android 原生Jetpack Compose
iOS 原生SwiftUI
3D 游戏HTML/CSS/JavaScript + Three.js
2D 游戏HTML/CSS/JavaScript

这里的重点不是默认技术栈本身,而是“未指定时给出合理方案,并等待用户批准”。这可以避免智能体一上来就生成大量代码,最后发现方向和用户预期不一致。


7. 操作指南:CLI 场景下要短、准、可执行

Qwen Code 运行在命令行里,交互方式和网页聊天不同。CLI 场景更重视直接、精简和动作优先。

它的输出风格可以概括为:

要求含义
简洁直接不写闲聊和长铺垫
输出少能用工具完成的动作,不用文字解释一大段
必要时保证清晰遇到歧义时可以问简短问题
Markdown 格式适配终端渲染
工具做动作,文字做沟通不在工具调用里夹杂解释性废话
无法完成时直接说明1 到 2 句话说明原因,并给替代方案

例如用户问:

1 + 2

合适回答就是:

3

用户要求启动服务器:

start the server implemented in server.js

智能体应该调用 Shell 工具执行类似命令:

node server.js &

不需要输出一大段解释。


8. 安全规则:能执行命令不代表可以乱执行

Agentic Coding 最大的风险之一,是模型拥有 Shell 和文件写入能力。Qwen Code 的 Prompt 对这类行为做了明确限制。

8.1 修改系统状态的命令要说明影响

在执行会修改文件系统、代码库或系统状态的命令前,需要简短说明命令目的和潜在影响。

例如用户要求删除临时目录,智能体可以说:

I can run `rm -rf /path/to/project/temp`.
This will permanently delete the directory and all its contents.

这里不需要过度解释,但必须让用户知道命令会造成什么结果。

8.2 不能泄露或提交敏感信息

模型生成代码时不能引入会暴露 secret、API key、token 的逻辑,也不能把敏感信息写入日志或提交到仓库。

8.3 沙箱外运行要额外提醒

如果环境变量显示当前不在 sandbox(沙箱)中,而是直接运行在用户系统上,那么对于可能影响项目目录外或系统临时目录外的关键命令,需要提醒用户考虑启用沙箱。

这条规则针对的是“工具能力越强,误操作代价越高”的问题。


9. 工具系统:ToolRegistry 把能力注册给模型

Prompt 负责规定行为,工具负责提供动作能力。Qwen Code 使用 ToolRegistry 统一注册工具,大体分成三类。

flowchart TD
    TR[ToolRegistry]
    TR --> Core[Core Tools:内置工具]
    TR --> MCP[MCP Tools:通过 MCP 服务发现]
    TR --> Disc[Discovered Tools:运行时发现的用户工具]

    Core --> L[LSTool]
    Core --> R[ReadFileTool]
    Core --> G[GrepTool]
    Core --> GB[GlobTool]
    Core --> E[EditTool]
    Core --> W[WriteFileTool]
    Core --> Sh[ShellTool]
    Core --> TD[TodoWriteTool]

9.1 Core Tools:内置核心工具

内置工具由 Config.createToolRegistry() 注册,是 Qwen Code 完成软件工程任务的基础。

工具作用
LSTool列出目录内容
ReadFileTool读取单个文件
GrepTool在文件中搜索文本或模式
GlobTool根据 glob 模式查找文件
EditTool对已有文件做就地修改
WriteFileTool写入新文件或覆盖文件内容
WebFetchTool从 URL 获取内容
ReadManyFilesTool批量读取文件或读取 glob 匹配结果
ShellTool执行 Shell 命令
MemoryTool记录用户明确要求保存的偏好或事实
TodoWriteTool规划任务和追踪进度
WebSearchTool执行网络搜索,需要满足 Tavily API key 等条件

这些工具组合起来,覆盖了智能体写代码所需的主要动作:找文件、读代码、改代码、跑命令、记录进度、查询外部信息。

9.2 MCP Tools:接入外部工具生态

MCP(Model Context Protocol,模型上下文协议)允许工具通过 MCP server 暴露给模型。Qwen Code 会根据本地 settings.json 中的 MCP 配置发现可用服务,并把它们注册成 DiscoveredMCPTool

这种方式的好处是工具能力可以扩展,不必全部写死在 Qwen Code 内部。例如团队可以通过 MCP 接入内部文档、数据库查询、工单系统或特定代码分析服务。

9.3 Discovered Tools:运行时发现的用户工具

还有一类工具来自运行时动态发现,功能和实现由用户定义的命令决定。它适合把项目或团队已有脚本封装成智能体可调用能力。


10. 工具调用规则:路径、并行、命令和确认

工具系统不是“模型想怎么调就怎么调”。Prompt 中对工具调用有很多细粒度要求。

规则说明
文件路径必须是绝对路径用户给相对路径时,模型要根据项目根目录解析
独立工具调用可以并行例如同时搜索多个目录或读取多个无依赖文件
Shell 用于执行命令修改性命令执行前要解释目的和影响
长时间运行命令使用后台进程例如 node server.js &
避免交互式命令优先用 npm init -y 这类非交互形式
复杂任务主动使用 Todo避免遗漏需求
Memory 只保存用户相关偏好不保存一般项目上下文
用户取消工具调用后要尊重不能马上重复发起同一个调用

其中“绝对路径”很容易被忽略,但对 CLI 智能体非常重要。工具调用如果拿到相对路径,可能会因为工作目录不一致而失败,甚至改到错误位置。


11. Git 仓库规则:提交前先看清变化

当当前目录是 Git 仓库时,Qwen Code 会增加一组版本控制规则。用户要求提交或准备提交时,智能体不能直接 git commit,而要先收集信息。

推荐命令组合类似:

git status && git diff HEAD && git log -n 3

各命令的作用如下:

命令目的
git status查看文件状态,确认哪些文件已修改、未跟踪或已暂存
git diff HEAD查看工作区相对上次提交的全部修改
git diff --staged只查看暂存区修改,适合部分提交
git log -n 3查看最近提交信息,匹配项目提交风格

提交信息也有约束:

  • 应清晰、简洁。
  • 更关注“为什么改”,而不是机械描述“改了什么”。
  • 智能体应该主动给草稿,而不是把完整提交信息丢给用户填写。
  • 提交后运行 git status 确认状态。
  • 未经用户明确要求,不能 push 到远程仓库。

这个流程可以降低两个风险:把不该提交的文件提交进去,以及生成和项目风格不一致的提交记录。


12. 一个重构任务如何跑完整闭环

用“把 src/auth.pyurllib 重构为 requests”做例子,可以看到 Qwen Code 的典型执行方式。

sequenceDiagram
    participant U as 用户
    participant Q as Qwen Code
    participant FS as 文件工具
    participant SH as ShellTool

    U->>Q: Refactor src/auth.py to use requests instead of urllib
    Q->>FS: Glob 查找 tests/test_auth.py
    Q->>FS: ReadFile 读取测试文件
    Q->>FS: ReadFile 读取 requirements.txt
    Q->>Q: 确认有测试覆盖且 requests 可用
    Q->>FS: Edit 修改 src/auth.py
    Q->>SH: ruff check src/auth.py && pytest
    SH-->>Q: 返回检查结果
    Q-->>U: 检查通过,形成稳定检查点

对应的智能体思路大致是:

1. 先找认证逻辑相关测试,确认修改有安全网。
2. 读取 requirements.txt,确认 requests 已经是项目依赖。
3. 制定重构计划:
   - 替换 urllib 调用
   - 增加 requests 网络异常处理
   - 删除 urllib import
   - 运行 lint 和测试
4. 修改文件。
5. 执行 ruff check src/auth.py && pytest。
6. 如果通过,询问是否需要准备提交。

这类任务效果高度依赖模型的 Tool Use(工具调用)能力。模型必须知道什么时候该搜索、什么时候该读文件、什么时候该编辑、什么时候该运行命令,还要能根据工具返回结果调整下一步。


13. Prompt 设计背后的几个工程原则

Qwen Code 的设计可以提炼成几条更通用的智能体工程原则。

13.1 把 Prompt 写成操作契约,而不是口号

“你是一个优秀程序员”这类描述太弱。更有效的是写清楚:

  • 修改代码前要观察项目约定。
  • 使用依赖前要检查配置。
  • 不确定测试命令时不能猜。
  • 文件工具必须使用绝对路径。
  • 修改性命令要说明影响。
  • 用户取消工具调用后不能重复尝试。

这些都是可执行、可检查的规则。

13.2 给模型外部状态

复杂任务不能只靠模型短期记忆。TodoWriteTool 把目标、步骤、状态放到外部工具中,让模型和用户都能看到当前进展。

13.3 工具调用要和工作流绑定

工具越多,越需要规则。没有工作流约束时,模型可能乱搜、乱改、乱跑命令。Qwen Code 把工具调用嵌入“计划—实施—调整—验证”的循环里,让每次调用都有上下文目的。

13.4 验证必须项目化

不同项目的测试命令、构建命令、Lint 命令差异很大。智能体不能把 npm testpytestgo test ./... 当成默认真理,而要从项目文件中确认。

13.5 安全规则要前置

当智能体有 Shell 权限时,安全不是附加项。删除文件、修改系统状态、提交代码、访问外部服务都需要明确边界。


14. 使用这类工具时容易踩的坑

问题表现处理方式
Prompt 规则冲突模型一会儿要求极简输出,一会儿又长篇解释把规则分层,明确优先级
不使用 Todo复杂任务执行到一半遗漏步骤多步骤任务强制创建和更新任务清单
盲目假设依赖代码引用不存在的库修改前检查配置文件和邻近代码
盲目假设测试命令执行错误命令或漏掉关键验证从 README、配置文件、CI 脚本中查找
工具路径错误相对路径导致读写失败调工具前统一解析为绝对路径
Shell 权限过大误删文件或改到项目外使用沙箱,并对高风险命令说明影响
擅自扩大范围用户只要解释,智能体直接改代码超出明确需求时先确认
只生成代码不验证改完看似合理,实际无法编译把测试、构建、Lint 作为闭环的一部分

15. 一个可复用的智能体 Prompt 骨架

如果要设计类似的软件工程智能体,可以参考这种结构,而不是把所有要求堆成一段话:

# Role
You are a CLI coding agent focused on software engineering tasks.

# Core Rules
- Follow existing project conventions.
- Verify dependencies before using them.
- Use absolute paths for file tools.
- Do not revert user changes unless asked.
- Ask before expanding task scope.

# Task Management
- Use a todo tool for multi-step tasks.
- Mark each task in_progress when starting.
- Mark each task completed immediately after finishing.

# Workflow
- Plan based on available context.
- Implement while collecting more context through tools.
- Adapt the plan when new information appears.
- Run project-specific tests, build, lint, and type checks.

# Tool Usage
- Use search tools to locate files and references.
- Use read tools before editing.
- Use shell tools for build and verification.
- Explain destructive or system-modifying commands.

# Git
- Inspect status and diff before committing.
- Draft a concise commit message.
- Never push unless explicitly requested.

这样的 Prompt 更接近“操作系统说明书”。模型不是被要求“表现得聪明”,而是被安排在一套可执行流程里持续推进任务。


结语

Qwen Code 的关键能力来自三件事的组合:细粒度 Prompt 规则、可调用的工程工具、持续更新的任务状态。Prompt 让模型知道边界和流程,工具让模型能操作真实项目,Todo 机制让长任务可追踪,测试和标准检查让结果可验证。

Agentic Coding 的价值不只是生成代码,而是把需求分析、上下文检索、代码修改、构建测试和反馈修复串成闭环。开发者在这种模式下更像任务设计者和结果审核者,需要给出目标、约束和判断标准;智能体则承担大量重复性的查找、修改和验证工作。


评论