Sidecar:Web Search 与 Vision
不同路由模型对托管 Web Search 和原生图像输入的支持并不相同。opencodex 通过两个
sidecar 补齐这些能力;它们可以使用 ChatGPT 登录(forward)provider,也可以使用已存储的
Anthropic OAuth provider;web search 还可通过显式 xai 后端使用已存储的 Grok OAuth。Sidecar 错误会转换成长度受限的工具结果或图像提示,不会让整个 turn
失败。
Web-search sidecar
Section titled “Web-search sidecar”当 Codex 为非透传的路由模型请求托管 web_search 时,opencodex 会:
- 移除托管的
web_search工具,改为向路由模型提供一个合成的web_search(query)function 工具。原托管工具的选项会保留并用于 sidecar 调用。 - 让路由模型在一个小型 agentic 循环中运行。模型调用
web_search时,opencodex 使用所选 后端:OpenAI 默认以gpt-5.6-luna运行托管web_search;Anthropic 默认以claude-sonnet-5运行web_search_20250305。xAI 默认以grok-4.6运行托管web_search, 并在xSearch.enabled为 true 时把x_search加入同一请求。Streaming 答案及引用会解析为工具结果。 - 循环直到模型回答,或真实查询总数达到
maxSearchesPerTurn(默认 3)。达到上限后会移除 search 工具并强制生成最终答案。如果模型调用apply_patch或 shell 等真实客户端工具,当前 turn 会结束,以便这些调用到达 Codex。
路由模型的每次迭代都会向上游请求 stream: true,但 opencodex 会在决定搜索还是返回最终答案前,
在内部完整缓冲所有语义 event。只有第一次迭代的最终 header/status 和 429 key rotation 会被提前
取得。因此,合成搜索调用和中间输出不会作为模型输出暴露给客户端。
注入结果会包裹在不可信数据边界中,限制长度,并按来源 URL 去重。在结构化输出 turn
(json_schema / json_object)中,结果会以紧凑 JSON 而不是普通文本传入。若路由模型是纯文本
模型,search 模型还会收到指令,用文字描述相关图像并附上来源 URL。
{ "webSearchSidecar": { "enabled": true, "backend": "anthropic", "model": "claude-sonnet-5", "reasoning": "low", "maxSearchesPerTurn": 3, "routedModelStallTimeoutMs": 200000, "timeoutMs": 200000 }}托管后端不允许在 minimal reasoning 下使用工具,因此默认值为 low。搜索失败时,路由模型会
收到长度受限的错误结果,仍可依据已有上下文继续回答。
此路径采用四个相互独立的时钟。stallTimeoutSec 是基础 bridge event-stall 预算。
connectTimeoutMs(默认 200000)只限制 DNS/TCP/TLS 和最终响应 header。仅可在配置文件中
设置的 webSearchSidecar.routedModelStallTimeoutMs(默认 200000,整数
1..2147483647)限制每次路由模型迭代中原始响应 byte 连续无活动的时间,并在收到每个非空 byte
时重置。webSearchSidecar.timeoutMs 独立限制单次托管搜索请求。实际 bridge watchdog 为
max(基础 stall, connect timeout, 路由模型 stall, sidecar timeout) + 30 秒。路由模型 stall
不是总生成 timeout。SSE 开始前的失败会返回非 2xx JSON;响应 header 开始后发生的生成失败则以
response.failed SSE 传递。
Vision sidecar
Section titled “Vision sidecar”当路由模型列在其 provider 的 noVisionModels 中,或该模型在 modelInputModalities 中被声明为仅文本,
并且请求包含图像时,只要有可用的 vision sidecar plan,opencodex 就会在主调用之前描述每张图像并用文字替换图像。
如果没有可用 plan,原始图像会被移除,而不会继续转发给纯文本后端。模型目录会为每个由 sidecar 覆盖的模型声明图像输入。
只有当每个 combo 成员都能原生或通过 sidecar 接受图像、且 combo 的 imageInput 设置未禁用时,combo 才会声明图像输入;
这样 Codex 应用等客户端会允许附件,而不会在 sidecar 运行前阻止它们。当 visionSidecar.model 缺失或为空时,OpenAI 执行路径、
Dashboard 和管理 API 都使用 gpt-5.4-mini 作为回退。启动时仍会把明确保存的旧
gpt-5.4-mini 值迁移到 gpt-5.6-luna;该迁移只作用于已保存值,不适用于缺失的 model 字段。
- 图像可以来自 user、developer 和 tool-result message,也包括 Codex 的
view_image结果。 - OpenAI 路径(ChatGPT 登录透传)会通过 Responses 端点把每张图像发送给配置的视觉模型,并携带所选
的
reasoning.effort(默认为low),描述结果就地替换图像部分。Anthropic 路径走 Messages 端点并使用自己的思考预算映射,会忽略这个 OpenAI 专用设置。 - 对于具有可靠能力元数据的原生模型,不支持的推理等级会归一化到不高于请求值的最高支持档位;如果 不存在这样的档位,则使用最低支持档位。对于缺少可靠能力元数据的未知模型或自定义模型,保持宽松处理。
- 描述任务最多同时处理 3 张图像,并保持输入顺序。发送给描述模型的用户上下文最多 800 个字符,
每张图像注入的描述最多 2,000 个字符。请求不会发送 ChatGPT 后端不支持的
max_output_tokens。 - 图像 URL 会在转发前校验。data URL 必须是
png/jpeg/jpg/webp/gif,base64 数据限制在约 20 MB;只接受data:和https:scheme。远程https图像由 OpenAI 后端获取, 而不是代理。 noVisionModels匹配会忽略 Ollama 风格的:size后缀,因此一个gpt-oss条目也能覆盖gpt-oss:120b。- 如果描述失败,模型会收到简短的处理错误提示。(如果没有可用的 sidecar plan,则不会尝试描述, 原始图像会按上文所述被移除。)
maxDescriptionsPerTurn(默认 8)限制每个主模型 turn 的新增描述次数。缓存命中和同一 turn 的重复请求不会消耗配额。成功的data:图像描述会按后端、模型、detail、图像字节和消息上下文 缓存;OpenAI 的缓存键还会额外包含推理强度(Anthropic 键不含,因为该字段在那里被忽略)。 内容可变的https:图像不会缓存。
{ "visionSidecar": { "enabled": true, "backend": "openai", "model": "gpt-5.6-luna", "reasoning": "medium", "maxDescriptionsPerTurn": 8, "timeoutMs": 45000 }}纯文本模型按 provider 标记:
{ "providers": { "ollama-cloud": { "baseUrl": "https://ollama.com/v1", "noVisionModels": ["glm-5.2", "gpt-oss", "qwen3-coder", "deepseek-v4-pro"] } }}仪表盘设置与禁用
Section titled “仪表盘设置与禁用”仪表盘的视觉附属服务卡片可以启用或停用 sidecar,并设置 maxDescriptionsPerTurn 和
timeoutMs,同时保留已有的模型、后端和推理强度控件。停用不会删除这些设置;重新启用后仍会保留原来的模型、后端、推理强度、超时和次数上限。
PUT /api/sidecar-settings 接受相同字段。部分更新会保留未提交的键。timeoutMs 使用运行时整数边界(1–2147483647 毫秒)。
如果更想直接改文件,仍可在 config.json 中把 enabled 设为 false。Anthropic OAuth 搜索和图像描述沿用现有 Claude Code OAuth fingerprint 先例,但仍应使用目标账户和实际负载充分 soak test。所有字段见
配置参考。

