Jev 在 Agent 循环中的决策层自动化指南

你的 agent 每轮循环里有一堆模型调用,它们不生成任何你要保留的文本,只负责选下一个 worker、判断工具调用是否安全、决定任务是否完成、评估检索文档是否相关。这些调用按 frontier 模型价格计费,增加几秒延迟,返回需要解析的字符串,还可能幻觉出字段名让流水线在凌晨三点挂掉。Jev 是 TypeSafe AI 做的 System One 模型,专门处理这类调用。你送进去状态和类型化问题,它返回类型化答案和校准概率。没有字符串,没有解析,70 到 500 毫秒,输入每百万 token 0.042 美元,输出免费。

这篇文章讲它放在 agent 哪里、怎么装、怎么量收益。重点不在概念,而在每个 fork 的代码、状态设计、路由经济学和失败模式。

图像

先数清楚 agent 循环里哪些调用不需要生成

一个通用 agent 迭代里,生成调用通常只有两处,决策有十一处,剩下是代码规则。今天很多栈把十三处全塞给同一个 frontier 模型。

user request arrives
    [D]  is this in scope, or does it need a human
    [D]  which model tier can handle this
    [G]  plan the task                            <- LLM
  loop:
    [D]  which worker acts next
    [C]  have we exceeded the action limit
    [D]  rebuild the available action menu, pick one
    [G]  generate the arguments if text is needed  <- small LLM
    [D]  is this tool call safe to execute
    ---- tool executes ----
    [D]  score the output: keep it, summarise it, drop it
    [D]  did that move us forward, or are we stuck
    [D]  is the goal satisfied
    [C]  has the spending cap been hit
  end loop
    [D]  did the work actually happen, or does the model just think so
    [D]  publish, or hold for approval

两条硬规则。你的规划模型、写作模型、编码模型都保留。这里做的是从它们身上减掉一类工作。Jev 不能生成,所以它不能成为 agent。它只能成为 agent 里做选择的部分。

图像

三个原语怎么放进循环

每个请求都是状态加一组命名问题。类型可以在同一请求里混合。Choice 返回获胜 key、每个选项概率和置信度,Score 返回数值分数、分布和置信度,Noul 返回 0 到 1 的概率。

类型 循环角色 返回
Choice 分派、路由、动作选择,最多 255 个选项 获胜 key、每选项概率、置信度
Score 相关性、紧急度、风险、进度,2 到 10 个 rubric 级别 数值分数、分布、置信度
Noul 门控和守卫,一个是/否陈述 [0, 1] 概率

代码拥有阈值。Jev 报告信念和确定性。把信念转成动作是业务逻辑,这个切分让系统以后可审计。

Score 有三个 rubric 级别时返回 0 到 2,包括小数。Noul 接近 0.5 表示模型认为状态没有把两种情况分开。自动化流水线里这个信号比答案更值钱,因为它是你的升级触发条件。

当前模型是 jev-1.13.0 / jev-latest。上下文 64k 总量,32k 给状态加最长单个问题。只支持文本输入。端点是 POST https://api.typesafe.ai/v1/systemone,SDK 有 Python 的 typesafe-sdk 和 JS/TS 的 @typesafe-ai/sdk,都读 TYPESAFE_API_KEY。如果你不想加供应商,也可以通过 Vercel AI Gateway 和 OpenRouter 访问。

图像

十一个决策点分别怎么写

下面每个点都来自上面的循环。先从最常碰到的工具调用门控和 worker 分派开始,不用一次全改。

1 模型路由

选能完成步骤的最便宜模型。

from langchain.agents import create_agent
from langchain_typesafe.experimental.middleware import (
    ModelChoice, ModelRouterMiddleware,
)

router = ModelRouterMiddleware(
    choices={
        "fast": ModelChoice(
            model="openai:luna",
            criteria="Direct lookups, extraction, localized changes.",
        ),
        "powerful": ModelChoice(
            model="openai:sol",
            criteria="Architecture and high-stakes decisions.",
        ),
    },
    instructions="Choose the least costly model that can complete the task.",
)

