Pi SDK + Jev:三段式 Agent Harness 实战指南 · 干货攻略
- 链接:https://x.com/i/article/2102762406204076532
- 分类:x-tips
- 来源:X @omarsar0
- 作者:Jay
- 更新:2026-09-29
这是什么
本篇来自 @omarsar0(elvis)的实操教程,基于 LangChain 官方博客上 Sydney Runkle 的同名文章,用 Pi SDK(TypeScript AI Agent 开发工具包)从零实现一套完整的三段式 Agent Harness,并将 Jev(TypeSafe AI 的决策模型)接入每个决策节点。
Pi SDK(github.com/earendil-works/pi)是 earendil-works 团队维护的 TypeScript Agent 工具包,MIT 协议,核心包包括:
| 包 | 作用 |
|---|---|
@earendil-works/pi-agent-core |
Agent 运行时,含工具调用和状态管理 |
@earendil-works/pi-ai |
统一多 Provider LLM API(OpenAI/Anthropic/Google 等 15+) |
@earendil-works/pi-coding-agent |
交互式 Coding Agent CLI |
Jev 是 TypeSafe AI(2026 年 9 月 15 日发布)的决策模型,定位为"System One 模型"——专注判断、不生成文本,输出结构化决策而非自然语言。Jev 版本为 jev-1.13.0(JevAdvBench 基准论文,2026-09-25 查询)。
为什么值得关注
解决什么问题
构建自定义 Agent Harness 时,核心痛点有两个:
- 决策判断贵:每次让 LLM 判断"这个工具调用安不安全"、"该用哪个模型"都要调一次完整的 Chat API,成本高、延迟大。
- Harness 逻辑散落各处:Gate/路由/验证逻辑混在 Agent 循环里,难以单独测试、难以调整阈值、难以审计。
Jev 把"判断"这件事做成一个廉价、可阈值化的原语:给状态 + 提问 → 返回带概率的结构化答案 → 代码直接做分支。不生成文本,不消耗多余 token。
三段式 Harness 是什么
教程把 Agent 循环中 Jev 插入的位置分成三个命名:
- Gate(门控):每次工具调用前,问 Jev 一个是否题,决定是否放行
- Router(路由):根据问题复杂度,问 Jev 该用哪个模型
- Verifier(验证):Agent 返回最终答案前,问 Jev 答案质量如何
核验结论
关于 Jev 的几个关键说法,交叉核验结果如下:
| 说法 | 来源 | 核验状态 |
|---|---|---|
| Jev 于 2026 年 9 月 15 日发布 | Sanity glossary | ✅ 多个来源一致 |
| Diogo Almeida 为前 OpenAI 研究员、InstructGPT 合著者 | RLCD glossary | ✅ 与公开记录一致 |
| Jev 版本 jev-1.13.0 | JevAdvBench arxiv 论文 | ✅ 学术来源 |
| RLCD 为 TypeSafe 自创方法,非行业标准 | RLCD glossary | ⚠️ 标注:厂商主张,无独立复现 |
| Jev 支持 Choice/Score/Noul 三种输出类型 | JevAdvBench 论文 | ✅ 学术来源一致 |
上手步骤
环境准备
# 安装 Node.js ≥ 18
# 创建项目
mkdir pi-jev-harness && cd pi-jev-harness
npm init -y
npm install @earendil-works/pi-agent-core
Jev 通过 TypeSafe AI API 调用(需要 API Key),文档地址 typesafe.ai/blog/introducing-system-one-models-and-jev。
第一段:Gate(工具门控)
每次工具调用前问 Jev 一个是否题,最基础的版本:
import { Agent } from "@earendil-works/pi-agent-core";
const agent = new Agent({
initialState: { systemPrompt, model, tools },
streamFn: models.streamSimple.bind(models),
});
// 在工具调用前插入 hook
agent.on("before_tool_call", async ({ toolName, toolArgs }) => {
const decision = await jev.ask({
type: "Choice",
prompt: `Should the tool "${toolName}" be allowed to run with args ${JSON.stringify(toolArgs)}? Answer yes or no.`
});
if (decision.choice === "no" && decision.confidence > 0.8) {
throw new Error(`Tool call blocked by Jev gate: ${toolName}`);
}
});
四个改进方向(对应教程四个 Gap)
教程指出了基础 Gate 的四个问题,并逐一解决:
Gap 1:阈值硬编码 → 把阈值提到 decideGate() 纯函数,形成 Policy 层:
function decideGate(jevResponse) {
// 阈值集中在一处,便于调参和测试
const threshold = 0.7;
return jevResponse.confidence >= threshold ? "allow" : "block";
}
Gap 2:所有请求用同一模型 → Router:根据复杂度动态选模型:
agent.on("before_llm_call", async ({ prompt }) => {
const complexity = await jev.ask({
type: "Choice",
options: ["simple", "moderate", "complex"],
prompt: `Rate the complexity of this request: ${prompt.slice(0, 200)}`
});
const modelMap = {
simple: "gpt-4o-mini",
moderate: "gpt-4o-mini",
complex: "gpt-4o"
};
return { model: modelMap[complexity.choice] };
});
Gap 3:Jev 不可用时无降级 → 增加 try/catch + fallback 到人工审批或拒绝:
async function safeGate(toolCall) {
try {
return await jev.ask({ ... });
} catch (err) {
return { choice: "escalate", confidence: 1.0 }; // 降级人工
}
}
Gap 4:不检查最终答案 → Verifier:在 Agent 输出前验证质量:
agent.on("before_response", async ({ response }) => {
const quality = await jev.ask({
type: "Score",
prompt: `Rate the quality of this answer: ${response}. Score from 1-5.`
});
if (quality.score < 3 && quality.confidence > 0.75) {
return { rerun: true, reason: "Low quality flagged by verifier" };
}
});
Pi SDK 的 Hook 机制
Pi 的 Agent 类在循环关键节点暴露 Hook:
| Hook | 触发时机 |
|---|---|
before_tool_call |
工具调用前(Gate) |
before_llm_call |
LLM 调用前(Router) |
after_tool_call |
工具调用后 |
before_response |
返回结果前(Verifier) |
官方内置了 permission-gate 扩展(packages/coding-agent/examples/extensions/permission-gate.ts),可直接参考。
坑与适用边界
⚠️ Jev 安全性警告(重要)
JevAdvBench 论文(arXiv:2609.31142v1,2026-09-25)对 jev-1.13.0 做了对抗性评测,结论触目惊心:
- 状态注入:在请求状态中追加一条未验证意见,可导致 12.1% 的决策被翻转
- 阈值穿透:此类注入使 38% 的高置信度答案(>0.8)跌破 0.8 路由阈值,被强制推向人工审核
- Rewording 稳定:单纯改写问题表述,偏差在 1.2 个百分点以内(较稳定)
- Schema 外字段:API 层面会把不合规范的字段预处理掉,不会到达模型
实操建议:不要把用户输入直接拼进 Jev 的 state prompt,必须做清洗和长度截断(教程建议 max_length=200),并始终保留人工兜底路径。
RLCD 方法论声明
RLCD(Reinforcement Learning for Calibrated Decisions)是 TypeSafe 自创术语,非行业标准。无公开论文、无奖励函数说明、无独立复现。其宣称的校准能力来自厂商自身材料,核验受限。性能数字需自行验证,不可盲目信任。
适用边界
- 适用:需要高频判断(工具安全、模型路由、答案质量)的自定义 Agent;追求比完整 LLM 调用更低延迟和成本的场景
- 不适用:判断逻辑本身很复杂(需要语义理解)的情况;Jev 不生成文本,无法做开放式推理
一句话结论
用 Pi SDK 的 Hook 机制把 Jev 三段式决策(Gate → Router → Verifier)嵌入 Agent 循环,是让自定义 Harness 同时实现低延迟判断和可审计策略的最直接路径——但必须正视 Jev 对状态注入的脆弱性,始终保留人工兜底。