Skip to content

本地测试机 ​

Agent 留在你们自己的机器上。那台机器上跑一个小程序,也就是测试机:它从平台领取测试,在本机对 Agent 执行,再把结果传回平台。它只向外发起 HTTPS 连接,平台从不主动连你们的机器。Agent 依赖你们内网的系统,或者代码和数据不能出公司时,选这种接法。

开始之前 ​

  • 一台专用的测试机(macOS 或 Linux),能运行 Agent,也能连到它的测试后端。Agent 在上面以普通进程运行,没有容器隔离,所以不要用存有生产凭证或生产数据的机器。
  • Node.js 22.5 或更高版本。
  • 能经 HTTPS(443 端口)访问平台地址。不需要开任何入站端口。
  • Agent 的仓库在这台机器上,装好了它自己的依赖(Python 的虚拟环境、npm install 之类),Agent 在这台机器上能自己跑起来。测试机只运行,不替你装。
  • Agent 调模型的密钥:没有也可以。 这台机器上没有 OPENAI_API_KEY(也没设 OPENAI_BASE_URL)时,平台的模型替 Agent 回答,和云端沙盒一样按用量计费(2026 年 10 月 29 日起):reviewctl 在这台机器的 127.0.0.1 上开一个转发口,把地址和一个占位密钥交给 Agent,再用测试机自己的令牌转给平台,什么都不用建、不用复制。用 OpenAI SDK(读这两个变量)的 Agent 直接就能用。想用你们自己的密钥,把 OPENAI_API_KEY 设在这台机器的环境变量或仓库的 .env 里(值不会上传)。默认用别家模型(Anthropic、Gemini 一类)的 Agent:这台机器上有这家的密钥就用你们的;没有时,reviewctl connect --ai 先照 Agent 自己的配置把它换成平台的模型(例如在 agent.env 里设 MODEL=openai/gemini-4-argon),按用量计费,换不了(只用这家的 SDK、模型写死在代码里)才要你设这家的密钥。
  • 平台网关仍然可以用(比如测试以外、Agent 平时也想用平台的模型):在这台机器上设 OPENAI_BASE_URL=<平台地址>/gw/openai/v1,OPENAI_API_KEY 设成项目令牌(在自动化 →「API 令牌」新建,勾「允许上传日志与实验」才能调用模型),模型名用 <平台地址>/gw/openai/v1/models 列出的。Agent 的调用经 AI 网关由平台的模型回答,按用量计费,也会出现在项目的日志里。AI 写的 review.yaml 把 OPENAI_BASE_URL 放进 agent.env_passthrough,平台也不会把这个地址当公网地址去掉。
  • 评审模型不用准备:平台提供,按用量计入组织的账单,和沙盒里的平台评审一样(见下面「装命令行工具」最后一段)。AI 写的 review.yaml 评审模型写的就是项目的模型。只有 review.yaml 写的是你们自己的评审模型、这台机器上又有它的密钥时,才用你们自己的;平台的项目令牌(pj_…)不算这样的密钥。
  • 一个项目只走一条路:已经连了 GitHub 仓库或自带镜像的项目在云端沙盒里测,要在本机测就新建一个项目,在目标里选「本地测试机」。在那种项目上运行下面的命令,平台会在注册测试机、用掉配对码之前就拒绝。

最快的做法:让 AI 补全并检查 ​

不想自己写 review.yaml 和适配脚本,就在 Agent 的仓库里运行一条命令。平台的模型会读仓库,写好 .reviewctl/ 下的测试接入文件;命令再在你这台机器上预跑检查,没通过就按结果改了再查,最多检查 10 次。

  1. 装好 reviewctl(见下面第 1 步),登录一次:reviewctl login --api https://<平台地址>(在浏览器里批准)。
  2. 在网页上打开目标,选「本地测试机」(自托管 runner),「让 AI 补全并检查:一条命令」下面给出了这条命令,项目编号已经填好。这台机器还不是项目的测试机时,先点「生成配对码」,配对码会加到命令里(10 分钟内有效,只能用一次)。
  3. 在 Agent 的仓库根目录运行:
bash
reviewctl connect --ai --project <项目编号> --code ABCD-EFGH    # 已经是测试机的机器不用 --code

跑 Agent 的机器不归你管? 展开配对码按钮下面的「发给开发同事的说明」,生成配对码后把整段复制给开发同事:写的就是上面这几步,配对码已经加在命令里。他用自己在组织里的账号登录;还没有账号,请组织的所有者在「组织 → 成员」里给他一个邀请链接。

读什么、发什么。 命令按平台读 GitHub 仓库的同一套规则,在你的机器上读仓库:README、依赖清单、容器和 Compose 文件、.env.example、入口文件和它们导入的模块、这些代码按文件名打开的文本文件(运行时加载的制度、提示词文件)、看起来是 Agent 的模块,再加几个脚本和测试。一共最多 40 个文件、150 KB;单个文件超过 24 KB 只读前面一部分(在字符边界上截断,不会把一个汉字切成两半),超过 200 KB 的不读。另外还发最多 1500 个路径的名字,不含内容。是 Git 仓库时,只看 Git 管着的和没被 .gitignore 忽略的文件。

它从不读 .env 和其他可能存密钥的文件(只发名字),也不读二进制文件、node_modules 一类依赖和构建目录、指向仓库外的链接,以及 reviewctl 自己的运行记录。看起来像密钥的内容,发送前就在你的机器上去掉,平台收到后再去一遍。旧版 reviewctl 发来的内容超过大小上限时,平台自己截好,在「经过」的第一条写明哪些文件只读了前面一部分、哪些没读;读了不该读的文件(密钥文件、二进制、仓库外的路径)的上传,平台整个拒收。发送前,命令会列出每个文件和大小,问你同不同意(直接回车是不同意;加 --yes 不问)。上传的仓库内容只留到这次「让 AI 补全并检查」结束。

写文件。 命令把 AI 写的 review.yaml 和适配脚本写进仓库的 .reviewctl/,别的地方一律不写;平台发来别的路径时,命令整轮拒绝,什么都不写。已有的文件先备份到 .reviewctl/.backup/<时间>/。写之前,命令列出每个文件是新增、有改动还是没变,以及检查要运行的命令,问你一次(直接回车是同意)。.reviewctl/.gitignore 会忽略 .review/(检查的运行记录)和 .backup/。看一遍,没问题就自己提交。

检查。 每次检查都是这台机器上的一次预跑:命令自己当测试机,按 .reviewctl/review.yaml 跑一个测试,规则和 reviewctl runner start 一样。本地测试机不安装依赖、不构建容器、不起服务,所以 Agent 要的依赖和服务要先在这台机器(或你们的内网)上准备好;AI 写的 environment 和 services 段会被平台去掉。检查命令要用的程序在仓库里还没有(比如 .venv/bin/python),检查命令直接用 python3、可仓库的依赖装在它自己的虚拟环境(.venv 或 venv)里,或者仓库有依赖却没有 node_modules,命令写好文件后当场提醒。每次执行都在仓库的一份临时副本里跑,见下面「在仓库的临时副本里跑」。没通过时,命令在这次检查那一行下面打印报错原文(已去掉密钥),并把这次日志里看起来出错的几行连同上面提醒的缺什么发给平台,发之前先在你的机器上去掉密钥的值和像密钥的内容,AI 再按这些行改了再查。

密钥。 只发名字,从不发值。本地测试机上,Agent 调第三方服务用的是这台机器上的密钥;调模型时这台机器上有 OPENAI_API_KEY 就用它,没有就由平台的模型回答;评审模型平台提供(这台机器上有它的密钥时用你们自己的)。AI 不会把 OPENAI_API_KEY 算成缺的密钥。AI 说 Agent 要哪些密钥,命令就看这台机器的环境变量(和它加载的仓库 .env)里有没有;缺了就说缺哪几个,结束时再说一遍,网页上的结果也写着。设好以后再运行同一条命令,它从上次写好的文件接着检查,不再调用模型。