agent = create_agent("openai:gpt-5.6-luna", middleware=[router])

路由是经济学最不直观的 fork。后面会解释为什么它失败两年,以及不进入上下文的决策模型怎么改变算术。

2 工具调用门控

每个值得信任的 coding agent 都会在运行前分类危险动作。这个步骤以前在闭源里。现在是一行 middleware。

from langchain_typesafe.experimental.middleware import AutoModeMiddleware

guardrail = AutoModeMiddleware(tools=["bash"])
agent = create_agent("openai:gpt-5.6-luna", middleware=[guardrail])

自己写的话,JS 版本是这样。

import { TypeSafe } from "@typesafe-ai/sdk";
const jev = new TypeSafe();

const { answers } = await jev.systemOne({
  model: "jev-latest",
  state: `Agent is about to run: ${command}\nWorking directory: ${cwd}\nRecent actions: ${history}`,
  questions: {
    destructive: {
      type: "noul",
      instructions: "Is this destructive or irreversible?",
    },
    action: {
      type: "choice",
      instructions: "Gate this command.",
      criteria: {
        allow:   "safe, run it",
        confirm: "ask the human first",
        block:   "never run",
      },
    },
  },
});

if (answers.action.choice === "block") throw new Error("blocked by policy");
if (answers.action.choice === "confirm" || answers.destructive.noul > 0.4) {
  await askHuman(command);
}

两个问题,一次往返,大约 100 毫秒,安全路径上零生成 token。

如果做得到,别只读命令字符串。执行前把文件内容读出来放进状态,能抓住一类文件名永远抓不住的问题。

图像

3 上下文压缩作为相关性过滤

今天的压缩通常是摘要 prompt。这很奇怪,因为摘要是一般压缩,一般压缩很难。查询感知压缩容易得多。知道自己在找什么,决定丢什么就简单。

所以给 chunk 打分,不要重写它们。

questions = {
    f"chunk_{i}": Score(
        instructions="How relevant is this to the current goal?",
        criteria=[
            "Unrelated to the goal, safe to drop",
            "Background only, a one-line summary is enough",
            "Directly needed, keep it in full",
        ],
    )
    for i in range(len(chunks))
}

result = client.system_one(
    state={"goal": current_goal, "chunks": chunks},
    questions=questions,
)

kept = [c for i, c in enumerate(chunks)
        if result.scores[f"chunk_{i}"].score >= 1.5]

给每个工具调用输入、工具调用输出、内部推理块打分,丢掉不达标的。没有内容被重写,也就没有内容因为糟糕改写而丢失。

生产环境里测过,一秒把一个 Claude session 从接近 1M token 压到 86K。

图像

更深的版本把二元保留换成每个 chunk 的显示策略,不显示、短摘要、长摘要、全文。到这一步,上下文不再是静态日志,而是依赖查询的视图。

4 卡住检测

Agent 会在从内部看起来很有产出的循环里烧预算。

result = client.system_one(
    state={
        "goal": goal,
        "last_5_actions": recent_actions,
        "last_5_observations": recent_observations,
    },
    questions={
        "progressing": Noul(
            instructions="The last five actions moved measurably closer to the goal.",
        ),
        "repeating": Noul(
            instructions="The agent is repeating an action that already failed.",
        ),
    },
)

if result.nouls["repeating"] > 0.7 or result.nouls["progressing"] < 0.3:
    escalate()

每 N 轮跑一次。它几乎不花钱,是防 overnight run 把全部预算花在绕圈上的最便宜保险。

5 下一个 worker 分派

经典编排 fork。

from typesafe_sdk import Choice, TypeSafeClient

