Skip to main content

模型策略

讲解按任务性质与质量/成本目标为每个智能体分配模型与推理深度的模型策略,以及把既定值落实到实际调用的强制机制。

更新 2026-08-26 12 分钟阅读 在 GitHub 上编辑 ↗

什么是模型策略?

模型策略是一套分配规则:把"所有事都用最贵的模型"换成"这件事用这个模型、用这个深度"。它把计划、审计这类思考繁重的工作与文档化、Git 流程这类轻量工作区分开,为每个智能体声明式地规定合适的模型与推理深度(effort)。这样既能把质量尽量拉高,又能避开速率限制错误——全部发生在 Claude Code 订阅计划之内。

这套规则是代币经济学(tokenomics,代币经济)的骨架。代币经济学指权衡质量与成本来分配代币的使用方式,而 MoAI-ADK 实现其中 成本 这一轴的手段,正是这套模型策略。

信息
一句话: 选定一个策略(high/medium/low),该列的值就一次性定下当天 11 个智能体各自的模型与推理深度。挑模型的负担从十一处收敛到一处(选择策略)。

为什么不该执着于"最强模型"

乍看之下全用 Opus 最安全。但有两个问题。

第一,决定账单的不是每代币单价,而是每个任务的步数。多轮智能体会一步步推进到任务结束,步数一长,输出代币不断堆积,成本随之膨胀。深度推理模型一次能做完的事,浅层模型要返工好几遍——即使代币单价便宜,总成本反而更高。反过来,真正一次简单 pass 就能结束的工作,每次都用深度推理模型去跑,只是白白花钱。

第二,同一个模型内部也能调节推理深度。Opus 的 low effort 若比某一档的 Sonnet 得分更高、同时每任务成本更低,那么与其为省钱下调模型等级,不如在同一个模型里只调低推理深度——存在质量与成本双双占优的区间。模型策略要做的,正是找到这个区间并完成分配。

模型面板与推理深度

先把可选项摆清楚。模型策略就是在下面的阵容中挑选用哪个模型、以哪个推理深度来用的规则。

模型阵容(2026-08)

模型标识符上下文特性
Claude Fable 5claude-fable-5256K新 Mythos 级通用旗舰。最深的推理与复杂编码
Claude Opus 5 / 4.8opus1M复杂架构、高难度推理
Claude Sonnet 5sonnet200K速度与智能的平衡,日常编码
Claude Haiku 4.5claude-haiku-4-5-20251001200K最快最省,简单 · 大批量任务

MoAI 的模型策略并不使用这份阵容的全部。按 No-Haiku 策略,Haiku 不出现在智能体矩阵的任何位置,多轮智能体行全部由 Opus 承担。原因就在下一节。

推理深度(effort)

模型思考得多深,分五档选择。

effort含义
low最浅的推理。快且便宜
medium平衡。默认配置文件的基准点
high深推理
xhigh更深的推理(Opus 5 · 4.8 · Sonnet 5 · Opus 4.7 支持)
max最深的推理

ultrathink 关键字: 输入 ultrathink 会同时开启 effort:xhigh 和 Adaptive Thinking(推理代币自动分配)。不使用固定的 budget_tokens —— 模型自行分配推理深度。也可以用 /effort low|medium|high|xhigh|max|ultracode|auto 斜杠命令切换。

三档配置文件

策略从三个值里选一个开始。选定后,整列随之激活。

配置文件 (profile)CLI 标志特性
high--model-policy high质量优先。审计·顾问·协调行保持 high,撰写行停在 medium
medium(默认)--model-policy medium平衡。与 high 只在两行(builder-harness · e2e-tester)上不同
low--model-policy low每任务成本最低。多数智能体行降到 Opus medium
提示
名称对照: llm.yaml 的 profile 字段、legacy performance_tier 别名与 CLI 标志 --model-policy 用的都是 high/medium/low 三个值,1:1 对应。默认值是 medium。旧顶层档位名 max 至今仍作为 high 的只读别名处理(让既有配置继续可读),但保存时始终写入 high。无需单独迁移。performance_tier 仅在 profile 缺失时读取。