测试身份。 AI 在 review.yaml 的 runner_env 里写的合成测试身份(AGENT_TEST_USER: test-user-1,不是真账号),文件一写好平台就当成这台测试机放行的身份变量,AI 接着写的测试直接用它,不用再 --allow-auth-ref。

已经有一次在跑。 同一个项目同时只能有一次「让 AI 补全并检查」。上一次的命令被中断时,命令会说是哪台机器、多久前还在回应,问你要不要取消那次重新开始(加了 --yes 不替你取消)。也可以在网页目标下「本地测试机」的向导里点「取消」;什么都不做的话,那台机器上的 reviewctl 10 分钟没回应,平台会自己停下。

结束。 检查通过时退出码是 0,接着让测试机常驻:reviewctl runner start --config .reviewctl/review.yaml。停下时会说清原因,退出码是 1,原因可能是缺密钥、要确认一个测试(项目关了 AI 自动审批)、这个仓库没法这样测、检查没通过是 Agent 自己的问题、10 次检查都没通过,或者助手当天的用量用完了。你拒绝、按 Ctrl-C 或者等太久时会取消,退出码是 2:按一次 Ctrl-C(或关掉终端),命令马上告诉平台取消,平台的 AI 在下一次调用模型之前就停下,这台机器上正在跑的检查收尾后命令退出;再按一次立即退出,退出码也是 2。Agent 调模型的密钥被模型服务拒绝时(比如把项目令牌当 OpenAI 的密钥),AI 不再改接入文件,停下来说要换密钥,或者去掉这台机器上的 OPENAI_API_KEY、让平台的模型回答,退出码是 1;设好后再运行同一条命令,从这次写好的文件接着检查。网页上同一页面显示每一步,和 GitHub 向导的「让 AI 补全并检查」一样。平台的 AI 写的时候,命令每过一会儿说一次它到哪了;一步还在排队等平台的 AI 时说「第 N 步在排队等平台的 AI(前面还有 N 个……)」,轮到以后才说「模型还没开始输出」或已经写了多少(见让 AI 补全并检查)。

费用。 模型调用算进助手的每日用量;检查在你的机器上跑,不按沙盒时长收费;评审模型由平台提供时,按评审模型的用量收费。平台锁定的设置(评审模型、每次执行的上限、代理一类变量)和 GitHub 仓库的一样。本地测试机上,地址只能是这台机器或内网上的,不能是公网地址;平台自己的 AI 网关(<平台地址>/gw/…)除外。命令和选项见命令行。

想自己一步步来,就按下面的步骤。

1. 装命令行工具 ​

测试机是 reviewctl 命令行工具的一部分。平台自己提供带版本号的安装包,地址是 https://<平台地址>/downloads/。先看最新的是哪个版本,以及它的校验值:

bash
curl -fsS https://<平台地址>/downloads/latest.json
# {"version": "0.1.20260930120509", "file": "reviewctl-0.1.20260930120509.tgz", "sha256": "…", "size": …, "node": ">=22.5", "built_at": "…"}

下载这个文件和旁边发布的校验值,核对后安装:

bash
curl -fsSO https://<平台地址>/downloads/reviewctl-<版本>.tgz
curl -fsSO https://<平台地址>/downloads/reviewctl-<版本>.tgz.sha256
shasum -a 256 -c reviewctl-<版本>.tgz.sha256    # Linux 上用 sha256sum -c reviewctl-<版本>.tgz.sha256
npm install -g ./reviewctl-<版本>.tgz
reviewctl --version                              # 例如 0.1.20260930120509+2e690dd