with TypeSafeClient(model="jev-1.13.0") as client:
    result = client.system_one(
        state={
            "goal": goal,
            "completed_work": notes,
            "available_workers": available_now,
            "constraint": "Save drafts for review. Do not publish.",
        },
        questions={
            "next_worker": Choice(
                instructions="Choose the next step for a research briefing.",
                criteria={
                    "research": "Collect evidence still needed for the goal.",
                    "write":    "Draft the briefing from sufficient evidence.",
                    "review":   "Goal unclear, outside scope, or work complete.",
                },
            )
        },
    )

answer = result.choices["next_worker"]
destination = "review"
if answer.choice in {"research", "write"} and answer.confidence >= 0.85:
    destination = answer.choice

看默认值。review 是不确定性去的地方,要覆盖它必须有自信答案。方向不是偶然。自动化里你能恢复的失败是停得太频繁。

0.85 是占位符。拿你自己流量里的标注样本调。置信度不是准确率百分比。它是校准的确定性信号,你要凭经验设阈值。

图像

6 从实时菜单选择动作

这是从 Browser Use 最值得偷的想法。

浏览器的可用动作每次点击后都会变。与其一次性描述固定动作空间,他们的 agent 会构建当前能观察到的控件列表,让 Jev 从这个列表里选。只有字段需要输入文本时,小 LLM 才跑。

把这一点用到你自己的 dispatcher。任何工具改变状态后刷新选项。否则决策模型从昨天的菜单里选,最自信的答案也没用,因为选中的选项已经不存在。

# wrong: the menu was built at startup
criteria = {w.name: w.description for w in ALL_WORKERS}

# right: the menu is built from what exists and is free right now
criteria = {
    w.name: w.description
    for w in ALL_WORKERS
    if w.is_available() and w.can_handle(current_state)
}
图像

候选集很大时,先在代码里过滤明显不匹配的,给幸存者 Score,再在短名单里 Choice。Choice 支持最多 255 个选项,这个两阶段模式是 TypeSafe 处理高基数问题的方式。

7 完成检查

一个自信答案不能证明文件已保存或消息已发送。这句话应该打印在每一个发布 overnight 自动化的人墙上。把两个检查分开。

# Jev decides the work looks done
done = client.system_one(
    state={"goal": goal, "artifacts": artifact_list},
    questions={
        "complete": Noul(
            instructions="Every deliverable named in the goal now exists.",
        ),
    },
)

# then code proves it independently
if done.nouls["complete"] > 0.8:
    assert draft_path.exists(), "model believes it saved a draft, filesystem disagrees"
    assert draft_path.stat().st_size > 500

Browser Use 就是这么做的。Jev 选择 DONE 后,另一个检查验证结果。借走这个分离。决定任务完成的东西,不应该同时是唯一确认任务完成的东西。

8 升级到人类

这个 fork 决定你的自动化是否可信。

result = client.system_one(
    state={"action": proposed_action, "context": context},
    questions={
        "reversible":     Noul(instructions="This action can be undone without cost."),
        "touches_money":  Noul(instructions="This action moves money or changes billing."),
        "external_reach": Noul(instructions="This action is visible outside the organisation."),
        "risk": Score(
            instructions="Blast radius if this is wrong.",
            criteria=["Local and trivial", "Recoverable with effort", "Irreversible or public"],
        ),
    },
)

四个问题,一次调用,策略在代码里,不在 prompt 的 vibe 里。一个有用的规则是,不可逆、花钱、外部可见的事情无论置信度多高都给人。其他事情按不确定性升级。

9 检索作为决策

见后面的检索部分。多数人接受点积作为意义的代理,这是循环里最容易停止这么做的地方。

10 对 trace 做在线评估

在完成的 run 上跑 judge,把结果喂回路由。