调低策略并不等于换更弱的模型等级。 在长周期智能体任务上,Opus 的 low effort 比任何 effort 的 Sonnet 得分都高,同时每任务成本更低。因此 low 策略是在 Opus 内部 靠调低推理深度来省,只在多步完赛失败不构成问题的单发行上才用 Sonnet。

各智能体分配表

下面 36 个格子就是配置矩阵(12 个智能体 × 3 个配置文件)。每个格子是解析器在调用时注入的 {model, effort} 对。编排器主会话不是被调用的智能体,因此不在表中。

Manager Agents(6 个)

智能体highmediumlow
manager-specopus / mediumopus / mediumopus / medium
manager-developopus / mediumopus / mediumopus / medium
manager-docssonnet / lowsonnet / lowsonnet / low
manager-gitsonnet / lowsonnet / lowsonnet / low
manager-designopus / highopus / highopus / medium
manager-leadopus / highopus / highopus / medium

Evaluator · Advisor · Builder · Specialist Agents(5 个)

智能体highmediumlow
plan-auditoropus / highopus / highopus / medium
sync-auditoropus / highopus / highopus / medium
super-advisoropus / highopus / highopus / high
builder-harnessopus / highopus / mediumopus / low
e2e-testeropus / mediumopus / lowsonnet / low

Built-in Agent(1 个)

智能体highmediumlow
Exploresonnet / lowsonnet / lowsonnet / low

Explore 在磁盘上没有智能体文件,无法用 frontmatter 固定 effort。矩阵改为把 sonnet / low 记作调用时的默认值,这个值原样写进调用提示。Agent Teams 静态层(静态 role profile)已在 v3.0 退役,其位置由子智能体并行执行与动态工作流补上。moai cg 的 teammate 运行时(tmux pane)保留不变。

Haiku 移除(v3.0): 原先的 Haiku 槽位(文档化 · MX 标注 · Git 流程)换成了更低的推理深度,而非更低的模型等级。成本不是靠换模型、而是靠按档分配 effort 削减的。

分配原则

  • 开销流向做判断的行: 这套策略是敲定的运营者判断,不是成本/得分推导。审计·顾问行(plan-auditor、sync-auditor、super-advisor)与协调行(manager-design、manager-lead)保持 high,而撰写·实现行(manager-spec、manager-develop)在三个配置文件中都停在 medium。
  • 所有智能体行都用 Opus: manager-spec、manager-develop、plan-auditor、sync-auditor、manager-design、manager-lead、builder-harness、e2e-tester 等多轮工作全部留在 Opus。因为 Opus 的 low 比任何 effort 的 Sonnet 得分高、每任务成本却更低。
  • Sonnet 只用于单发·以输入为主的行: manager-docs 的文档整理、manager-git 的机械性工作与 Explore 探索都是一次以输入为主的 pass 就结束,不存在多步完赛失败的问题,而在这些位置 Sonnet 更低的输入单价是决定性的。这三行在三个配置文件下都固定为 sonnet / low。
  • 没有任何行取 max: max 仍作为 high 之上唯一的级别留在词汇表中,但当前没有格子使用它。
  • xhigh 哪里都不用: 在 Opus 上得分与 high 相同,成本却多 49%。

manager-lead 现在是矩阵的一行。 此前它完全不在表里,解析成未映射智能体的 inherit 哨兵值 —— Tier L 协调者拿到的是会话碰巧在用的模型。现在它和其他保留智能体一样拥有自己的行,是注入与覆盖的对象。

制定计划的智能体不得审计自己的计划——plan-auditor 与 sync-auditor 因此与 manager-spec 分开分配。防偏差的力量不来自格子取值,而来自目录结构本身。

既定值如何传给智能体

到这里整理的是"这个智能体该用这个模型"的意图。但意图不等于执行。把矩阵定下的值落实到实际调用(spawn)的过程另有其事,而那正是模型策略的强制点。

解析器决定取值

每次调用一个智能体时,决定它使用哪个 {model, effort} 的决策器称为解析器 (resolver)。解析器按固定优先级取第一个命中的值。

  1. 若存在 llm.agent_overrides[智能体名],该值优先。
  2. 否则使用活动配置文件的智能体格(config 的 llm.profiles)。
  3. config 中没有该格,则用 Go 默认矩阵的智能体格。
  4. 矩阵之外的智能体(用户自行添加的)为 inherit —— 不注入模型,直接跟随父会话。

