MCPcopy Index your code
hub / github.com/china-qijizhifeng/agentic-harness-engineering

github.com/china-qijizhifeng/agentic-harness-engineering @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
676 symbols 2,395 edges 96 files 402 documented · 59% updated 23d ago★ 6982 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Agentic Harness Engineering:以可观测性驱动的编码 Agent Harness 自动演化

Paper PDF Blog License: MIT Python Managed with uv

Agentic Harness Engineering

English | 简体中文

本文档为英文 README.md 的中文翻译,可能略有滞后;如有冲突以英文版为准。


📰 动态


🎯 概览

AHE (Agentic Harness Engineering) 是一个开放的可观测性系统,用于自动演化围绕在编码 agent 周围的 harness。基础模型保持不变,演化的是 harness 的各个组件——系统提示词、工具描述、工具实现、中间件、skill、子 agent、以及长期记忆。

AHE 建立在三层可观测性之上:

  • 组件可观测性 (Component observability) —— NexAU 把 harness 拆分为七个正交的文件级组件,每一项都纳入 git 追踪,因此每次修改都可审计、可回退。
  • 经验可观测性 (Experience observability) —— Agent Debugger 把 ~10M-token 的原始 trace 蒸馏成分层、可溯源的报告;优化器默认读 digest,但任何论断都可以下钻回某次 rollout 的原始 trace。
  • 决策可观测性 (Decision observability) —— Evolve Agent 提出有证据支撑的修改、预测其影响,并由下一轮迭代中翻转的任务自动证伪。

经过十轮 评估 → 分析 → 改进 迭代,AHE 在 GPT-5.4 上把 Terminal-Bench 2 的 pass@1 从 69.7% 提升到 77.0%,超过手写的 Codex (71.9%) 以及自演化的 ACE 与 TF-GRPO 基线;同时产出了一个无需重新演化即可迁移到 SWE-bench-verified 以及四个其他基础模型上的"冻结 harness",表明被演化出的组件编码的是通用工程经验,而非针对单一 benchmark 的调优。

Cross-Model Transfer Case Study Training Curve


🚀 快速开始

0. 前置依赖

  • Python ≥ 3.13
  • uv
  • tmux
# macOS
brew install uv tmux

# Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
sudo apt install -y tmux

1. 克隆 + 安装依赖

git clone https://github.com/Curry09/agentic-harness-engineering.git
cd agentic-harness-engineering
uv sync

uv sync 会安装 pyproject.toml 中声明的所有依赖。

2. 配置环境变量

cp .env.example .env

编辑 .env,至少需要设置:

