跳转到主要内容
在 niceeval 里,Agent 是 core 调用的抽象,Adapter 是具体实现。你通过名字选择 agent,adapter 决定怎么调用被测系统、怎么把输出转成标准事件流。

两个词,一个边界

  • Agent:由 experiment 引用的 adapter,用来驱动被测系统。
  • Adapter:实现 send(input, ctx) 的代码,负责调用 HTTP、函数或 CLI。

为什么是 experiment 选 agent,不是 --url

experiment 选择 agent;experiment 名之后的位置参数只选择“跑哪些 eval”。被测系统的 URL、鉴权、模型和协议都属于 adapter 的私有配置。
# 同一份 eval,切换不同 adapter
npx niceeval exp local support
npx niceeval exp prod support

Agent contract

所有 adapter 最终都返回一个 Turn
type Turn = {
  events: StreamEvent[];
  data?: unknown;
  status: "completed" | "failed" | "waiting";
  usage?: Usage;
};
events 是主要事实来源。messagetoolCalls 等便捷字段会从事件流推导。

capabilities 决定 t 上有哪些方法

Adapter 声明能力:
capabilities: {
  conversation: true,
  toolObservability: true,
  sandbox: false,
}
这些 flags 控制 TypeScript 层面可见的 t 方法。例如没有 toolObservability 时,不应该使用 t.calledTool()

标准事件流

niceeval 用标准 StreamEvent[] 表示 agent 行为,包括文本输出、工具调用、子 agent、命令和错误。每个 adapter 可以从自己的原始 transcript 转换到这个 canonical stream。
如果你接的是已有 HTTP 服务,优先在 adapter 里写一个小 mapper,把服务响应转换成标准 events。不要让 eval 文件直接理解服务私有格式。

两种 transport

defineAgent

适合进程内函数和远程 HTTP 服务:
import { defineAgent } from "niceeval/adapter";

export default defineAgent({
  name: "support-bot",
  capabilities: { conversation: true },
  async send(input, ctx) {
    const res = await fetch(process.env.SUPPORT_BOT_URL!, {
      method: "POST",
      body: JSON.stringify({ message: input.text }),
      signal: ctx.signal,
    });
    const body = await res.json();
    return {
      status: "completed",
      events: [{ type: "message", role: "assistant", content: body.reply }],
      data: body,
    };
  },
});

defineSandboxAgent

适合需要文件系统的 coding agent。adapter 拿到 ctx.sandbox,在里面安装 CLI、运行命令、读取 transcript。
import { defineSandboxAgent } from "niceeval/adapter";

export default defineSandboxAgent({
  name: "my-cli-agent",
  async send(input, ctx) {
    await ctx.sandbox.runCommand("my-agent", ["run", input.text]);
    return { status: "completed", events: [] };
  },
});

内置 agents

niceeval 内置 claude-codecodexbub 的 sandbox adapters。自定义 adapter 用 defineAgent / defineSandboxAgent 创建,再从 experiment 文件引用。

Agent × Sandbox 正交

experiment.agent 选择谁来执行任务,--sandbox 选择在哪里执行任务。一个 sandbox agent 可以运行在 Docker,也可以运行在云端 sandbox。

相关阅读

  • 评分 — 标准事件流如何驱动作用域断言。
  • 架构概览 — 四层架构和边界。
  • 远程 Agent — 编写 HTTP / 进程内 adapter。