const result = await client.systemOne({
  state: { goal, trace, final_output: output },
  questions: {
    satisfied: {
      type: "noul",
      instructions: "The final output satisfies the original goal.",
    },
    efficiency: {
      type: "score",
      instructions: "How efficiently was the goal reached?",
      criteria: [
        "Heavily wasteful",
        "Some wasted steps",
        "Direct and minimal",
      ],
    },
    failure_mode: {
      type: "choice",
      instructions: "If the run underperformed, what went wrong?",
      criteria: {
        none: "Run was fine.",
        wrong_tool: "Picked the wrong tool or worker.",
        stuck: "Repeated a failing action.",
        premature: "Stopped before the goal was met.",
        overreach: "Did work outside the goal.",
      },
    },
  },
});

按这个价格,你可以判断每个 run,不用采样。路由阈值不再靠猜。

11 流水线中的分类

工单、邮件、文档、日志行,任何需要分支的输入流。形状总是一样。条目是状态,目的地是 criteria。

生产参考点。500 封邮件几秒分类,3.5 美分。1,018 篇研究论文分到 24 个主题,总共 0.08 美元,每篇中位 256 毫秒,DeepSeek V4 Flash 先生成摘要。一个欺诈流水线 1.42 秒分拣 100 封邮件,把不确定尾部交给 Kimi K3,100 封里 96 封正确,大约 7 美分。

最后一个案例是多数生产分类该有的形状。便宜模型做决定,贵模型处理尾部,升级阈值是你调出来的数字,不是希望。

路由为什么需要不进入上下文的模型

路由看起来最该用便宜决策模型,但它在两年里经常失败。原因是把大模型换出再换回会触发 KV 缓存重建,成本藏在定价页外。

两个模型。Opus 每百万输入 5 美元,每百万输出 25 美元。Sonnet 每百万输入 3 美元,每百万输出 15 美元。

计划是把简单部分送给 Sonnet,把困难部分留给 Opus。

设 X 为百万上下文 token,Y 为百万生成输出 token,Z 为输出内部生成的额外百万 token,比如 shell 命令和文件读取。

纯 Opus:

25 * Y   generation
 5 * Z   reading
-------
25Y + 5Z

Opus → Sonnet → Opus:

3 * X        Sonnet loads the context
15 * Y        Sonnet generates
 3 * Z        Sonnet reads
 5 * (Y + Z)  Opus reloads everything Sonnet produced
-------
3X + 20Y + 8Z

用现实拆分 X = 0.65,Y = 0.12,Z = 0.23:

(25 * 0.12 + 5 * 0.23) / (3 * 0.65 + 20 * 0.12 + 8 * 0.23)

纯 Opus 成本大约是路由路径的三分之二。

图像

向下路由再向上返回,比从不路由更贵,因为大模型重新拿回控制权时必须重读整个上下文。重建 KV 缓存是主导项,定价页上看不到。

一个从不进入对话的决策模型去掉了这一项。Jev 不加载历史,不生成 token,不留缓存要重建。决策在循环旁边发生,返回类型化值给你的代码分支。这是决策层和便宜模型之间的架构差别,也是现在路由能工作而以前不能的原因。

缓存税还压坏了另外五件事。

工具调用是一笔坏交易。工具必须提前声明在系统消息里,不管这轮是否相关。这是永久上下文成本。模型也不擅长高基数、偏离策略的工具选择。

压缩依赖一个假设。每个未来轮次都想要同一份共享状态。去掉假设,查询感知过滤每次都胜过通用压缩。

子代理表现不佳。它们的成本很大一部分花在决定传什么上下文进去、合并什么出来,不在工作本身。让这个决定变便宜,子代理就值得开。

重启存在的原因是状态被假设为有状态并最终损坏。按需加载相关旧状态是替代方案,只是以前没人负担得起。

电池被排除,因为每个内置电池都永久占用上下文。如果提示可以便宜、schema 可以按需加载,你可以用接近零成本发布数百个工具。

安装 Jev 的五个步骤

先在 Playground 测一个 fork,再装 SDK,再单独建路由器,最后接 worker。失败表放在最后。

Step 1 写代码前在 Playground 测一个 fork

打开 https://console.typesafe.ai/playground。用你自己 agent 里的真实 state 对象,不要玩具。

