
English | 简体中文
本文档为英文 README.md 的中文翻译,可能略有滞后;如有冲突以英文版为准。
AHE (Agentic Harness Engineering) 是一个开放的可观测性系统,用于自动演化围绕在编码 agent 周围的 harness。基础模型保持不变,演化的是 harness 的各个组件——系统提示词、工具描述、工具实现、中间件、skill、子 agent、以及长期记忆。
AHE 建立在三层可观测性之上:
经过十轮 评估 → 分析 → 改进 迭代,AHE 在 GPT-5.4 上把 Terminal-Bench 2 的 pass@1 从 69.7% 提升到 77.0%,超过手写的 Codex (71.9%) 以及自演化的 ACE 与 TF-GRPO 基线;同时产出了一个无需重新演化即可迁移到 SWE-bench-verified 以及四个其他基础模型上的"冻结 harness",表明被演化出的组件编码的是通用工程经验,而非针对单一 benchmark 的调优。

# macOS
brew install uv tmux
# Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
sudo apt install -y tmux
git clone https://github.com/Curry09/agentic-harness-engineering.git
cd agentic-harness-engineering
uv sync
uv sync会安装pyproject.toml中声明的所有依赖。
cp .env.example .env
编辑 .env,至少需要设置:
| 变量 | 用途 |
|---|---|
LLM_API_KEY / LLM_BASE_URL |
主 LLM 端点(code_agent 与 evolve_agent 都消费它) |
E2B_API_KEY |
E2B 沙箱——SaaS 与自部署的差异详见下一小节 |
SERPER_API_KEY |
evolve_agent 使用的 web 搜索 |
ADB_LLM_* 与 GPT54_LLM_* 是可选项——不设置时回退到 LLM_*,或可用它们让 ADB / gpt-5.4 实验指向更强的模型。LANGFUSE_*、BP_HTML_PARSER_* 与 FEISHU_WEBHOOK 全部是可选的可观测性 / 便利性钩子;完整列表见 .env.example。
AHE 每一次 rollout 都跑在 E2B 沙箱里,支持两种部署模式:
E2B_API_KEY,不要设置 E2B_API_URL / E2B_DOMAIN(注释掉即可)。SDK 会自动连到 e2b.dev。⚠️ 并发上限。 SaaS E2B 对每个账号有按 tier 划分的并发沙箱上限。如果 harbor 试图启动超出该上限的沙箱,多余的会启动失败,整轮迭代会卡住。在调高 harbor / 实验配置中的并行度之前,请先确认你的 tier 配额并保持安全余量。
E2B_API_KEY 并让 SDK 指向你的集群:dotenv
E2B_API_KEY="your_e2b_key"
E2B_API_URL="https://your-e2b-host.example.com"
E2B_DOMAIN="your-e2b-host.example.com"
没有共享并发上限,但仍受集群硬件容量约束。
这里使用的数据集来自 laude-institute/harbor-datasets 的子集——克隆你需要的部分,然后让 --dataset-dir 指向它的目录。
每次 rollout 都从一个预构建的 E2B 模板里启动沙箱,模板里已经装好了 uv 以及位于 /opt/nexau-venv 的 NexAU/harbor venv。在启动前一次性构建好这些模板:
# 构建数据集声明的所有模板,并发 16
uv run python scripts/build_templates.py --dataset-dir /path/to/dataset -j 16
# 失败后续跑:仅重试当前 E2B 构建状态为 ERROR 的任务
uv run python scripts/build_templates.py --dataset-dir /path/to/dataset --retry-failed
# 只构建某些任务
uv run python scripts/build_templates.py --dataset-dir /path/to/dataset task_a task_b
数据集目录下每个任务必须是一个子目录,里面有声明 [environment].docker_image 的 task.toml(或 environment/Dockerfile 作为 fallback)。每个任务的模板别名是 <task_name>,把 . 替换为 -。
每个模板默认烤进去的包列表来自 scripts/build_templates.py:DEFAULT_NEXAU_PACKAGES(一个公开的 NexAU + 沙箱内部使用的 NexAU-harbor 变体,故意区别于 pyproject.toml 中宿主侧的 harbor-LJH)。如果需要在沙箱里换一个版本,可用一个或多个 --nexau-package <git-or-pip-spec> 参数覆盖。
如果任务镜像来自私有 Docker registry,调用前还需要 export DOCKER_REGISTRY_USERNAME 和 DOCKER_REGISTRY_PASSWORD。
# 通过 tmux 在后台运行单个实验
./scripts/evolve.sh configs/experiments/exp-003-simple-code-gpt54.yaml
# 启动并自动 attach 到日志流
./scripts/evolve.sh --attach configs/experiments/exp-003-simple-code-gpt54.yaml
# 批量:启动 configs/experiments/ 下的所有实验
./scripts/evolve.sh --batch
启动后常用的 tmux 操作:
tmux ls # 列出会话
tmux attach -t <session> # 接入某个会话
# Ctrl-b d # 分离(会话仍在后台运行)
tmux kill-session -t <session> # 终止
基础模型保持不变,演化的是它周围的 harness。每一轮外层循环都是 评估 → 分析 → 改进,构建在概览中介绍的三层可观测性之上。
harbor 在隔离的 E2B 沙箱里把当前的 code_agent 跑一遍数据集。每个任务会写出:
agent/nexau_in_memory_tracer.cleaned.json —— 完整的 step 级 trace(消息、工具调用、中间件事件)agent/nexau.txt —— 运行时日志(中间件错误、崩溃、警告)verifier/reward.txt —— pass / fail 结果之后所有步骤操作的单位是 trace,而不是 pass rate。
Agent Debugger 把每一轮迭代的原始 trace(动辄 10M+ token)压缩成分层报告:
analysis/overview.md —— 跨任务的根因汇总analysis/detail/{task}.md —— 每个任务的深度分析优化器默认读 digest,但每一条结论都能反向链接到原始 trace,因此在落地修改前可以一路下钻。
关于 Agent Debugger 的开源说明。 当前版本中 Agent Debugger 是部分开源的;出于公司战略原因,目前无法完全开源。
Evolve Agent 只能写 workspace/ 内部,那里暴露了 NexAU 的七个组件:systemprompt.md、code_agent.yaml、tool_descriptions/、tools/、middleware/、skills/、sub_agents/(外加 LongTermMEMORY.md)。每一次修改必须提交四个字段:
每个 runs/iteration_NNN/ 同时混着两代:input/ 是上一轮 NNN-1 产出的 workspace(刚被评估完),evolve/ 是本轮 NNN 写出的内容(在下一轮被评估)。下一次评估中出现的翻转(pass↔fail)会在 change_evaluation.json 中归因回本轮的修改——预测不成立的会被回滚或修订。循环在达到 target_pass_rate 或 max_iterations 时终止。
| 组件 | 作用 |
|---|---|
evolve.py |
主循环编排器 |
agents/code_agent_simple/ |
被评估和被演化的编码 agent |
agents/evolve_agent/ |
执行改进步骤的元 agent(基于 NexAU 框架构建) |
agents/explore_agent/ |
上游数据集 / 源码探索 agent |
configs/ |
base.yaml(共享默认值)+ experiments/(按实验覆盖) |
scripts/ |
tmux 启动脚本(evolve.sh、evolve-resume.sh) |
agentic-harness-engineering/
├── evolve.py # 主循环
├── trace_converter.py # rollout trace → debugger 友好的 JSON
├── agents/
│ ├── code_agent_simple/ # 被演化的编码 agent
│ ├── evolve_agent/ # 演化元 agent
│ │ ├── evolve_prompt.md
│ │ ├── middleware/ # 上下文压缩 / failover / ralph 循环 …
│ │ ├── skills/ # agent-debugger-cli / nexau-evolution-guide
│ │ └── tools/ # 文件 / shell / web / 会话工具
│ └── explore_agent/ # 探索 agent(源码 + web)
├── configs/
│ ├── base.yaml # 共享默认值
│ └── experiments/ # 每个实验一个 overlay
├── scripts/
│ ├── evolve.sh # tmux 启动器
│ └── evolve-resume.sh # 续跑辅助
└── .env.example
configs/base.yaml 保存共享默认值。每个 configs/experiments/exp-*.yaml 通过开头的 _base: ../base.yaml 继承它,并只覆盖需要修改的字段。YAML 中的任何 ${ENV_NAME} 引用会从 .env 中替换。
base.yaml 关键字段:
| 字段 | 描述 |
|---|---|
path |
数据集路径 |
target_pass_rate |
达到后即停(默认 0.95) |
max_iterations |
最大迭代轮数(默认 100) |
harbor_job_timeout_minutes |
单次 harbor 评测的超时(0 = 不限) |
experiment_timeout_minutes |
整个实验的总 wall-clock 预算(0 = 不限) |
llm.api_key / base_url / model |
主 LLM 配置(通常保留 ${LLM_*}) |
agent_debugger.llm |
给 ADB 专用的 LLM(debug 时可换更强的模型) |
notify.feishu_webhook |
可选:在实验里程碑时推飞书 webhook |
实验的数据来源通过 path 或 dataset 指定——二选一:
| 形式 | 含义 | 示例 |
|---|---|---|
path: "./dataset/xxx" |
本地数据集目录(相对于 AHE 根目录) | ./dataset/terminal-bench-2 |
path: "/abs/path/xxx" |
本地数据集目录(绝对路径) | /root/dataset/terminal-bench-2 |
dataset: "<name>@<ver>" |
引用 harbor 内置数据集(不需要本地文件) | terminal-bench@2.0 |
公开的数据集包(按照 AHE 期望的目录结构)发布在 laude-institute/harbor-datasets——克隆或下载你需要的子集,然后让 path 指向它。
base.yaml 与 configs/experiments/*.yaml 中默认的 path 值都只是占位符——请按你的环境调整,或注释掉 path、解开 dataset 行以使用 harbor 的内置数据集。
python evolve.py| Flag | 描述 |
|---|---|
--config <file> |
配置文件(overlay 优先) |
--batch [dir\|files...] |
批量模式;默认扫描 configs/experiments/ |
--experiment <name> |
续跑某个已有实验(传 experiments/ 下的目录名) |
--start-iteration N |
从第 N 轮开始(默认 1) |
--skip-eval |
跳过评估、复用已有 rollout(调试用) |
./scripts/evolve.shuv run python evolve.py + tmux 的轻封装。
| Flag | 描述 |
|---|---|
<config_file> |
位置参数:配置文件路径 |
--experiment <name> |
续跑某个已有实验 |
--start-iteration N |
起始迭代 |
--skip-eval |
跳过评估 |
--session <name> |
自定义 tmux 会话名 |
--batch |
在批量模式下启动每个 overlay |
--attach |
启动后自动 attach |
从第 16 轮恢复一次中断的实验:
./scripts/evolve.sh \
--experiment 2026-04-10__23-20-14__gpt54 \
--start-iteration 16 \
configs/experiments/exp-003-simple-code-gpt54.yaml
只跑 evolve_agent,不重新评估:
./scripts/evolve.sh \
--experiment <existing-exp-dir> \
--skip-eval \
configs/experiments/exp-003-simple-code-gpt54.yaml
MIT
$ claude mcp add agentic-harness-engineering \
-- python -m otcore.mcp_server <graph>