你要找的可能是另一篇。 这里讲的是 Strict 模式下 copilot 拿去用的 模型。如果你想知道怎么在 Codex / Claude Code / Cursor 里面使用 copilot, 那是宿主端,看
hosts/。
名字 作为宿主(copilot 跑在它里面) 作为后端(它被 copilot 拉起) Claude Code ✅ /imreview→hosts/claude-code.md✅ STRICT_BACKEND=claude-codeCodex ✅ $imreview→hosts/codex.md✅ STRICT_BACKEND=codexCursor ✅ /imreview→hosts/cursor.md✅ STRICT_BACKEND=cursorDeepSeek(dsh) ✗ ✅ STRICT_BACKEND=deepseekZCode(GLM) ✗ ✅ STRICT_BACKEND=zcodeapi(Anthropic/OpenAI 兼容) ✗ ✅ 默认 一句话判据:宿主提供模型给你用;后端是 copilot 拿去用的模型。 宿主端不需要 API Key,后端端要么要 Key、要么要订阅登录。
Strict 模式跑完整执行主脊,每一次模型调用原本都走 llm.py::LLM——一个需要
ANTHROPIC_API_KEY 或 OPENAI_API_KEY 的原始 completions 客户端。只有编码
Agent 订阅(Claude Pro/Max、ChatGPT、Cursor)而没有裸 API Key 的用户,根本
跑不了 Strict。
但 Claude Code、Codex CLI、cursor-agent 在订阅认证下不暴露 completions
接口——它们是自带工具循环的 agent harness。所以接入点不可能是
LLM.create()(无状态的 system+messages+tools → tool_use 往返),只能上移
一层:委托一整个 agent step。
于是有了两种 provider kind:
| kind | 是什么 | 谁拥有工具循环 | 接入点 |
|---|---|---|---|
api |
原始 Anthropic/OpenAI 兼容端点 | 我们的 agent_loop |
LLM.create() |
harness |
订阅制(或 SDK 制)厂商 agent | 厂商的 | run_session()——一整个 step |
两者住在同一张注册表 providers/registry.py 里,走同一条解析路径、同一套
trace 词汇。用 api 时行为逐字节不变(平价棘轮)。
| id | kind | 凭据 | 能力 | 验证程度 |
|---|---|---|---|---|
api |
api | .env 里的 Key |
完整——我们自己的工具循环 | 基线路径 |
cursor |
harness | 订阅(cursor-agent CLI) |
mcp_tools usage_reporting |
已实测 |
claude-code |
harness | 订阅(claude CLI) |
mcp_tools builtin_tools_off max_turns system_prompt usage_reporting cost_reporting |
订阅认证下实测 |
codex |
harness | 订阅(codex CLI) |
mcp_tools sandbox_read_only usage_reporting |
仅离线测试(开发机无 ChatGPT 登录,readiness 会报出登录缺口) |
deepseek(dsh) |
harness | API Key | sandbox_read_only system_prompt api_keyed——注意没有 mcp_tools,见下 |
已实测 |
zcode |
harness | 订阅(zcode CLI,Z.AI OAuth) |
mcp_tools builtin_tools_off usage_reporting——模型按次钉死并校验,见下 |
2026-10-01 实测(zcode 0.16.9) |
claude-code 的能力集最全;codex 与 deepseek 靠 OS 级只读沙箱而不是关闭
内置工具;cursor 两者都做不到,因此额外配了事后审计(见 §5)。
deepseek 是个例外,有两处打破常规,都要记住:
-
它是 harness,却需要 API Key。 通过 Python SDK 驱动(PATH 上没有二进制, 运行时随 wheel 发布),凭据是
DEEPSEEK_HARNESS_API_KEY(缺省回退ANTHROPIC_API_KEY)。注册表用api_keyed标出这个不对称,供那些默认 "harness ⇒ 凭据在厂商那边"的调用方判断。 -
它用不了我们的工具桥——这是实测结论不是选择。它捆绑的运行时编译进了 122 个插件,
@deepseek-ai/dsh-mcp-client不在其中,所以 dsh 的 lens 跑在 harness 自带的bash+str_replace_editor上,我们的 scoped 工具(含考古工具组) 作为具名工具不可达。bash 能覆盖其中大部分(它们本就是薄薄的 git 包装), 但那些调用落在我们的审计轨迹之外,因此每个拿到桥 spec 却无法履约的会话都会 记一条capability_gap。由此而来的一条硬规矩:跑在原生 bash 上的 arm,绝不能被标成"tools bridged"。 本轮战役已经测到过三个 arm 与其标签不符。
zcode 也有两处要记住:
- 模型按次钉死,再校验实际服务的模型。 设置
STRICT_BACKEND_MODEL=GLM-5.3-Flash即可选择模型,无需修改宿主的/model。虽然 CLI 没有--model,传输层会在每次会话的 临时目录写最小个人配置,并通过ZCODE_PERSONAL_PROVIDER_CONFIG_FILE交给子进程: 模型 id 按目录拼写规范化,且带上 CLI 选择模型所需的options.reasoningLevel。ZCODE_REASONING_LEVEL=low|high|max(缺省max);ZCODE_PROVIDER_ID留空时使用宿主 配置的 provider id,再缺省为 Z.AI 个人 coding plan。宿主配置和凭据不改写,provider 规则 不复制进临时目录。模型留空时仍使用宿主缺省。会话结束后,请求模型与流里session.updated报出的modelId比对(不区分大小写),不一致时按MODEL_MISMATCH_POLICY处理(缺省fail,抛ModelMismatchError)。 - 会话 cwd 是我们自己的临时目录,不是 PR worktree。 zcode 会从 cwd 加载
.env, 并从 cwd 往上到 git 根发现zcode.json/.zcode/config.json——项目配置能声明 stdio MCP server(也就是命令),zcode 不经信任确认就会连上。在 PR checkout 里跑, 等于让被审的 PR 配置审稿人。所以仓库按绝对路径读取,prompt 里写明 checkout 位置; 工具桥写在临时目录的.zcode/config.json里。
默认用 api。 它是唯一行为完全确定、成本可测、且所有评测结论都建立其上的
后端。选别的只有三个理由:
- 你只有订阅,没有裸 Key —— 用
cursor/claude-code/codex。 - 你要按 pass 混搭模型 —— 见 §4 的
REVIEW_LENS_BACKENDS。 - 你在做后端对比实验 —— 先读 §6 的实测结果,别重复已有结论。
反过来,有一条不该选 harness 的理由值得写下来:harness 会话
不向 span 记账暴露 token(每一项都记 tok_out=0),所以它们的成本优势是
假定的,不是测出来的。metrics 会把来源记成 subscription,绝不编造 USD。
# ~/.infermatrix-copilot/.env
STRICT_BACKEND=api # api | cursor | claude-code | codex | deepseek | zcode
# STRICT_BACKEND_MODEL= # harness 内部的模型 id(可选,见下)
# STRICT_BACKEND_CONCURRENCY=2 # 并发 harness 会话数
# STRICT_BACKEND_CLI= # 二进制路径覆盖(否则走 PATH 查找)
# STRICT_BACKEND_TIMEOUT_S=1800 # 单会话墙钟上限STRICT_BACKEND_MODEL 留空时谁来定模型。 三个订阅制 CLI
(cursor/claude-code/codex)自己挑模型,留空即可。deepseek(dsh)没有内建
缺省——空模型会让每一轮以 has no provider/model 失败,所以它在 provider 注册表里
声明了 default_model: deepseek-v4-pro,由 Settings.tier_target 解析。因此留空时
run 报告的模型与实际服务的模型仍然是同一个(不会出现 target 记 ""、dsh 实跑
deepseek-v4-pro 这种贴错标签)。想换模型就显式填这一项。
显式选择,硬报错。 未知 id 在 Settings 校验阶段就被拒(会列出合法取值);
Strict 启动前 strict_readiness 先查缺项,绝不启动一个注定失败的后台任务。
没有自动探测,没有静默回退——这与 TierNotConfiguredError 是同一套哲学。
按 pass 路由(把测出来的模型互补性变成一条 arm):
REVIEW_LENS_BACKENDS=adversary=claude-code:...,round2=claude-code:...把某个评审 pass 映射到 provider:model,让那个 seat 跑在别的后端上。改之前先读
eval/dataset/results/model_comparison.md。
这是接入 harness 时最要紧的一条:厂商 agent 自带工具循环,但它拿到的工具是 我们给的。
- 工具经 MCP tool bridge 回流(
tool_bridge.py):harness 会话拿到的是 copilot 自己的 scoped 工具,每一次调用仍然经过tools.dispatch,ToolScope/PathScope检查与 trace 记录一个不少。桥比进程内循环还多两条 收紧:读取也受容纳根约束(ToolScope本身只管写;harness 是持有不可信 diff 的低信任调用方,这是防.env外泄的那道),且工具事件写独立的bridge_trace.jsonl,不与父进程的run_trace.jsonl交错。 桥提供内置工具 +doc_search/doc_read+ 按需repo_map+ 考古工具组; skill/memory 检索刻意不开放——那两个能提知识 candidate,跨进程写入口没有开。 例外:deepseek用不了这座桥(见 §2),它的调用落在审计轨迹之外。 - 能关内置工具的就关(
builtin_tools_off,claude-code;zcode 用--mode plan+--disallowed-tools剥到只剩读工具,并对照读工具白名单做事后审计); 关不掉的用 OS 级只读沙箱(sandbox_read_only,codex / deepseek)。 - 两者都做不到的(cursor-agent)额外上事后审计(
providers/audit.py): 检查文件读取是否越出会话的容纳根(PR-time worktree + run 目录),只读 scope 下是否出现了 write/edit 调用。这是侦测型而非预防型的兜底, 结论会写进 RUN_REPORT——公开声明,绝不静默。 (这套检查是从 Composer 评测臂产品化过来的,它当初真的抓到过一次越界读~/.claude/skills/...。) - 子进程环境是白名单(
providers/base.py::sanitized_env):只保留PATHHOMETERMCOLORTERMLANGUSERLOGNAMESHELLTMPDIR以及LC_*/XDG_*。厂商 CLI 必须保住自己的订阅认证(存在 HOME 状态里), 但绝不能继承我们的模型端点变量——这类机器上的ANTHROPIC_BASE_URL往往指向某个网关,继承过去会悄悄把厂商 CLI 的流量改道。API Key、 gh token、CLAUDECODE这类宿主标记也一并丢弃。
数据以
eval/dataset/results/model_comparison.md为准,它比这张表更新得勤。方法论与完整结论见GUIDE.md §8。
同一批 10 个 train item 上的后端冠军是 api/DeepSeek 核心,不是 Composer:
| 配置 | Δrecall [95% CI] | Δprecision [95% CI] |
|---|---|---|
| v17ds train(api/DeepSeek) | +.024 [−.030, +.077] | +.016 [−.061, +.093] |
| v17cb train(Composer 2.5 / cursor) | −.052 [−.165, +.061] | −.097 [−.215, +.021] |
val 一度把 Composer 排前面,那是 n=5、区间 ±.22 的小样本幻觉;train 的 item 方差紧四倍(sd .075 vs .158)。每个 CI 都跨零——结论是"测量精度内打平", 不是"更优"。
速度与成本:harness 后端快 2–4 倍(Composer 350–680s vs api 1000–2900s 每项) 且吃订阅,但如 §3 所述,成本优势未经测量。
一条安全提醒:grok 家族(4.5 / 4.6,Composer 从未出现)会在评审会话中主动
搜索并读取 copilot 自己的 imreview 方法论 skill。相关评测臂已作废并进污染
台账。跑 cursor 系评测前,三份 skill 副本必须移出 $HOME 并在事后恢复。
infermatrix-copilot doctor # 逐项 ✓/✗,失败即给出唯一修复命令
infermatrix-copilot doctor --probe # 每档模型 1-token 实探(唯一付费检查)| 症状 | 原因与修法 |
|---|---|
unknown STRICT_BACKEND 'x' |
配置校验拒绝了未知 id;合法取值已在报错里列出 |
... backend selected but no CLI found |
厂商 CLI 不在 PATH;装上,或设 STRICT_BACKEND_CLI=/path/to/cli |
| readiness 报登录缺口 | 该 harness 的订阅未登录(codex 在开发机上就是这个状态);用厂商 CLI 自己的登录命令 |
deepseek 报缺凭据 |
设 DEEPSEEK_HARNESS_API_KEY(或 ANTHROPIC_API_KEY) |
| Strict 直接返回缺项而没起任务 | 这是设计行为:strict_readiness 不会启动注定失败的后台任务 |
各后端的判定逻辑在 providers/<id>.py::auth_gap()——它只做一次廉价的状态调用,
拿不准就返回 None 让运行期大声失败,而不是猜。
- 在
providers/registry.py::PROVIDERS加一条ProviderSpec(id / kind / display / cli_names / capabilities)。 - 实现
HarnessTransport子类:run_session()(一整个 agent step)+complete()(一次性无工具调用,供HarnessLLM),可选auth_gap()。 - 在
transport_for_id()里接上。未实现的后端登记进_UNSHIPPED, 这样 readiness/doctor 会报"尚未发布"而不是运行到一半失败。 - 测试:
test_providers.py+ 对应的test_provider_<id>.py。
设计决策记录在 ../features/provider-registry.md。