Skip to content

功能规格说明:视觉子代理 ​

创建日期:2026-08-12

背景:DeepSeek 等主模型速度快、价格低,但不支持图像识别;支持视觉的模型速度慢、价格贵。设置 WAVE_VISION_MODEL 环境变量后,系统内置一个 vision 子代理,主模型可继续使用非视觉快速模型,把图片识别委托给视觉模型。 社区调研结论:Claude Code 提供 CLAUDE_CODE_SUBAGENT_MODEL 全局子代理模型覆盖,但无内置视觉子代理、无自动触发,需用户自写;Codex 对非视觉模型直接丢弃图片(占位文本);OpenCode 无非视觉 fallback。Wave 的「环境变量 + 内置 vision 子代理」方案为社区首创。 触发机制:主模型自行决定(不做自动注入)。主模型收到占位符 + [Image source: <path>] 路径元数据 + Agent 工具列表中的 vision 子代理描述后,自行判断是否用 Agent 工具委托。

用户场景与测试 (必填) ​

用户故事:WAVE_VISION_MODEL 环境变量启用内置 vision 子代理(优先级:P1) ​

作为用户,我希望设置 WAVE_VISION_MODEL 环境变量后,系统自动内置一个使用该模型的 vision 子代理,以便无需手写子代理文件即可把图像识别委托给视觉模型。

为什么是这个优先级:这是功能核心——环境变量是唯一开关,内置子代理免去用户配置成本。子代理通过现有加载机制(builtin/subagents/ 目录扫描)注册,模型通过 frontmatter 特殊值 model: visionModel 解析为该环境变量,与现有 model: fastModel 机制对称。

独立测试:设置 WAVE_VISION_MODEL 后加载子代理配置,断言出现名为 vision 且 model 等于该环境变量的配置;未设置时断言不出现 vision 配置。可通过 loadSubagentConfigurations 单测覆盖。

验收场景:

  1. 假设 环境变量 WAVE_VISION_MODEL 已设置(如 qwen-vl-max),当 系统加载内置子代理配置时,则 出现名为 vision 的子代理,且其解析后的模型为该环境变量的值
  2. 假设 环境变量 WAVE_VISION_MODEL 未设置,当 系统加载内置子代理配置时,则 不出现 vision 子代理(避免主模型委托一个解析到非视觉模型的子代理)
  3. 假设 内置 vision 子代理已加载,当 主代理查看可用子代理列表时,则 该子代理出现在 Agent 工具的描述中,主代理可发现并调用

用户故事:非视觉主模型委托图像识别(优先级:P1) ​

作为用户,我希望主模型(如 DeepSeek)收到图片时能看到图片路径和 vision 子代理的存在,并自行决定委托它描述图片,以便我继续使用快速文本模型处理其余任务。

为什么是这个优先级:这是用户痛点的直接解法——主模型收到图片时,非视觉分支目前仅替换为占位符、不带路径元数据,主模型无从委托。需要让非视觉分支也附加 [Image source: <path>],主模型才能把路径传给 vision 子代理。委托后图片以 base64 图像块形式到达视觉模型(vision 子代理用 Read 工具读取路径即可获得图像块,无需新增图片转发机制)。

独立测试:构造主模型 supportsVision=false + 消息含图片路径的场景,断言转换后的 API 消息同时包含占位符文本与 [Image source: <path>] 文本;构造 vision 子代理调用场景,断言子代理可通过 Read 工具读取路径并获得包含 base64 图像块的 ToolResult。可通过 convertMessagesForAPI 与 readTool 单测覆盖。

验收场景:

  1. 假设 主模型不支持视觉(如 DeepSeek),当 用户消息包含图片且转换 API 消息时,则 图片被替换为占位符文本,同时附加 [Image source: <路径>] 元数据文本,主模型可知晓图片来源路径
  2. 假设 主模型决定委托,当 它调用 Agent 工具(subagent_type: "vision",prompt 包含图片路径)时,则 vision 子代理以 WAVE_VISION_MODEL 指定的模型运行
  3. 假设 vision 子代理运行,当 它用 Read 工具读取图片路径时,则 返回包含 base64 图像块的 ToolResult,视觉模型可看到真实图片内容并返回文字描述
  4. 假设 vision 子代理返回描述文本,当 主模型继续处理时,则 主模型基于该描述回答用户,无需自身具备视觉能力

用户故事:视觉模型不受影响(优先级:P2) ​

作为用户,我希望主模型本身支持视觉时,图片仍按原有方式直接发送,不受 WAVE_VISION_MODEL 影响。

为什么是这个优先级:保证现有视觉主模型用户零回归——环境变量只增加委托能力,不改变直接发送路径。

独立测试:构造主模型 supportsVision=true 场景,断言图片仍以 image_url 块发送,不附加委托相关逻辑。可通过 convertMessagesForAPI 单测覆盖。

验收场景:

  1. 假设 主模型支持视觉且 WAVE_VISION_MODEL 已设置,当 用户消息包含图片时,则 图片仍以 image_url 块直接发送给主模型
  2. 假设 主模型支持视觉,当 消息包含本地路径图片时,则 仍附加 [Image source: <路径>] 元数据(与 PR #1718 行为一致)

边界情况 ​

  • WAVE_VISION_MODEL 设置为不存在的模型或未配置的模型时会怎样? 子代理按现有模型解析逻辑处理,模型不可用时报错,与用户自写子代理配置无效模型行为一致。
  • 用户消息包含多张图片时会怎样? 每条图片路径均附加 [Image source: <路径>],主模型可把多个路径一并传给 vision 子代理。
  • 图片为 dataURL(webview 粘贴)时会怎样? 遵循 PR #1718:CLI 先落盘为临时文件,再附加落盘路径的元数据;无法落盘时不附加路径(主模型无法委托该图)。
  • vision 子代理被用户自定义同名子代理覆盖时会怎样? 按现有子代理合并优先级(project > user > builtin),用户自定义配置优先,WAVE_VISION_MODEL 不强制覆盖。
  • 主模型支持视觉但用户仍想用 vision 子代理时会怎样? 可直接用 Agent 工具显式调用,与普通子代理一致。
  • 图片文件在委托前被删除或不可读时会怎样? vision 子代理的 Read 工具返回错误,主模型收到错误后可提示用户或跳过该图。