变量 用途
LLM_API_KEY / LLM_BASE_URL 主 LLM 端点(code_agentevolve_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

E2B 沙箱:SaaS 与自部署

AHE 每一次 rollout 都跑在 E2B 沙箱里,支持两种部署模式:

  • SaaS E2B(默认)。 设置 E2B_API_KEY,不要设置 E2B_API_URL / E2B_DOMAIN(注释掉即可)。SDK 会自动连到 e2b.dev

⚠️ 并发上限。 SaaS E2B 对每个账号有按 tier 划分的并发沙箱上限。如果 harbor 试图启动超出该上限的沙箱,多余的会启动失败,整轮迭代会卡住。在调高 harbor / 实验配置中的并行度之前,请先确认你的 tier 配额并保持安全余量。

  • 自部署 E2B 集群。 设置 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"

没有共享并发上限,但仍受集群硬件容量约束。

3. 构建 E2B 模板(每个数据集一次性)

这里使用的数据集来自 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_imagetask.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_USERNAMEDOCKER_REGISTRY_PASSWORD

4. 启动

# 通过 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。每一轮外层循环都是 评估 → 分析 → 改进,构建在概览中介绍的三层可观测性之上。

1. 评估 (Evaluate) —— 输出的不只是分数,更是 trace

harbor 在隔离的 E2B 沙箱里把当前的 code_agent 跑一遍数据集。每个任务会写出:

  • agent/nexau_in_memory_tracer.cleaned.json —— 完整的 step 级 trace(消息、工具调用、中间件事件)
  • agent/nexau.txt —— 运行时日志(中间件错误、崩溃、警告)
  • verifier/reward.txt —— pass / fail 结果

之后所有步骤操作的单位是 trace,而不是 pass rate

2. 分析 (Analyze) —— 把 ~10M-token 的 trace 蒸馏成可溯源证据

Agent Debugger 把每一轮迭代的原始 trace(动辄 10M+ token)压缩成分层报告:

  • analysis/overview.md —— 跨任务的根因汇总
  • analysis/detail/{task}.md —— 每个任务的深度分析

优化器默认读 digest,但每一条结论都能反向链接到原始 trace,因此在落地修改前可以一路下钻。

关于 Agent Debugger 的开源说明。 当前版本中 Agent Debugger 是部分开源的;出于公司战略原因,目前无法完全开源。

3. 改进 (Improve) —— 有证据支撑、可证伪的修改

Evolve Agent 只能写 workspace/ 内部,那里暴露了 NexAU 的七个组件:systemprompt.mdcode_agent.yamltool_descriptions/tools/middleware/skills/sub_agents/(外加 LongTermMEMORY.md)。每一次修改必须提交四个字段:

  1. 失败证据 (Failure evidence) —— 触发本次修改的失败任务和 trace 片段
  2. 根因 (Root cause) —— 为什么失败,而不仅仅是失败了什么
  3. 针对性修复 (Targeted fix) —— 直接对准上述根因的改动
  4. 预测影响 (Predicted impact) —— 哪些任务应当翻转为 pass,哪些可能受到风险

4. 循环 (Loop) —— 错峰世代让证伪成为可能

每个 runs/iteration_NNN/ 同时混着两代:input/ 是上一轮 NNN-1 产出的 workspace(刚被评估完),evolve/ 是本轮 NNN 写出的内容(在下一轮被评估)。下一次评估中出现的翻转(pass↔fail)会在 change_evaluation.json 中归因回本轮的修改——预测不成立的会被回滚或修订。循环在达到 target_pass_ratemax_iterations 时终止。

主要组件

组件 作用
evolve.py 主循环编排器
agents/code_agent_simple/ 被评估和被演化的编码 agent
agents/evolve_agent/ 执行改进步骤的元 agent(基于 NexAU 框架构建)
agents/explore_agent/ 上游数据集 / 源码探索 agent
configs/ base.yaml(共享默认值)+ experiments/(按实验覆盖)
scripts/ tmux 启动脚本(evolve.shevolve-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

配置(base + overlay)

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.yamlconfigs/experiments/*.yaml 中默认的 path 值都只是占位符——请按你的环境调整,或注释掉 path、解开 dataset 行以使用 harbor 的内置数据集。


CLI 参考

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.sh

uv 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


Star 历史

Star History Chart

Core symbols most depended-on inside this repo

search
called by 63
agents/evolve_agent/tools/web_tools/web_tool.py
read_text
called by 43
agents/evolve_agent/tools/llm_friendly.py
get_sandbox
called by 13
agents/evolve_agent/tools/_sandbox_utils.py
resolve_path
called by 12
agents/evolve_agent/tools/_sandbox_utils.py
get_llm_config
called by 10
evolve.py
_clean_shell_token
called by 10
experiments/evolved_harness/tools/shell_tools/run_shell_command.py
_emit_failure
called by 10
agents/evolve_agent/skills/agent-debugger-cli/_source/agent_debugger_core/cli/adb.py
run_agent
called by 10
agents/evolve_agent/skills/agent-debugger-cli/_source/agent_debugger_core/runtime/runner.py

Shape

Function 394
Method 213
Class 69

Languages

Python100%

Modules by API surface

evolve.py92 symbols
agents/evolve_agent/tools/mcp_client.py76 symbols
trace_converter.py34 symbols
agents/evolve_agent/tools/file_tools/apply_patch.py31 symbols
agents/evolve_agent/tools/llm_friendly.py28 symbols
experiments/evolved_harness/middleware/execution_risk_hints.py25 symbols
agents/evolve_agent/skills/nexau-evolution-guide/scripts/validate_agent.py21 symbols
agents/evolve_agent/middleware/context_compaction/middleware.py19 symbols
experiments/evolved_harness/tools/shell_tools/run_shell_command.py16 symbols
agents/evolve_agent/middleware/llm_failover.py15 symbols
agents/evolve_agent/middleware/context_compaction/compact_stratigies/sliding_window.py15 symbols
agents/evolve_agent/middleware/context_compaction/compact_stratigies/user_model_full_trace_adaptive.py14 symbols

For agents

$ claude mcp add agentic-harness-engineering \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page