{
  "goal": "Compare three AI-agent tools in a morning briefing.",
  "completed_work": "No sources collected yet.",
  "available_workers": ["Researcher", "Writer"],
  "constraint": "Save drafts for review. Do not publish."
}

加上分派问题。运行。然后把 completed_work 换成真实研究笔记,再运行。看决策怎么移动,比任何文档都更能告诉你状态设计得好不好。

图像

Step 2 安装 SDK

Python 3.12 或更新。

mkdir jev-starter && cd jev-starter
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade typesafe-sdk

Windows:

mkdir jev-starter; cd jev-starter
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade typesafe-sdk

在 https://console.typesafe.ai/settings/keys 获取 key。调用会记到那个账户。

如果你用 coding agent,安装官方 skill,让它生成正确集成,不要猜。

# Claude Code
claude plugin marketplace add typesafe-ai/skills
claude plugin install typesafe@typesafe-ai

# anything else
npx skills add typesafe-ai/skills --skill typesafe-ai

这个 skill 教 agent API 和把多个问题打包进一次调用的模式。它不会把你的 coding agent 变成 Jev。

Step 3 先建独立路由器,再碰 agent

不要第一天接生产。把 dispatcher 做成独立脚本,看它决策,再连接。

import json, os
from getpass import getpass
from pathlib import Path
from uuid import uuid4
from typesafe_sdk import Choice, TypeSafeAPIError, TypeSafeClient

if not os.environ.get("TYPESAFE_API_KEY"):
    os.environ["TYPESAFE_API_KEY"] = getpass("TypeSafe API key: ").strip()

goal = input("Goal: ").strip()
if not goal:
    raise SystemExit("Enter a goal.")
notes = input("Completed work: ").strip() or "Nothing yet."
state = {"goal": goal, "completed_work": notes}

try:
    with TypeSafeClient(model="jev-1.13.0") as client:
        result = client.system_one(
            state=state,
            questions={
                "next_worker": Choice(
                    instructions="Choose the next step for a research briefing.",
                    criteria={
                        "research": "Collect evidence still needed for the goal.",
                        "write":    "Draft the briefing from sufficient evidence.",
                        "review":   "Goal unclear, outside scope, or work complete.",
                    },
                )
            },
        )
except TypeSafeAPIError as error:
    raise SystemExit(f"API error {error.status}; see step 5.")

answer = result.choices["next_worker"]
destination = "review"
if answer.choice in {"research", "write"} and answer.confidence >= 0.85:
    destination = answer.choice

folder = Path(__file__).resolve().parent / "queue" / destination
folder.mkdir(parents=True, exist_ok=True)
job = folder / f"{uuid4().hex}.json"
payload = dict(state, choice=answer.choice, confidence=answer.confidence,
               destination=destination, status="queued")
job.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
print("Saved handoff:", job)
$ .venv/bin/python chief.py
TypeSafe API key: ••••••••••
Goal: Compare three AI-agent tools for tomorrow's briefing
Completed work: No sources collected yet
Saved handoff: /Users/you/jev-starter/queue/research/a3f8....json

每次运行会把 JSON 文件丢进 queue/research、queue/write 或 queue/review。这些是本地任务队列,保存的 job 等 worker 消费。拿 backlog 里的真实目标跑二十次,读文件。你会在它花你任何钱之前发现糟糕的 criteria 文本。

图像

Step 4 接到 worker

把这段 brief 交给你的 coding agent。

Read the TypeSafe skill and inspect my worker interfaces. Connect chief.py's
JSON queues to my existing research and writing handlers. Prevent duplicate
processing. Save progress after each action. Add call and spending limits,
review on uncertainty, and a draft-exists completion check. Keep publishing
behind approval. Identify missing connectors explicitly.

Step 5 失败表

Symptom Fix
python not found 完成 Python 安装,重开终端
module not found 用同一个 .venv 解释器重跑 SDK 安装
401 替换 API key 并重跑
422 对照代码检查请求里的命名字段
429 / 529 允许 backoff,持续出现就稍后重试