也可以不核对,直接从地址安装:npm install -g https://<平台地址>/downloads/reviewctl-<版本>.tgz。两种方式下,npm 都会从它的源下载命令行工具用到的开源依赖。

报 EACCES(没权限)? 用系统自带的 Node(比如 Ubuntu 的 apt install nodejs)时,全局目录要 root 才能写。不用 sudo,装到自己的目录里,再把它加进 PATH:

bash
npm install -g --prefix ~/.local https://<平台地址>/downloads/reviewctl-<版本>.tgz
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && . ~/.bashrc    # zsh 写进 ~/.zshrc
reviewctl --version

命令行工具和测试机跟系统语言走,系统语言是中文时说中文;要固定用哪种,设 REVIEWCTL_LANG=zh 或 en。每条命令和选项见命令行。

平台每次发版都带一个新版本号(最后一段是构建时间)。平台有更新的版本时,目标 →「测试机」里这台测试机那一行会提示「有新版本 x.y.z」,并给出一行升级命令;reviewctl connect --ai 和 reviewctl runner start 开始时也会在终端里说一句。升级后重启测试机。

让「重启」顺便更新 ​

用 npm install -g 装的 reviewctl 可以让平台来更新:在测试机上用 reviewctl runner start --config review.yaml --self-update 启动(每台测试机自己选,不开就和以前一样)。之后它落后于平台的版本时,那一行的按钮变成「更新并重启」,点了以后测试机空闲时:

  1. 从它连着的那个平台下载安装包(只认同一个地址下的 /downloads/ 里的文件);
  2. 核对下载到的文件的 SHA-256 和平台随安装包一起公布、随这次重启发给它的校验值;
  3. 对得上才用 npm install -g <刚核对过的文件> 安装(不经过 shell;npm 照常从它的源下载开源依赖),然后重新启动。

对不上、下载不了,或者这台机器上的 reviewctl 不是用 npm install -g 装的,就什么都不装,用现在的版本重启,原因写在测试机的日志里。网页上那一行会写「上次「更新并重启」没有装上」,并给出手动升级的命令。校验值和安装包来自同一个平台,所以它防的是下载坏了或被调包,不防平台本身出问题。

评审模型。 本地测试机也用平台提供的评审模型(2026 年 10 月 22 日起):测试机经平台按用量计费的评审代理调用它,用的是测试机自己的令牌,平台的模型密钥不离开平台;review.yaml 写的是平台提供的模型时,换成项目的模型评审,第二个评审模型和嵌入模型也和沙盒里一样。费用按评审模型的用量计入组织的账单,每次任务的上限和沙盒一样。这时要判断的回复和测试要点会发给平台的评审模型。不想这样,就在这台机器上设好 review.yaml 写的评审模型的密钥(比如 openai:gpt-4.1-mini 要 OPENAI_API_KEY),测试机就用你们自己的,回复不经过平台。测试机的日志开始时会说这次用的是谁的评审模型。review.yaml 写的是平台不提供的模型、这台机器上又没有它的密钥时,没有评审模型可用。

Agent 自己调模型也一样(2026 年 10 月 29 日起):这台机器上没有 OPENAI_API_KEY 时,平台的模型替 Agent 回答,经平台按用量计费的模型代理,用的也是测试机自己的令牌,费用上限和沙盒一样;测试机的日志开始时会说这次谁替 Agent 回答。有 OPENAI_API_KEY 时用你们自己的。

2. 写 review.yaml ​

  1. 在网页上点「新建项目」,选「会调用工具的 Agent」,起个名字。打开目标,选「本地测试机」,页面会给出 review.yaml 的开头几行,里面有你们项目的编号。
  2. 在 Agent 的项目目录里生成一份初始配置(--project 填网页上的项目编号:注册测试机时 review.yaml 的 project.id 必须是它),再填上怎么启动 Agent、它的工具,以及怎么重置和读取测试数据:
bash
reviewctl init --project <项目编号> --domain <你们的业务领域>    # 例如 prj_01J8…、expense 或 generic
reviewctl doctor                                                 # 检查重置、工具观测、故障注入和数据读取

每一段、每个字段见 review.yaml 参考。reviewctl 会加载 review.yaml 旁边的 .env 文件。被测的 Agent 只拿到 review.yaml 交给它的变量(agent.env 和 env_passthrough),外加 PATH、HOME 这类基本变量,拿不到机器上的其他环境变量。密钥的值永远不写进 review.yaml,也不进报告。

3. 注册测试机 ​

在目标下「本地测试机」的向导里点「生成配对码」。配对码 10 分钟内有效,只能用一次。点「重新生成配对码」后,页面上原来那个马上作废:再用它注册会被拒,并说它已经作废了。在测试机上:

bash
reviewctl runner register --api https://<平台地址> --code ABCD-EFGH --config review.yaml

测试机的凭证存在 ~/.reviewctl/runners/<项目编号>.json,只有你的用户能读。网页上随时可以撤销。

不想自己动手?用上面「让 AI 补全并检查」的一条命令;也可以写成一句话交给你们的编码 AI(「开发机 AI」),它会连上平台、修好测试接入、再检查一次。开发机 AI 选「MCP over HTTP(不用装 reviewctl)」时,它自己不用装 reviewctl,但本地项目的预跑和测试在测试机上跑,测试机还是要装 reviewctl、运行 reviewctl runner start。开发机就是测试机时,编码 AI 用 reviewctl dev connect … --runner 连上,它的 MCP 服务起来时会顺带启动这台测试机,见从编码 AI 用平台。

4. 让它一直运行 ​

bash
reviewctl runner start --config review.yaml

用 systemd 或 launchd 托管,机器重启后它也能自动起来。运行期间它每隔几秒向平台领取任务、上报心跳,页面上显示为在线。按一次 Ctrl-C,它会在当前这次执行结束后停下并上传部分报告;按两次立即退出。

每次执行一跑完就开始判,后面的执行接着跑(2026 年 11 月 5 日起),所以最后一次执行跑完后很快就出报告,不用再等全部判完。最多同时判 3 次执行。每次执行里的评审调用还是一个接一个,判法和以前完全一样。Agent 在等平台的模型回复时,评审一次只判一件。几个评审调用同时在等、评审模型限流、暂时不可用或太慢时,这次运行先改回一次判一件,不会因此换第二评审模型来判;一次一件至少 1 分钟、又连着 5 个调用都答了,再回到同时判 3 件,每再改回一次,下次回到 3 件前要等的时间翻倍(最多 10 分钟)。快到费用上限时,评审把在等的每个调用都按它最多可能花的钱算,只要这些还放得下就再发一个(新发的这个自己不算;2026 年 11 月 5 日起,所以余地够一个调用最多花的钱时能同时判 2 件),连在等的那一个都放不下了就一次一件;一次运行超过上限最多一次调用的费用,和一次一件时一样。当时在等的那几个回来、又答了几个以后,会试着多放一个,上限调高了或者还有余地,就回到同时判 3 件(2026 年 11 月 5 日以前一直一次一件到运行结束)。评审什么时候、为什么改成一次一件,记在报告 JSON 的 usage.judge.concurrency 里。平台可能再跑一次的执行,等算数的那一次跑完再判;有模拟用户的测试,还是等最后一次执行跑完再判。

在仓库的临时副本里跑 ​

