Open Interpreter qwen-code Harness 深度解析:Qwen Code CLI 提示词在 Chat Completions 请求中的复现机制
本文以 Open Interpreter 仓库中 qwen-code harness 的系统提示词文件为核心,完整拆解这份提示词的设计理念(核心约束、任务管理、工作流、安全与 Git 规范),并结合 qwen_code.rs 的源码说明该提示词如何被编译进二进制、如何拼装启动上下文、如何归一化历史消息,以及 harness = "qwen-code" 的配置方式与自动推断规则。读完后,你可以掌握一个 Agent 系统提示词从 Markdown 文件到最终 provider 请求体的完整链路。
一、qwen-code 是什么:Open Interpreter 的提示词级 harness
Open Interpreter 的 harness 模式通过替换"模型可见的提示词、工具 schema、消息转换与响应处理"来模拟外部 CLI 编码代理(如 Claude Code、Kimi Code、Qwen Code)的行为,但不真正调用外部可执行程序——工具仍在原生 Rust 运行时中执行(详见 Harness 文档)。
qwen-code 是其中一个 harness ID。从路由源码看,它与线协议(wire API)的匹配关系是严格的一对一:
- 在 routing.rs 中,
(WireApi::Chat, Harness::QwenCode)组合被解析为StreamTransportRoute::ChatHarness(ChatHarnessRoute::QwenCode),即走 Chat Completions 兼容线; - 若 provider 声明的是
wire_api = "messages",则会直接报错wire_api = "messages" is not supported by harness = "qwen-code"(见 routing.rs),单元测试 qwen_code_chat_wire_uses_harness_native_chat_route 固化了这一行为。
harness ID 的字符串解析在 Harness 枚举:配置值 Some("qwen-code") 映射为 Harness::QwenCode。也就是说,你只需在配置中写:
harness = "qwen-code"
或在单次运行时临时指定:
interpreter -c harness='"qwen-code"' "solve this task"
1.1 何时自动进入 qwen-code 模式
即使不显式配置,Open Interpreter 也可能自动推断出 qwen-code。从 model-provider-info/src/lib.rs 的推断逻辑看,只要满足以下任一条件,默认 harness 即为 qwen-code:
- 模型 ID 包含
qwen(如QwQ系模型也会经由qwq家族命中); - provider ID 或名称包含
qwen或dashscope; - base URL 包含
dashscope.aliyuncs.com/compatible-mode或dashscope-intl.aliyuncs.com/compatible-mode。
这与 docs/harness.md 中"Qwen/QwQ/DashScope provider ids, names, base URLs, or model ids → qwen-code"的表格一致;显式配置的 harness = "..." 优先级始终最高。
二、系统提示词全文骨架:qwen_code_prompt.md 的设计拆解
qwen_code_prompt.md 是一份约 250 行的完整 Agent 系统提示词,它通过 qwen_code.rs 中的 include_str! 宏在编译期嵌入二进制:
const QWEN_CODE_SYSTEM_PROMPT: &str = include_str!("qwen_code_prompt.md");
其开头声明了角色定位:"You are Qwen Code, an interactive CLI agent developed by Alibaba Group, specializing in software engineering tasks." 全文由以下章节构成,每一节都针对 CLI Agent 的特定失效模式而设计。
2.1 Core Mandates:十条核心约束
这一节是提示词的行为基线,覆盖了 Agent 修改代码时的典型陷阱:
- Conventions(遵循约定):读写或修改代码前,先分析周边代码、测试与配置,严格遵循项目既有约定;
- Libraries/Frameworks(禁止臆测依赖):绝不假设某个库可用——必须检查
package.json、Cargo.toml、requirements.txt、build.gradle等配置文件或相邻文件的导入,确认其在项目中已被使用; - Style & Structure(风格模仿):模仿既有代码的格式、命名、框架选择、类型标注与架构模式;
- Idiomatic Changes(地道修改):编辑前理解本地上下文(imports、函数/类),让改动自然融入;
- Comments(谨慎注释):注释只写"为什么"而不写"是什么";不要编辑与本次改动无关的注释;绝不允许用注释向用户说话或描述改动内容;
- Proactiveness(彻底完成):加功能/修 bug 时要附带测试,且所有创建的文件(尤其测试)默认视为持久产物;
- Confirm Ambiguity/Expansion(边界确认):不越过请求的明确范围执行重大动作;如果用户只是问"怎么做",先解释而不是直接动手;
- Explaining Changes(静默交付):完成代码修改或文件操作后,除非被要求,否则不提供总结;
- Path Construction(绝对路径):调用
read_file/write_file等文件系统工具前,必须把项目根目录的绝对路径与相对路径拼接成完整绝对路径(例如根目录为/path/to/project/,文件为foo/bar/baz.txt,最终必须是/path/to/project/foo/bar/baz.txt);用户给出相对路径时也要先对根目录解析; - Do Not revert changes(不回滚):除非用户要求,否则不还原代码库的既有变更;只有你自己造成的错误性改动才回滚。
这些约束的共性是压缩 Agent 的"自作主张"空间:不臆测依赖、不越权扩大范围、不输出总结噪音、路径必须绝对化。
2.2 Task Management:todo_write 强制规划
提示词要求高频使用 todo_write 工具进行任务跟踪与拆解,并给出两个完整的 <example> 示范对话:
- 示例一(修构建):"Run the build and fix any type errors" → Agent 先写两条 todo(跑构建、修类型错误),构建暴露 10 个错误后追加 10 条 todo,然后逐条
in_progress → completed,直到全部完成; - 示例二(新功能):实现"使用指标跟踪与导出"功能 → 先规划"调研既有指标代码 → 设计采集系统 → 实现核心功能 → 创建导出功能"四个步骤,边做边标记状态。
关键行为准则是:完成一个任务就立即标记完成,不许攒着批量标记。提示词用"如果规划时不用这个工具,你可能会忘记重要任务——这是不可接受的"这种强语气来保证执行率。
2.3 提问机制与主工作流
提问:ask_user_question 工具用于澄清、验证假设或在不确定时做决策;展示选项或计划时禁止给出时间估算,只描述每个选项包含什么。
软件工程任务遵循"Plan → Implement → Adapt → Verify"迭代循环:
- Plan:基于现有认知先形成粗略计划并用
todo_write记录,不等待完全理解; - Implement:在实施中遇到具体未知时,战略性地使用
grep_search、glob、read_file收集上下文; - Adapt:发现新信息或障碍时更新计划与 todo;
- Verify (Tests):用项目自身定义的测试命令验证——通过 README、
package.json等构建配置或既有测试执行模式来识别,绝不假设标准测试命令; - Verify (Standards):改动后必须执行已识别的项目特定 build/lint/类型检查命令(如
tsc、npm run lint、ruff check .);若不确定命令,可以先询问用户是否要跑、怎么跑。
其核心原则是:"基于可用信息先给出合理计划,然后边学边调整。用户更愿意快速看到进展,而不是等待完美理解。"
2.4 New Applications:新建应用的六步流程
对于从零构建应用的请求,提示词定义了六步目标导向流程:理解需求(缺关键信息时用 ask_user_question 精准提问)→ 提出计划(含技术选型偏好表)→ 获得用户批准 → 实施(用 todo_write 拆解,npm init/npx create-react-app 等脚手架命令)→ 验证(对照原始需求与批准的计划,修复 bug 与占位资源,最后必须构建应用且确保无编译错误)→ 征求反馈(附启动方式说明)。
技术选型偏好(用户未指定时)包括:前端 React + Bootstrap(Material Design 原则);后端 Node.js/Express 或 Python/FastAPI;全栈 Next.js 或 Django/Flask + React/Vue;CLI 用 Python 或 Go;移动端 Compose Multiplatform 或 Flutter,原生端 Jetpack Compose / SwiftUI;3D 游戏 HTML/CSS/JS + Three.js;2D 游戏 HTML/CSS/JS。对需要视觉资产(游戏贴图、图标)的应用,策略是用基础几何体、程序化图案或开源素材做占位,模型能自产简单资产(如纯色方块贴图、简单 3D 立方体)就自己生成。
2.5 Operational Guidelines:CLI 交互与安全规则
语气与风格为 CLI 场景专门调校:
- 专业、直接、简洁,尽可能每次回复少于 3 行文字(不含工具调用/代码);
- 需要澄清时清晰度优先于简短;
- 禁止闲聊式铺垫("Okay, I will now...")和收尾("I have finished the changes...");
- 使用 GitHub-flavored Markdown,输出按等宽字体渲染;
- 工具用于"做",文字仅用于"说"——不要在工具调用内加解释性注释;
- 无法满足请求时一两句说明即可,不做过度辩护,可给出替代方案。
安全规则有两条硬约束:
- Explain Critical Commands:执行会修改文件系统、代码库或系统状态的
run_shell_command命令前,必须先简述命令目的与潜在影响;但不需要请求许可——用户端会弹确认对话框(提示词特别注明"你不需要告诉用户这一点"); - Security First:绝不引入暴露、记录或提交 secrets/API 密钥等敏感信息的代码。
工具使用细则还包括:文件操作一律绝对路径(不支持相对路径);独立的多个工具调用尽量并行(如并行检索代码库);常驻命令(如 node server.js)用 is_background: true 后台执行,且使用托管后台模式时不要在命令尾部追加 &;避免需要交互的 shell 命令(如 git rebase -i),优先非交互变体(npm init -y),否则提醒用户交互命令不受支持、可能挂起;文件搜索优先委托给 agent 子代理工具以节省上下文;尊重用户的取消操作——用户取消某个 function call 后不得重试,除非用户在后续提示中主动要求同一调用。
交互细节方面,提示词声明了 /help(查看帮助)与 /bug(报错与反馈)两个斜杠命令。
2.6 Outside of Sandbox 与 Executing actions with care
这两节共同构成"非沙箱环境下的风险控制":
- Outside of Sandbox:Agent 声明自己运行在用户系统上而非沙箱容器中。对特别可能修改项目目录或系统临时目录之外状态的命令,在解释命令时须额外提醒用户考虑启用沙箱。
- Executing actions with care:以"可逆性与爆炸半径"为决策框架——本地可逆操作(改文件、跑测试)可自由执行;但对难以逆转、影响共享系统或破坏性强的动作,默认先确认再执行。具体列举的高风险动作清单包括:
- 破坏性操作:删除文件/分支、删库表、杀进程、
rm -rf、覆盖未提交变更; - 难以逆转的操作:force-push、
git reset --hard、修改已发布提交、降级依赖、改动 CI/CD 流水线; - 他人可见/影响共享状态的操作:push 代码、创建/关闭/评论 PR 与 issue、发消息(Slack/邮件/GitHub)、改共享基础设施或权限;
- 上传内容到第三方 Web 工具(图表渲染、pastebin、gist)即等于公开发布,需考虑内容敏感性(即使日后删除也可能已被缓存或索引)。
- 破坏性操作:删除文件/分支、删库表、杀进程、
其中一条关键授权语义值得注意:用户批准某次操作(如一次 git push)不等于批准所有场景下的同类操作——除非持久指令(如 QWEN.md 文件)中有事先授权,否则每次都先确认;授权的效力只覆盖指定范围。遇到障碍时也不得用破坏性动作"抹掉问题"(如 --no-verify 绕过安全检查),要查根因;对陌生文件/分支/锁文件,先调查再删。
2.7 Git Repository:提交工作流规范
提示词假定当前项目目录受 git 管理,并规定了标准的提交流程:
- 先收集信息:
git status确认跟踪/暂存状态(按需git add);git diff HEAD查看自上次提交以来工作区的全部变更(含未暂存);需要部分提交时用git diff --staged只看已暂存部分;git log -n 3查看最近 3 条提交信息以匹配其风格(详略、格式、署名行); - 尽量合并命令以省时,例如
git status && git diff HEAD && git log -n 3; - 必须主动给出提交信息草稿,而不是让用户自己写;草稿偏好"why"多于"what"、清晰简洁;
- 每次提交后运行
git status确认成功;提交失败时,未经要求不得自行绕过问题; - 未经用户明确要求,绝不 push 到远端。
2.8 Examples 与 Final Reminder
文末用一组 <example> 示范"极简输出"的底线标准("1 + 2" → 3;"is 13 a prime number?" → true),以及三个完整工具链示范:
- 启动服务器:识别
node server.js需常驻 → 带is_background: true的run_shell_command工具调用; - 重构 auth 逻辑:先
glob+read_file确认存在tests/test_auth.py作为"安全网",再读requirements.txt确认requests是依赖,然后给出 4 步计划(替换调用 → 加try...except→ 移除旧 import → 跑 linter 与测试),完成后以ruff check src/auth.py && pytest验证,并主动询问是否写提交信息; - 写测试:先读被测文件与既有测试约定,
write_file新建someFile.test.ts,再跑项目测试命令验证; - 文件查找:
glob匹配./**/app.config后列出结果,并询问用户先读哪一个。
Final Reminder 收束全文:核心职能是"高效且安全的协助";在极致简洁与安全性/系统变更所需的清晰度之间取得平衡;始终优先用户控制权与项目约定;绝不假设文件内容,用 read_file 核实;作为 agent,持续工作直到用户的问题被完全解决。
三、请求构造:qwen_code.rs 的源码级实现
提示词只是请求的一部分。qwen_code.rs 展示了 build_request 如何把提示词、会话历史与工具 schema 拼装成最终的 Chat Completions 请求体。
3.1 请求体结构与固定参数
build_request 生成的 JSON 请求体(见 qwen_code.rs)包含:
model:model_info.slug;messages:系统提示 + 合成启动上下文 + 助手确认语 + 归一化后的历史消息;max_tokens:常量QWEN_CODE_DEFAULT_MAX_TOKENS = 8_000(L11);stream: true且stream_options.include_usage: true,保证流式响应同时返回用量统计;tools:复用super::kimi_cli::build_tools(&prompt.tools)生成的工具 schema——即 Qwen Code 的工具面与 kimi-cli harness 共用同一套构建器,这正是 docs/harness.md 中"Qwen handlers include read file, write file, edit, shell command, glob, grep, todo write, ask user question, plan exit, and agent"的落点。
build_request 还接收 _reasoning_effort、_conversation_id、_yolo_mode 三个带下划线的未使用参数,说明该 harness 不消费 reasoning effort 与 yolo 模式信号(对比 request.rs 中其他 harness 的路由分支,qwen-code 分支不挂任何 ChatHarnessPostprocess 后处理,响应流原样透传)。
3.2 合成启动上下文:日期、OS、目录与文件夹列表
Qwen Code CLI 的标志性设计是在对话开始前有一段"设置上下文"的交换。build_startup_context_message 复刻了这一结构,生成一条 role: "user" 的多部分内容消息,文本包含:
This is the Qwen Code. We are setting up the context for our chat.开场声明;- 今天的日期(
chrono::Local::now().format("%A, %B %-d, %Y"),按用户 locale 格式化); - 操作系统(
std::env::consts::OS,macOS 统一显示为darwin); - 规范化后的当前工作目录(
cwd.canonicalize(),失败时退回原路径); - 文件夹列表,最多展示 20 项。
render_folder_listing 的渲染细节:过滤掉以 . 开头的隐藏条目,目录名追加 / 后缀,按名称排序取前 20 个,并用树形前缀 ├─── / └───(最后一项)排版,整体形如:
/path/to/project/
├───src/
├───package.json
└───README.md
这条 user 消息之后紧跟一条固定的 role: "assistant" 回复 Got it. Thanks for the context!(L27-L30),完成一次完整的合成"设置交换",之后才追加真实的会话消息(由 build_qwen_messages 基于 kimi_cli::build_messages 转换)。这套结构保证模型在"第一句话"之前就已经拥有环境快照,与提示词中"Path Construction"一节要求的绝对路径习惯形成配合。
3.3 消息归一化:让历史消息适配 Qwen 侧格式
normalize_qwen_message 对每条转换后的历史消息做四类修正:
- 空 content 修复:
role: "assistant"且带tool_calls但content为空数组的消息,把content改写为空字符串——规避部分 Chat Completions 实现拒绝"空数组 content + tool_calls"组合的问题; - tool 消息 content 结构化:
role: "tool"且 content 是纯字符串的,改写成[{"type": "text", "text": ...}]内容块数组; - reasoning_content 清洗:去除推理字段尾随换行,保证多轮拼接时的稳定形态;
- tool call arguments 紧凑重排:
function.arguments从字符串解析回 JSON 对象后,对三个高频工具按固定字段顺序紧凑重序列化(ordered_qwen_arguments):
| 工具 | 固定字段顺序 |
|---|---|
read_file |
file_path, offset, limit, pages |
edit |
file_path, old_string, new_string, replace_all |
run_shell_command |
command, description, directory, is_background, timeout |
其他工具则退化为普通紧凑 JSON 序列化。固定顺序 + 紧凑格式的好处是:多轮对话中同类工具调用的 token 序列高度一致,有利于命中 prompt cache,同时让模型在历史中"看到"的参数排列与工具 schema 保持确定性。
3.4 系统提示的三段式拼装
build_system_prompt 在静态提示词之上再叠两层动态内容,形成最终 system 消息:
- 基底:
QWEN_CODE_SYSTEM_PROMPT(即第二节拆解的 md 文件,去掉尾部换行);若环境变量INTERPRETER_DISABLE_SYSTEM_IMPORT为"1",则到此为止直接返回,不再追加任何动态指令; # Additional Developer Instructions:从 prompt 输入中抽取所有role: "developer"消息的文本(InputText/OutputText项拼接),多段之间以空行分隔——这是用户级开发指令(对应仓库中的AGENTS.md一类机制)进入 Qwen Code 会话的通道;# Session Instructions:追加base_instructions.text(会话级基础指令)。
值得注意的是,request.rs 中的 harness guidance 注入(prompt_with_harness_guidance)按 docs/harness.md 的说明目前只对 kimi-cli 生效,qwen-code 不受 harness_guidance 开关影响。
四、配置、路由与验证要点汇总
把前文信息汇总成实操检查表:
| 维度 | 取值/行为 | 依据 |
|---|---|---|
| 配置项 | harness = "qwen-code"(TOML)或 -c harness='"qwen-code"' 临时覆盖 |
docs/harness.md |
| 线协议要求 | 仅 wire_api = "chat";responses/messages 组合会落入通用兼容路由或直接报错 |
routing.rs |
| 自动推断 | Qwen/QwQ/DashScope 的 provider id、名称、base URL 或模型 id 命中即默认 qwen-code |
model-provider-info/src/lib.rs |
| 请求常量 | max_tokens = 8000,stream = true,include_usage = true |
qwen_code.rs |
| 工具面 | read file、write file、edit、shell command、glob、grep、todo write、ask user question、plan exit、agent(与 kimi-cli 共用构建器) | qwen_code.rs |
| 启动上下文 | 合成 user 消息(日期/OS/cwd/≤20 项目录树)+ 助手确认语 | qwen_code.rs |
| 后处理 | 无(ChatHarnessPostprocess::None,响应流原样透传) |
request.rs |
对于 DashScope 兼容模式的 provider,一个最小可运行配置形如:
model_provider = "dashscope"
model = "qwen3-coder-plus"
harness = "qwen-code"
(provider 目录中 DashScope 兼容端点与 coding.dashscope.aliyuncs.com 等端点均携带 Qwen 系模型清单,见 provider_catalog.json。)
五、小结
qwen-code harness 展示了 Open Interpreter 用"提示词 + 消息整形"复刻外部 CLI 代理的完整范式:一份强调绝对路径、todo 跟踪、最小输出、高风险确认与 Git 纪律的系统提示词(qwen_code_prompt.md)被 include_str! 编译进二进制,运行时通过合成启动上下文注入环境快照,历史消息经四步归一化对齐 Chat Completions 语义,最终与 kimi-cli 共用的工具 schema 一起构成 8000 token 上限的流式请求。对希望自研 harness 的读者而言,这条链路(md 提示词 → build_request → 路由分支 → 工具面复用)在 harness 模块 中是一个可直接参照的模板。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00