SDK 会重试。API 错误在重试后仍然存在,脚本会停。

状态设计决定决策质量

决策错的时候,先看状态。模型很少是原因。

送证据,别送结论。

# useless
state = {"status": "The researcher finished."}

# useful
state = {
    "goal": goal,
    "sources_collected": [
        {"id": "s1", "title": "...", "published": "2026-09-14", "key_claim": "..."},
        {"id": "s2", "title": "...", "published": "2026-09-16", "key_claim": "..."},
    ],
    "findings": ["...", "..."],
    "gaps_remaining": ["no pricing data for tool C"],
    "actions_taken": 7,
}

第一个版本逼模型猜。第二个版本让它决定。把原始请求、进度、约束放在不同字段,模型才能区分。

图像

字段名不贡献信息。Jev 看不到你的问题 ID。把字段命名为 safe_to_publish 不提供任何指令。要求住在 instructions 和每个选项的 description 里。

# the name is for your code
"safe_to_publish": Noul(
    # this is what the model actually reads
    instructions="This content can be published externally without legal or "
                 "brand review, contains no customer data, and makes no "
                 "claims about unreleased products.",
)

用 criteria 描述选项。标签没有含义。research 没有意义,Collect evidence still needed for the goal 有意义。criteria 文本是决策所在,答案看起来不对时先改它。

批量读取同一状态的每个问题。一个请求里的问题针对同一状态并行评估。增加问题几乎不增加延迟,只增加它们的 token。你还可以跑投机分支,一次问几个可能的下一个动作,只使用实际走的分支答案。没用到的答案几乎不花钱。

result = client.system_one(
    state=state,
    questions={
        "next_worker": Choice(instructions="Choose the next step.", criteria={...}),
        "urgency": Score(
            instructions="Rate request urgency.",
            labels=["low", "medium", "high", "critical"],
        ),
        "safe_to_run": Noul(
            instructions="The requested action is safe to execute without human review.",
        ),
    },
)

一个硬限制。问题不能读彼此的答案。如果一个决策依赖新的搜索结果,先做搜索,再发第二个请求。

在买更快模型前审计工具调用。Browser Use 优化运行时把浏览器协议调用中位数从 1,092 降到 101,三个匹配对里任务中位时间下降 25%,两侧用同样模型。收益来自只读一次页面状态,不再对无关动画重新预测。Agent 延迟通常是结构问题,先看循环,再看账单。

图像

检索可以交给 Jev 做判断

小语料直接用 Jev 给每个 query-doc 对打分排序,大语料让 embeddings 召回 top k,再用 Jev 重排。

多数 agent 用 embedding 相似度检索,接受点积作为意义的代理。根据语料大小,有两种更好的安排。

小语料,Jev 就是相似度度量。完全跳过 embeddings。给每个 query-doc 对打分,按返回概率排序。

query ──┬──> doc 1  ──┐
        ├──> doc 2  ──┤
        ├──> ...    ──┼──> Jev (query, doc) -> relevant? p ──> ranked by p
        └──> doc N  ──┘

N 次调用,没有 embedding 模型,没有向量库,没有索引要保鲜,没有 chunking 策略要调。结果回来是 doc 17 p=0.97,doc 4 p=0.91,doc 22 p=0.12。

几百篇文档时,这更简单也更好,因为它能抓住和 query 不共享词汇但正好回答问题的文档。

大语料,Jev 做 reranker。

query ──> embeddings + dot product ──> top k ──> Jev (query, candidate) ──> reranked
          millions of docs                        k calls, semantic match
          cheap, approximate, recall not precision

Embeddings 做它们擅长的事,便宜的高召回候选生成。Jev 在短名单上做语义匹配,精度在这里决定,点积在这里最弱。

