第 24 章

第 24 章:Harness Engineering——把决策织进智能体骨架

第 24 章:Harness Engineering——把决策织进智能体骨架

一个 agent 之所以能自己跑下去,靠的是一圈循环里反复做出的判断:下一步做什么、调哪个工具、这个结果可不可信、该不该停、要不要叫人。把这些判断从模型的自由生成里取出来,交给决策层,agent 的骨架就变得可控、可测、可审计。本章讲决策点该插在哪、工具权限怎么用 Noul 管,以及把决策层做成 first-class 集成到底意味着什么。

Agent 循环里的决策点

先看一个通用的 agent 循环,标出该插判定的位置:

flowchart TD
    O["观察:当前状态 / 上一步结果"] --> Q1{"下一步做什么?
Choice"} Q1 --> Q2{"调哪个工具 / 哪个目标?
Choice"} Q2 --> G{"这个操作允许吗?
Noul(权限闸门)"} G -- 允许 --> ACT["执行工具"] G -- 需确认 --> HUMAN["转人工确认"] ACT --> V{"结果可信吗?
Noul"} V -- 可信 --> M["写入上下文"] V -- 不可信 --> RETRY["重试 / 丢弃"] M --> S{"该停了吗?
Noul"} S -- 继续 --> Q1 S -- 停 --> DONE["产出结果 / 结束"]

五个决策点对应五种问题:下一步动作、工具选择、操作权限、结果可信度、停止判断。它们的共同特征是——答案封闭、能被代码接住、需要被大量重复。这正是第 3 章那三个判据的落地:规则写不动、输出封闭、会被反复调用。

工具选择与权限:把"是否允许"变成 Noul

Agent 最危险的一步是"决定去执行某个操作"。把这一步的授权交给生成模型,等于让它一边生成一边自我批准。更稳的做法是把它拆成一个 Noul 权限闸门,并且硬规则优先于模型。

jev-auto-approve 给出的正是这个模式:它作为 Claude Code 的 PreToolUse 钩子,问 Jev 一个 Noul——"这条 shell 命令是不是严格只读",在 0.95 以上自动放行,否则回落到正常权限确认,从不直接拒绝;同时用一个本地 hard-no 列表和注入过滤器,把危险命令挡在进入 Jev 之前。它公布的校准里,8 条会改变状态的命令一条都没被放行。

READ_ONLY_SAFE = 0.95

def guard_command(cmd: str) -> str:
    # 硬规则先跑:明显危险的根本不进模型
    if any(pat in cmd for pat in HARD_NO):
        return "deny"
    d = client.systemone(
        state=cmd,
        questions={"read_only": {"type": "noul",
                   "question": "这条 shell 命令是不是严格只读、不会改变任何文件或系统状态?"}},
        instructions="只有确定只读才判真;任何写入、删除、网络副作用都判假。",
    )
    if d["read_only"].value and d["read_only"].probability >= READ_ONLY_SAFE:
        return "allow"
    return "ask"     # 回落到正常权限确认,绝不光凭概率直接 deny

三个设计要点值得抄:硬规则前置(危险命令连模型都不进,节省调用也避免被绕过);阈值由代码定(0.95 写在代码里,不写在提示词里);失败不越权(不确定时回落到保守的人工确认,而不是把决定权让给模型)。工具选择本身也是一次 Choice——从当前可用工具的候选集里选一个,类似于 pi-typesafe-router、decide-mcp 那样把工具路由做成类型化判定。

置信度不是权限

权限闸门有一个容易踩的误解:以为置信度够高就等于获得授权。tenuo.ai 那篇 "typed decisions, scoped authority" 把它讲清楚了——一个置信值只能授权它作用域本来就允许的动作。换句话说,概率回答的是"这个判断有多确定",不是"这个操作该不该被允许归你管"。两者必须分开:作用域(哪些动作在原理上允许、由谁授权)是代码和策略层的事,跑在模型之外;置信度只在作用域已经圈定的候选里做取舍。JevLoop 的规则正是这个原则的极端版本——高风险分数强制触发人工授权,任何概率都无法覆盖它。所以闸门的正确顺序是:先用代码划出作用域,再让模型在作用域内按概率排序;一个 0.999 的"只读"判断,也救不回一条本就落在禁用作用域里的命令。

停止条件与预算控制

Agent 最常见的两个失败模式是"停不下来"和"停太早"。前者烧钱,后者交半成品。把停止判断做成显式的决策点,并且让代码持有最终否决权。

MAX_ROUNDS, BUDGET = 12, 0.50

def should_stop(evidence: str, rounds: int, cost: float) -> bool:
    if rounds >= MAX_ROUNDS or cost >= BUDGET:
        return True                      # 硬预算由代码持有,模型无权推翻
    d = client.systemone(
        state=evidence,
        questions={"enough": {"type": "noul",
                   "question": "基于已积累的证据,是否已经足以回答最初的问题?"}},
    )
    return d["enough"].value and d["enough"].probability >= 0.8

DeepSearcher 的停止策略实验就是这个思路的公开验证:用 Jev 的 Noul 判断所累积的证据是否足以支撑停下,还是要在检索轮次预算内继续。更接近"反方向停止"的是 wakegate:在休眠中的 agent 被定时器或事件唤醒之前,Jev 对着 agent 自己的睡眠笔记回答一个 Choice(唤醒 / 还不到 / 无关),代码只在"唤醒"概率低于 0.2 时才跳过这次唤醒,同时用户消息、裸定时器、跳过上限、错误和超时一律强制唤醒;它的一次运行通过了21 个手写场景(README 自己说这是冒烟测试而非基准)。这两个例子的共同点是:模型给建议,代码下最终判断,而且这个最终判断有明确的、可审计的兜底条件。

多智能体协作中的路由

多 agent 系统里,"这条任务交给谁"天然是一个 Choice。Eliza 就是这样一个多智能体框架,集成 TypeSafe System One 决策服务做亚 100 毫秒的意图分类、动作派发和置信度门控的工具执行。更轻量的还有 hono-jev-router:它是一个 Hono 中间件,按语义而不是按方法和路径路由 HTTP 请求,判定由 Jev 完成。pi-typesafe-router 则把 Pi 的工作按类型化决策路由。它们的价值在于把"分发"这件事从 if-else 里解放出来——路由规则不再是一堆字符串匹配,而是一次带概率的判定,答案可记、可测。

详解一:AutoGPT 的一等决策块

AutoGPT 是自主智能体平台的代表项目,它集成了一等的 TypeSafe Jev 决策块,用于类型化路由、过滤、打分,以及置信度门控的下一步动作派发。

这个"一等(first-class)"是关键。当决策只是提示词里的一句话时,它不被工程看见、无法测试、不可审计;当它是节点图里的一个决策块时,它就有了输入、输出、概率和可断言的行为。AutoGPT 的选择说明:决策被当成积木,而不是被当成指令。

详解二:Pydantic AI 的 TypeSafeModel

Pydantic AI 是官方 agent 框架,它提供一等的 TypeSafeModel 集成,把 Pydantic schema 的字段映射成类型化的 Jev System One 问题,并返回带置信度的答案。

这个映射很优雅:你在 Python 里本来就用 Pydantic 类型描述数据,现在同一套类型可以直接变成"问题集"。字段名成为问题、字段的枚举成为 Choice 的选项、布尔字段成为 Noul。你不需要为决策层另学一套建模语言——你已有的类型系统就是问题定义。

详解三:mu 的 38 个决策点

如果只读一个项目来理解"Harness Engineering",建议读 mu。它是一个基于 pi 的编码 agent 和桌面应用,在循环里设置了38 个决策点,问 Jev 的 Noul、Choice、Score。这些决策点具体到令人信服:

  • 长工具输出的哪些片段该进入上下文;
  • 一条被规则标记的命令,是不是用户真的要求执行的;
  • 抓取到的网页或 MCP 结果里,是否夹带着瞄准模型的指令(prompt injection);
  • 一个"完成了"到底有没有被验证过。

而且每个点都可以设为 active / shadow / off,每条裁决都写进本地 ledger。在它仓库的重放基准里,用 Jev 做的目标感知式测试日志选择,砍掉了 40–46% 的日志而没有丢掉任何必需的行。

这个项目的意义是示范了 harness 工程的全部要素:决策点被逐点列出、逐点开关、逐点记账。 决策不是散在代码各处的临时调用,而是被显式枚举、可开关、可回放的一套基础设施。

把决策层做成 first-class 集成

"决策"能不能成为框架里语言级别的东西,决定了它好不好用。2026 年这一批集成给出了肯定答案:

eve(Vercel)的引擎把 Jev 作为默认评测模型(typesafe-ai/jev)内置在它的 evaluate 路径里;Sim 是一个构建与监控 agent 的协作工作台,原生集成 TypeSafe System One 评测与决策 provider;RubyLLM 提供了官方的 Ruby gem,用原生 System One 协议承载类型化问题、概率答案和错误归一化;jev-mcp 把十一个 Jev 判断工具(verify、screen、noul、find、rerank、classify、decide、compare、extract、review、gate)做成 MCP 服务器,配 fail-closed 处理;官方还开源了 system-one-adapter-python,作为跑在 OpenAI / Anthropic 兼容 API 之上的 drop-in 适配器;Rust 侧有类型化的 typesafe-ai 客户端。

JevLoop(zjunlp)则把"一流集成"和"代码掌握控制权"合在一起:Choice 从每一步重建的候选工具里挑下一个工具,Score 给这次调用评级风险,Noul 决定它是否需要授权,而由普通代码来执行答案——一个高风险分数会强制触发人工授权,任何概率都无法覆盖它。它的判定在离线 judge 下只占 7.7% 的墙钟时间(走托管 API 时是 79%)。

这里的信号很清楚:当决策成为一个和 generate、stream 并列的推理类型(如 neurolink 里的 decide),而不是一条特殊提示词时,agent 骨架才算真正把决策织了进去。

落到生产的清单

把上面所有东西收成一份可勾选的清单:

  • 决策点显式枚举。 像 mu 那样逐点列出,而不是散落在代码里;先支持 shadow 模式跑一段,再决定开关。
  • 阈值写进代码。 0.8、0.95 这些数字属于代码,不属于提示词。
  • 硬规则前置。 危险的、确定能判的先在模型之外处理,别让模型做它做不好的事。
  • 失败策略逐点决定。 权限闸门 fail-closed(不确定就不放行),上下文压缩、日志剪裁这类 fail-open(出错就保留全部)。别用一个默认策略套所有点。
  • 每个判定留 ledger。 记录 state、问题、概率、模型版本,方便审计、回放和漂移监控(第 23 章的回归测试就建在这上面)。
  • 预算硬上限由代码持有。 轮次、成本、超时,模型无权推翻。
  • 低置信有明确降级路径。 不是"随便猜一个",而是转人工或升级给更大的模型。

这份清单的本质,是让 agent 的每一处判断都可解释、可回滚、可监控——也就是"可推理"。

回到那句话

全书从一段几乎所有 AI 应用都写过的代码出发:让生成模型判断"这条评论是垃圾吗",再字符串匹配它的回复。我们花了二十三章,把那个判断从自由文本里剥出来,装进一个类型化的槽位,最终讲成了这本书的论点——

代码拥有控制流,模型只做语义判定。

这句话不是一句口号,它在这三章里有了具体的形状。第 22 章里,它是 Map Reduce 的分块、映射、聚合:并行和聚合的逻辑在代码里,模型只管填每一块的标签,于是 2,300 篇论文能在 83 秒、14 美分里判完。第 23 章里,它是回归门和护栏:锁版本、对概率做区间断言、监控漂移、按阈值分流,模型给概率,代码下判断,于是 97.5% 的核实准确率背后还有可复现的阈值曲线。第 24 章里,它是 agent 骨架的 38 个决策点:模型对"这条命令只读吗"给出 0.95 的把握,代码决定放行还是转人工;模型对"够了吗"给出答案,代码还持有预算和一票否决。

统一的道理始终只有一条:语义判定是模型最擅长也最该做的事,控制流是软件最擅长也最该保有的东西。 把这两者各自归位,判断就变得便宜、快速、可验证——软件没有变简单,而是变得可推理了。

这就是"一个特别聪明的 switch 语句"真正值钱的地方。

小结

  • Agent 循环里至少有五个该插判定的位置:下一步动作、工具选择、操作权限、结果可信度、停止判断。
  • 工具权限用 Noul 闸门管理,并坚持三条纪律:硬规则前置、阈值写在代码里、不确定时回落到保守而非把决定权交给模型。
  • 停止与预算由代码持有最终否决权(DeepSearcher 的停止策略、wakegate 的 21/21 场景都体现了这一点)。
  • mu 的 38 个决策点示范了 harness 工程的全部要素:逐点枚举、active/shadow/off 开关、逐点记 ledger。
  • first-class 集成意味着决策成为 generate/stream 并列的推理类型:AutoGPT 的决策块、Pydantic AI 的 TypeSafeModel、eve 的默认评测模型、jev-mcp 与官方 system-one-adapter-python。
  • 从生产清单回到全书论点:代码拥有控制流,模型只做语义判定——判断变便宜、变快、可验证,软件因此变得可推理。

📑 Jev 实战:用类型化决策重构软件

1 第 1 章:为什么需要决策层——从"生成一切"到"只做判定" 2 第 2 章:三种类型化输出——Choice、Score、Noul 与调用契约 3 第 3 章:十个决策形态——什么时候该把判断交给 Jev 4 第 4 章:Classification 与 Routing——把分诊做成一等公民 5 第 5 章:Detection 与 Scoring——二元判断与有序评分 6 第 6 章:Search 与 Retrieval——在候选集里找相关 7 第 7 章:Ranking 与 Verification——排序与校验 8 第 8 章:ML Feature Extraction 与 Structured Data Extraction——把文本变特征与结构化数据 9 第 9 章:检索与知识图谱——Search and retrieval / Graphs and knowledge graphs 10 第 10 章:模型路由与 LLM 护栏——Model routing / LLM guardrails 11 第 11 章:语义代码检查——Semantic code linting 12 第 12 章:特征提取与需求预测——Feature extraction / Demand forecasting 13 第 13 章:招聘与线索生成——Recruiting / Lead generation 14 第 14 章:客户支持——Customer support 15 第 15 章:理赔、金融犯罪与风险评估——Insurance claims / Financial crime / Risk assessment 16 第 16 章:法律与合规——Legal and compliance 17 第 17 章:电商市场与广告——E-commerce marketplaces / Advertising 18 第 18 章:内容审核与信任安全——Moderation and trust and safety 19 第 19 章:游戏——Gaming 20 第 20 章:实时应用——150 毫秒预算 21 第 21 章:科学发现——Scientific discovery 22 第 22 章:大数据上的 AI Map Reduce——为什么便宜 100 倍 23 第 23 章:通用验证——Universal Verification 24 第 24 章:Harness Engineering——把决策织进智能体骨架
← 返回本书大纲