查看解析出的值,用只读命令 moai model profile。人读的表不带参数,机器读取加 --json。

bash
moai model profile          # 人读的表
moai model profile --json   # 机器读取用 JSON

这条命令什么也不改 —— 只是把编排器调用智能体时会传入的值原样展示。

model 与 effort 走不同的路

这里是关键。解析出的 model 与 effort 的消费路径不同。

  • model —— 是编排器调用智能体时每次给出的运行时参数,以 Agent(model: <alias>) 形式传入。智能体文件的 frontmatter 保持 model: inherit 不动,初始化 · 更新 · 保存任何阶段都不碰这个值。
  • effort —— 是智能体决定推理深度的依据,属于文档化的意图。调用智能体的工具在每次调用时不接收 effort 参数,所以 effort 只能经由 (a) 智能体文件的 effort 默认值、(b) GLM effort 覆盖层、(c) 工作流或提示层的 steering 生效。
注意
model: inherit 陷阱: 几乎所有智能体文件的 frontmatter 默认都是 model: inherit。于是编排器调用智能体时一旦漏掉 model 参数,就会悄悄回落到父会话的模型,而不是配置文件定下的模型。配置照常计算,却没有任何机制报告"没被应用"。实际观测中,带 model 参数的调用不足 1%。这一点引出下一节的漂移话题。
flowchart TD
    A["活动配置文件
high / medium / low"] --> B["解析器
计算各智能体的 model + effort"] B --> C["编排器调用智能体"] C --> D{"带上了 model 参数吗?"} D -->|"带了 — profile 值"| E["落定: 应用矩阵值"] D -->|"漏了"| F["inherit → 回归父会话模型
漂移: missing"] D -->|"明确写了别的 model"| G["声明≠解读
漂移: mismatch"] E --> H["agent-model-guard 钩子
观察 · 提示 · 选择性拦截"] F --> H G --> H H --> I[".moai/logs/agent-model-audit.jsonl"]

GLM 后端的 reasoning 上限

在 GLM 后端(moai glm,或 moai cg 的 GLM 面板)上,effort 不能照搬 Claude 的 5 级词汇。GLM-5.3 始终推理 —— 不支持关闭 reasoning,请求关闭会直接失败。调节轴只有三档 reasoning_effort(low / high / max),Claude effort 向它收拢:

Claude effortGLM reasoning_effort
lowlow
mediummax
highmax
xhighmax
maxmax
(无法识别的值)max —— 全称条款: 绝不推理不足

也就是说上限是 max: low 以上的所有 Claude effort 都收敛到 reasoning-max,无法识别的值落到 reasoning-max,没有显式覆盖的 GLM 会话默认以 reasoning-max 运行。reasoning-high 仍是有效的 wire 值,但没有任何 Claude effort 收拢到它上面。实现智能体 manager-develop 无论收拢结果如何都强制 reasoning-max(z.ai 的"编码任务用 reasoning max"建议),manager-git 在三个配置文件中都是 low effort,占据 reasoning-low 的位置。

这套映射的源头是代码而不是本页 —— 运行时 SSOT 为 internal/template/glm_effort_overlay.go。

声明与解读不一致时(漂移)

矩阵定下的值(解读)与实际调用携带的值(声明)不同,就产生漂移 (drift)。MoAI 挂了一个机械观察这道缝隙的 PreToolUse 钩子——agent-model-guard。每次调用发生时,这个钩子取出声明的 model,向解析器询问"这个智能体本该用什么模型",然后给出四种判定 (verdict) 之一。

判定含义处理
ok声明与解读一致放行
missing解读是具体别名,但调用里根本没有 model 参数提示(不拦截)—— 最常见的情形
mismatch调用声明的 model 与解读不同提示 +(选择开启后)拦截
unmapped保留目录之外的智能体(用户 harness 专家)—— 本就是 inherit,无从比较放行

三档强度

钩子以三档运行,各自独立开关。

  • observe(观察)—— 始终开启。每次调用留下一行 JSONL 记录,绝不拦截。
  • advise(提示)—— 始终开启。missing 或 mismatch 时弹出非拦截的提示消息。
  • block(拦截)—— 选择开启。只在打开 workflow.agent_model_guard.enabled(默认 false)后生效,且只拒绝 mismatch 判定。
注意
missing 不拦截。 在带 model 参数的调用不足 1% 的现实里,连 missing 也拦的话,几乎全部调用都会被拒。所以即使打开闸门,missing 仍停留在提示。拦截只作用于"明确写了另一个模型"的 mismatch。

审计记录与 fail-open

观察记录逐行累积在 <项目根>/.moai/logs/agent-model-audit.jsonl。每行包含时间 · 会话 · 智能体 · 声明的 model · 解读的 model · 判定,绝不记录提示正文。用这份日志可以统计各智能体的漂移比例。

拦截只在有确凿证据时发出(fail-open 原则)。智能体标识符可解析、解读已映射、声明的 model 存在、且两者不同——只有这些齐备才拒绝。其余所有不确定状态(解析失败、无标识符、未映射、config 读取失败、项目根无法定位)一律放行。强制机制不该因为自己的 bug 把会话卡停。

effort 不在这个钩子的范围内。 调用智能体的工具根本不暴露 effort 参数,调用时刻能观察到的只有 model。effort 是否落实,只能靠 frontmatter 与覆盖层把关。

v3.1 的强化

目前的 agent-model-guard 停留在"观察常开、拦截可选"的阶段。最常见的 missing 判定只到提示为止,意图中的配置文件被悄悄忽略的缝隙仍然存在。v3.1 正在推进把这道强制收紧的工作(SPEC-AGENT-MODEL-ENFORCE-001,进行中)。

方向是减少调用时漏掉 model 参数这件事本身 —— 强化路由,让编排器把 moai model profile --json 告知的值逐次调用如实注入;观察记录累积起来后,把漂移比例可视化。但这个 SPEC 尚在进行中,不要读成"v3.1 起会自动拦截 missing"。当前拦截仍然只针对 mismatch、且需要选择开启。

再省成本的两个 lever

模型策略决定"用哪个模型",旁边还有两个把成本再往下压的 lever。两者都从本页的 成本 视角点出,深入内容交给各自专页。

提示缓存通过前缀匹配(tools → system → messages 的顺序)复用先前请求的前段,降低输入成本。读约为基本输入的 0.1 倍,写为 1.25 倍,5 分钟没有请求(空闲 TTL)缓存即过期。因此闸门要提前绑、长会话要拆分才划算。顺带一提,这个 成本 视角的提示缓存,与上下文/内存的提示缓存讨论的"上下文保持"视角看的角度不同 —— 同一个机制,一个算账单,一个算会话连续性。

MOAI_AUTONOMY_TIER 定义各自主级别的成本与速度取舍。级别越高,越多工作无需人工介入推进,代币消耗也随之增大。级别定义详见自主级别页面。

设置方法

项目初始化时

bash
moai init my-project
# 交互式向导中包含模型策略选择

重置既有项目

bash
moai update
# 交互式提示:
# - Reset model policy? (y/n) — 重置模型策略
# - Update GLM settings? (y/n) — 配置 GLM 环境变量

用 CLI 标志直接设置

bash
moai init my-project --model-policy high    # 质量优先 (审计·顾问·协调行 high)
moai init my-project --model-policy medium  # 平衡 (默认值)
moai init my-project --model-policy low     # 每任务成本最低

--model-policy 接受 high/medium/low 三个值,结果保存在 llm.yaml。旧顶层档位名 max 作为输入仍然接受,并归一化为 high。

提示
默认策略是 medium(对应 llm.yaml profile: "medium" 与 CLI --model-policy medium,无值时按 medium 处理)。GLM 配置单独放在 settings.local.json,不会提交进 Git。只想覆盖单个智能体时,在 llm.agent_overrides 里以智能体名为键写值 —— 写入会用模型 enum 与智能体目录校验,未知名字会被拒绝。

下一步

  • 配置矩阵 —— 36 个格子的布置依据(判断加权策略)与解析器优先级细节
  • CG 模式 —— Claude 领队 + GLM 工作者的混合省钱方式
  • 自主级别 —— MOAI_AUTONOMY_TIER 的成本 · 速度取舍
  • CLI 参考 —— moai init、moai update、moai model profile 详解