规则是这样。小数据,Jev 直接作为相似度度量,给每对打分,按概率排序。大数据,embeddings 拉候选集,Jev 重排。

图像

Harness 模式值得搭的几种

同样权重在不同 loop 工程下分数差很大。决策变便宜后,几种以前不经济的 harness 设计可以开。

元注意力替代压缩。针对 query 重算当前上下文有多好,构造更好的。简单形式是每 chunk 一个 Noul。丰富形式是 Score 在 don’t show、short summary、long summary、full text 之间选。上下文从日志变成视图。

便宜子代理。如果决定传什么上下文进去、合并什么出来是类型化问题,而不是模型调用,开很多并行子代理就实际可行。你会继承共享状态、写锁、同步这些有趣问题。

skills、MCP 和 tools 之间的中间地带。你想同时要三件事,短提示说明动作存在,完整 schema 按需加载,两者都不污染上下文。做到这点,你可以用接近零成本打包数百工具和数千文档。

条件 AGENTS.md。只在前端工作时加载风格指南。只在那个子目录加载坑文件。Skills 接近,但倾向于表示“现在做这个”而不是“记住这个”,加载的 skill 会在下一次压缩时被摘要掉。相关性打分的上下文没有这个失败模式。

安全感知路由。成本不是路由的唯一原因。如果子任务携带触碰不同文件类别的可能性,你可以按类别应用不同策略,让敏感工作完全避开某些供应商。

后台只读任务。好的 agent 工作流里反复出现一种模式,仪表盘并行更新,evals 后台生成,跨模型审查让一个 agent 审另一个的输出。它们都是当前 repo 状态的只读函数。为变更找相关信息是昂贵部分,如果这部分工作被每个后台任务共享,跑很多个就变得经济。

自动化成本怎么算

输入每百万 token 0.042 美元,输出免费。按一千 billed input tokens 一次决策,一万次决策 42 美分。真正要看的指标是每完成一个任务的成本。

拿十一个决策点里的保守估计,每轮循环五次决策,每个任务二十轮,每天一百个任务。

5 * 20 * 100        = 10,000 decisions/day
10,000 * 1,000 tok  = 10M input tokens/day
10M @ $0.042/MTok   = $0.42/day

同样一万次决策放到 frontier 模型,即使按便宜的一美元每百万输入 token 和短输出算,也会高两到三个数量级,每次还增加几秒而不是几毫秒。

但真正重要的指标是每个完成任务的成本。一个便宜决策把 worker 送错分支,代价远大于决策本身。Instrument completions。

参考点,每个带范围。

  • ▸
    Browser Use 7 秒找到航班,花费 0.0039 美元,对账用 90,558 个记录的 Jev 输入 token 加文本 helper 费用。浏览器基础设施不在这个数字里,时钟从第一次页面观察后开始,它找航班而不是订票。
  • ▸
    1,018 篇论文分类总花费 0.08 美元,每篇中位 256 毫秒。
  • ▸
    500 封邮件分诊 3.5 美分。
  • ▸
    一个 Claude session 从约 1M 压到 86K token,用一秒。
  • ▸
    Vercel 的 fx 团队报告安全分类比 GPT-5.6 Luna 快 5 到 18 倍,准确率也提高。这涉及分类器步骤,不是整个 agent run。
图像
图像

TypeSafe 首页的 193.6 倍更快和 444.6 倍更便宜来自他们自己的工作流评估。方法论比多数好,每个模型拿到同一工作流,不允许 harness 工程,但工作流由他们自己的模型能力团队构建,参考答案是 GPT-6 Astra 和 Fable 5.1 的平均,偏向 OpenAI 和 Anthropic 模型。TypeSafe 把这些描述为现实收益的高端。

会踩到的失败模式

类型安全保证答案形状,不保证推理完整性。下面这些坑会反复出现。

它可能很字面。它按 criteria 做,不按你的意思做。先改 criteria,再怪模型。

计数、算术、日期数学弱。放到代码里。这不是提示能解决的。