被测的 Agent 可能改文件、提交代码(比如 aider),它的工具(比如文件系统、Git 的 MCP 服务器)也可能写仓库。所以测试机(包括 connect --ai 的检查)在系统临时目录里给每次执行拷一份仓库:.git 也整份拷过去,Agent 的提交只进副本;.venv、node_modules 链接到你仓库里的;.env 这类没提交的文件也在副本里。数据重置、读数据和平台工具代理起的 stdio 工具服务器也都在副本里跑。下一次执行换一份新的,一个任务跑完就删掉,你的仓库不动。第一次复制时,日志会说副本在哪、多大。

  • 仓库是 git worktree 或子模块(.git 是指回别处的文件)时,副本里不带 .git。
  • 拷的是 Agent 运行的目录:review.yaml 在仓库根目录的 .reviewctl/ 下(「让 AI 补全并检查」就这样写),或者那个目录是 Git 仓库的根。review.yaml 放在仓库里别的子目录时不复制(它可能用到上层目录的路径),每次执行直接在那里跑,日志会直说。
  • 仓库(含 .git,不含 .venv、node_modules)超过 500 MB 时不复制,每次执行直接在你的仓库里跑,日志会直说。这种情况请给测试机专门克隆一份。
  • 链接过去的 .venv、node_modules 还是你的:Agent 往里面装包会改到它们。

平台经测试机能做什么、不能做什么:

  • 能选跑哪些已确认的测试、在什么情况下跑、跑几遍。
  • 不能下发命令。Agent 的命令和环境变量只来自你们机器上的 review.yaml,测试机拒绝任何它不认识的任务字段。

5. 写测试、预跑、开始测试 ​

  1. 在数据集 →「全部测试(详细列表)」里写测试:「让 AI 帮你写测试」「新建测试集」或「手写一个场景」,确认要留下的测试(场景与测试集)。
  2. 点「测试新版本」,再点「开始测试」。它先把这次的功能测试各预跑一次,看测试是不是真的进到了 Agent;预跑通过后,正式运行自动开始。每项测 1 遍、只测正常情况时,正式运行和预跑跑的一样,不另外预跑,它本身先当预跑。取消预跑,等着它的那次测试也会一起取消。不想预跑,开始时勾上「跳过预跑,开始正式测试」。复测(把之前某次运行里的测试重跑一遍并对比)和普通测试一样,没设通过标准时用默认的。
  3. 这一轮变成一个带发布门槛的实验;它的「完整报告」给出结论、每个问题的证据和修改意见。有时只有评审模型读得出 Agent 有没有说办成,而评审模型又用不了(review.yaml 写的是平台不提供的模型、测试机上又没有它的密钥,或者每次调用都失败)。这时这些测试算「没测成」,结论不会是通过。

预跑没通过、入口程序报错时,预跑结果的「详情」里有测试机报上来的报错原文(stderr 最后几行,或者程序没起来的原因,比如 spawn .venv/bin/python ENOENT),密钥已去掉;开发机 AI 读预跑结果时也拿得到。

也可以在命令行里跑,比如放进 CI:

bash
reviewctl review --wait                           # 退出码 0 通过、1 阻断、2 没跑完、3 出错
reviewctl retest --run <基线 run id> --wait       # 对照之前的一次运行复测新版本,并做对比
reviewctl login --api https://<平台地址>           # 只需一次:用设备码登录
reviewctl push --run <run id>                      # 把本地的一次运行上传到平台

选项见命令行。

什么会进我们的云 ​

只有运行包(证据、脱敏轨迹和日志)和测试文件会进我们的云。源码、测试数据和凭证都留在你们的机器上,只有用 reviewctl connect --ai 时例外:经你同意,按上面的规则挑出的一部分源码文件会发给平台的模型,发之前已去掉像密钥的内容,留到那次「让 AI 补全并检查」结束为止;检查日志里出错的几行同样先去掉密钥再发。运行包里只记环境变量的名字,不记值。用本地测试机时,评审模型默认是平台的:要判断的回复和测试要点经平台的评审代理发给评审模型;这台机器上有评审模型的密钥时,由你们的机器用自己的密钥调用,不经过平台。一个运行包解压后最多 512 MB、10000 个文件、单个文件 64 MB;超过的会被拒绝,什么也不留。

本站的法律文件都是草稿,待律师审阅,尚未生效。