重间接和巨大噪声状态会降低表现。如果回答需要穿过状态三跳才能把问题和证据连起来,重构状态或拆分问题。

提示注入仍然有效。类型安全保证答案形状,不保证推理完整性。如果不可信内容在状态里,它可以移动判决。对不可信输入的 gate 决策保持和 LLM 一样的怀疑。

校准是分布性质。更高置信度在许多调用上相关于更高准确率。它对任何单个答案没有证明力。

只支持文本输入。还没有图像、音频、视频,如果你的 agent 靠截图驱动,这很重要。

上下文 64k,其中 32k 给状态加最长问题。大 trace 在成为状态前需要过滤,这本身也是 Jev 的工作。

图像

从哪里开始改

不要重构整个 agent。挑它最常撞到的 fork,通常是工具调用门控或下一个 worker 分派,先搬这一个。然后量三件事一周。

  1. 每个完成任务的成本,不是每次调用成本
  2. 每个完成任务的墙钟时间
  3. 升级路径触发频率,以及触发是否正确

如果三个都改善,拿下一个 fork。如果升级路径从不触发,你的阈值太松,你已经悄悄建了一个无人监督系统。

速览清单

  • ▸
    数清循环里的决策、生成、规则,把 [D] 和 [G] 分开。
  • ▸
    选一个 fork,在 Playground 用真实 state 测,不要一次搬十一个。
  • ▸
    安装 typesafe-sdk,设置 TYPESAFE_API_KEY。
  • ▸
    建独立路由器,输出到本地 JSON 队列,先观察决策。
  • ▸
    接 worker 前加调用上限、花费上限、不确定升级、草稿存在检查。
  • ▸
    批量问同一 state 的问题,问题不能读彼此答案。
  • ▸
    每周量每完成任务成本、墙钟时间、升级路径触发率和正确率。
  • ▸
    先从工具门控或 worker 分派开始。

FAQ

Jev 能替代我的 LLM 吗
不能。它不生成。它只做选择、打分、是/否判断。

一个请求能混用 Choice、Score、Noul 吗
能。类型可以在同一请求里混合。

置信度 0.85 是准确率吗
它是校准的确定性信号,不是准确率百分比。用你自己流量里的标注样本调阈值。

为什么路由到便宜模型再回大模型可能更贵
大模型重新拿回控制权时要重读整个上下文,重建 KV 缓存,成本盖过节省。

小语料检索一定要 embeddings 吗
不一定。小语料可以直接让 Jev 给每个 query-doc 对打分排序。大语料用 embeddings 召回,再让 Jev 重排。

完成检查为什么还要代码验证
模型相信任务完成不能证明文件存在或消息已发送。Jev 判断后,用文件系统或 API 独立验证。

上下文超了怎么办
当前 64k,其中 32k 给状态加最长问题。先过滤 trace,再送状态。过滤本身可以让 Jev 做。

从哪里开始
选最常撞到的 fork,通常是工具调用门控或下一个 worker 分派。先测一个,量每完成任务成本。

参考链接

  • ▸
    Docs https://docs.typesafe.ai/
  • ▸
    Quickstart https://docs.typesafe.ai/introduction/quickstart
  • ▸
    Coding agents https://docs.typesafe.ai/introduction/coding-agents
  • ▸
    Primitives https://docs.typesafe.ai/primitives/choice
  • ▸
    State https://docs.typesafe.ai/concepts/state
  • ▸
    Confidence https://docs.typesafe.ai/confidence
  • ▸
    Parallel evaluation https://docs.typesafe.ai/patterns/fan-out
  • ▸
    Skills https://github.com/typesafe-ai/skills
  • ▸
    Browser Use + Jev https://github.com/browser-use/jev-ultrafast
  • ▸
    LangChain harness guide https://langchain.com/blog/building-a-harness-with-jev

TypeSafe 相关数字为厂商报告。第三方数字来自旁边注明的构建者,本文没有独立复现。