Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
e646126
Add the redesigned VeRO system at the repository root
varunursekar Jul 23, 2026
4d98f4b
harbor: baseline_floor off by default + pinnable baseline score (feed…
varunursekar Jul 23, 2026
4bbe47b
harbor: score-baseline producer for pinnable baseline numbers (feedba…
varunursekar Jul 23, 2026
dcd7ffa
tests: fix harbor build benchmark tests for the split + candidates fl…
varunursekar Jul 23, 2026
6d7f18d
harbor: k-anonymity floor defaults to 5, not a no-op (feedback #2)
varunursekar Jul 23, 2026
b535d18
harbor: pre-warm harness uv cache so isolation actually works
varunursekar Jul 23, 2026
b069cb1
harbor: re-record n_dead_infra / n_clean in the mean aggregate (feedb…
varunursekar Jul 23, 2026
d1076c5
address Greptile review on PR #45
varunursekar Jul 23, 2026
bc4316d
docs: harbor benchmark architecture overview + review order
varunursekar Jul 23, 2026
3693319
Bump harbor to 0.20.0; drop dead harness PYTHONPATH workaround
varunursekar Jul 23, 2026
5ef8162
Fix harness isolation: grant traversal on the candidate checkout parent
varunursekar Jul 23, 2026
54b91b1
Fail fast when the harness can't reach its workspace after provisioning
varunursekar Jul 23, 2026
b85de40
Add container integration test for harness-isolation invariants
varunursekar Jul 23, 2026
0dcdbd6
Rename agent context .vero -> .evals with self-describing inner tree
varunursekar Jul 24, 2026
91f58e4
Add agent-facing `evals` CLI and packaged skill
varunursekar Jul 24, 2026
10e3dea
small changes
varunursekar Jul 24, 2026
3fdcf90
Enforce the k-anonymity floor in the engine; type the spec->policy seam
varunursekar Jul 24, 2026
8d20950
Sidecar context: write task resources under tasks/ and emit plan.json
varunursekar Jul 24, 2026
0af70e1
Share one context-tree writer between the workspace and sidecar paths
varunursekar Jul 24, 2026
0d08967
Gateway telemetry: per-request logging and W&B mirroring from the sid…
varunursekar Jul 24, 2026
893a904
Backend: alias OPENAI_API_BASE for task packages that template it
varunursekar Jul 24, 2026
5dae928
Build config: recognize vendored local task_source in manifest check
varunursekar Jul 24, 2026
f7975f9
Report per-evaluation cost and latency; accuracy stays the objective
varunursekar Jul 24, 2026
1e97791
Per-trial token accounting: agent-reported metrics + flagged gateway …
varunursekar Jul 24, 2026
e4fe668
fix: cap requires-python <3.14 so uv can't pick a Python that fails t…
shehabyasser-scale Jul 24, 2026
f4e2057
fix: forward per-run agent env (--ae) to the optimizer's harbor run
shehabyasser-scale Jul 24, 2026
cc464ce
Complete run_command test stubs for the merged agent_env field
varunursekar Jul 24, 2026
14d69ca
Preserve cancellation and shield refunds in the budget cleanup paths
varunursekar Jul 24, 2026
d949a39
Gate infrastructure exclusion and retry to trusted evaluations
varunursekar Jul 24, 2026
34b732f
Document AgentAccessSpec and VerificationTargetSpec
varunursekar Jul 25, 2026
d059a6e
Replace EvaluationModel with a shared StrictModel base
varunursekar Jul 25, 2026
145fa29
Document the remaining build config models
varunursekar Jul 25, 2026
800af32
Reject models the inference gateway would refuse at build time
varunursekar Jul 25, 2026
99626a1
Let a build declare a command evaluation backend
varunursekar Jul 25, 2026
a431e8f
Make task_source optional, required only for a harbor backend
varunursekar Jul 25, 2026
d822ed5
Resolve a relative harness_source against the build YAML
varunursekar Jul 25, 2026
0f8aaee
Record the measured scope of the nested-backend refactor
varunursekar Jul 25, 2026
936a3f1
Centralize the compiled-task layout in one object
varunursekar Jul 25, 2026
f27d4aa
Derive the sidecar factory path instead of hardcoding it
varunursekar Jul 25, 2026
4462614
Derive every gateway scope URL from one route string
varunursekar Jul 25, 2026
7532c1e
Make the task image build timeout configurable
varunursekar Jul 25, 2026
2da2901
Group vero/ by process and trust boundary
varunursekar Jul 26, 2026
5ff70a9
Fix the circle-packing example against the current policy schema
varunursekar Jul 26, 2026
41739e6
Add a compiled, gateway-metered variant of the circle-packing example
varunursekar Jul 26, 2026
d131412
Move the benchmark-config tests to the branch that has the benchmarks
varunursekar Jul 26, 2026
5bd66a2
Move the report's HTML document out of a Python string literal
varunursekar Jul 26, 2026
e3e3003
Single-source the credentials the compose file routes to the gateway
varunursekar Jul 26, 2026
55487cb
Decompose the Harbor build config by concern
varunursekar Jul 26, 2026
70f8273
Point the architecture doc at the modules that exist
varunursekar Jul 26, 2026
a480213
Give the ledger's three durable writes one drain loop
varunursekar Jul 26, 2026
c038d11
Shield the success path's record write like the two failure paths
varunursekar Jul 26, 2026
e4ba52d
Let a verification target override attempts-per-case
varunursekar Jul 27, 2026
0148acb
Stop advertising the retired insights subagent in the optimizer instr…
varunursekar Jul 27, 2026
b67bca8
Document blocking evals + power-flags + submit for the optimizer
varunursekar Jul 27, 2026
3ce8913
Add elapsed/case-count to evals status; add evals wait
varunursekar Jul 27, 2026
b85f760
Report per-case cost the way latency is: mean, median, and max
varunursekar Jul 27, 2026
585e34d
Stop advertising a seed the Harbor backend rejects, and say why it re…
varunursekar Jul 27, 2026
d49df2c
Publish each partition's case count in the evaluation plan
varunursekar Jul 27, 2026
1528914
Tell the optimizer to keep every evaluation call in the foreground
varunursekar Jul 27, 2026
2dbc335
Tell the optimizer its results are persisted, so printed output is di…
varunursekar Jul 27, 2026
a49fa4c
Add a cheap end-to-end conformance example for new harnesses and models
varunursekar Jul 27, 2026
c3db0c9
Lift Harbor trial phases into CaseResult.execution_trace
varunursekar Jul 27, 2026
24a8ec2
Route opencode's non-openai providers through the gateway
varunursekar Jul 27, 2026
7f4c91a
Add a conformance-check skill for validating a harness or model
varunursekar Jul 27, 2026
98ebbcf
conformance: let uv-installed harnesses install as the optimizer user
varunursekar Jul 27, 2026
2971474
Refund the reservation when cancellation escapes as a raw CancelledError
varunursekar Jul 27, 2026
31dd261
Stop the finalization drain from inheriting the unreachable eval ceiling
varunursekar Jul 27, 2026
3d3b826
Publish which backend serves each partition in the evaluation plan
varunursekar Jul 28, 2026
c2d5a19
Return a terminal status for budget exhaustion so nothing retries it
varunursekar Jul 28, 2026
5417507
Name the outer trial's Modal app so its sandbox can be found
varunursekar Jul 28, 2026
41ba60f
Raise opencode's step limit so the harness does not truncate the search
varunursekar Jul 28, 2026
2697735
Give litellm-based harnesses the gateway URL under the name litellm r…
varunursekar Jul 28, 2026
7789354
Send litellm's anthropic route the path it will not double
varunursekar Jul 28, 2026
b4ce2ad
Meter the prompt Anthropic reports in its cache fields
varunursekar Jul 28, 2026
10a4749
Complete the non-streaming request before closing it
varunursekar Jul 28, 2026
1035a44
Point kimi-cli at the gateway instead of api.openai.com
varunursekar Jul 28, 2026
1cfa624
Write kimi-cli's gateway base URL into its config file
varunursekar Jul 28, 2026
3d37dc9
Re-lock against the declared Python range
varunursekar Jul 28, 2026
37f95b7
Make the paper code findable and turn the library README back into one
varunursekar Jul 28, 2026
3334b72
Give the READMEs a real result, and report the baseline that produced it
varunursekar Jul 28, 2026
13ca48e
Decline auto_best selection instead of asserting on absent fields
varunursekar Jul 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Python-generated files
__pycache__/
.pytest_cache/
*.py[oc]
build/
dist/
Expand All @@ -9,3 +10,11 @@ wheels/
# Virtual environments
.venv
.env*

# Run secrets loaded via `vero harbor run --env-file` (keep only *.example)
secrets.env
*.secrets.env
!*.example

# Local benchmark scoping notes (paper planning; not tracked)
harness-engineering-bench/benchmark-scoping.md
164 changes: 77 additions & 87 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,122 +1,112 @@
# VeRO: Versioning Rewards and Observations
# VeRO: a harness for agents to optimize programs, text, and agents
> **Looking for the code from the VeRO paper?** See
> [Paper reproduction](#paper-reproduction) — reproduce from the `paper-v1`
> tag, or read the same code in place under [`legacy/`](legacy/).

[![Paper](https://img.shields.io/badge/arXiv-2602.22480-b31b1b.svg)](https://arxiv.org/abs/2602.22480)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)

VeRO is an evaluation harness for using coding agents to optimize LLM-based agents and workflows. It treats agent code as a versioned artifact — making changes, evaluating results, and hill-climbing toward better performance using git version control.

> **Paper**: [VeRO: An Evaluation Harness for Agents to Optimize Agents](https://arxiv.org/abs/2602.22480)

## Repository Structure
VeRO gives a coding agent something to edit, an evaluation boundary, and durable
memory of every candidate it tried. The target is anything you can put under Git
and score — a **program** (a single function up to a whole codebase), **text**
(a prompt, spec, or config), or an **agent** (its scaffold, tools, and prompts).
VeRO was introduced to optimize agents, and the same version / evaluate / select
loop applies to any of these.

```
vero/
├── vero/ # Core library (scale-vero)
├── vero-agents/ # Agent implementations (benchmarking targets)
├── vero-benchmarking/ # Benchmarking scripts and analysis
└── LICENSE
┌─────────────────────────┐ submit candidate ┌─────────────────────────┐
│ candidate production ├──────────────────────►│ evaluation service │
│ │ │ │
│ coding agent, command, │◄──────────────────────┤ owns cases + scoring │
│ or custom strategy; │ score + diagnostics │ │
│ edits its own Git │ │ development: may ask │
│ worktree per candidate │ │ validation: aggregate │
└───────────┬─────────────┘ │ test: withheld │
│ commit └───────────┬─────────────┘
▼ │ report
┌─────────────────────────┐ next round ┌───────────────▼─────────────┐
│ candidate history: │◄──────────────────┤ selection: keep the best │
│ every version kept, │ │ feasible candidate │
│ each one re-selectable │ └─────────────────────────────┘
└─────────────────────────┘

Every model call on both sides goes through the inference gateway, which holds
the provider key and meters spend in tokens against a per-scope budget.
```

### [vero/](vero/)

The core optimization framework. Provides:

- **Policy** — orchestrates the optimization loop (agent + evaluator + git)
- **Agents** — VeroAgent (OpenAI Agents SDK) and ClaudeCodeAgent (Claude Agent SDK)
- **Evaluator** — runs task evaluations in isolated subprocess environments
- **Tools** — MCP-based tools for agents (bash, file I/O, experiment runner, dataset viewer, etc.)
- **Traces** — session analysis and LLM-based trace interpretation

```bash
cd vero && uv sync --extra optimize
```

See [vero/README.md](vero/README.md) for full documentation.

### [vero-agents/](vero-agents/)
The target and evaluator do not need to be Python. External evaluators and
candidate producers connect through command protocols; Python benchmarks can
use the optional, optimizer-independent `scale-vero-tasks` package.

Agent implementations used as optimization targets:
Targets may live locally or in an isolated sandbox. VeRO keeps optimization
state and experiment tracking on the host while running Git worktrees, producer
commands, builds, and evaluation commands in the target sandbox. The core guide
includes a no-bind-mount `DockerSandbox` example.

| Agent | Description |
|-------|-------------|
| **generic-agent** | General-purpose agent for MATH, GPQA, GAIA, GSM8K, etc. |
| **web_search_agent** | Web search agent for SimpleQA, Facts Search |
| **KIRA** | Terminal task agent for Terminal Bench 2.0 |
| **tau-bench** | Customer service tool-use agent |
| **pharma_summarizer** | Document summarization agent |
## Repository layout

See [vero-agents/README.md](vero-agents/README.md) for details.
| Directory | Purpose |
| --- | --- |
| [`vero/`](vero/) | The `scale-vero` optimization kernel, runtime, CLI, and coding-agent adapters |
| [`vero-tasks/`](vero-tasks/) | Narrow Python task types and schema-v1 evaluation runner |
| [`harness-engineering-bench/`](harness-engineering-bench/) | Harbor-native target programs and end-to-end optimization benchmarks |
| [`legacy/`](legacy/) | The pre-v0.5 tree, i.e. the original VeRO paper code — reference only, not used by the current system |

### [vero-benchmarking/](vero-benchmarking/)
Start with the [generic C matrix-multiplication quickstart](vero/examples/c-matmul/),
try the [26-circle packing benchmark](vero/examples/circle-packing/), or read the
[core guide](vero/README.md). The C example demonstrates the language-neutral
command protocol without model credentials. Circle packing is a substantive
coding-agent benchmark with exact geometry checks and inspectable search
artifacts.

Scripts and infrastructure for running optimization experiments:
For a full agent-optimization example, the [GAIA benchmark](harness-engineering-bench/gaia/)
pairs a tool-using GPT-5.4 mini target with Harbor's canonical GAIA verifier and
an immutable 20% / 40% / 40% development, validation, and test split.

```bash
cd vero-benchmarking && uv sync --all-extras

# Run an optimization experiment
uv run python scripts/run_benchmark.py --scaffold claude-code-vmf --model sonnet --task math

# Build datasets
./scripts/build_datasets.sh
cd vero
uv sync --all-extras
uv run vero --help
```

See [vero-benchmarking/README.md](vero-benchmarking/README.md) for full documentation.
## Paper reproduction

## Quick Start
VeRO was introduced in [*VeRO: A Harness for Agents to Optimize
Agents*](https://arxiv.org/abs/2602.22480), accepted at ICML 2026. The current
library generalizes that version/evaluate/select loop from agents to programs.

### Prerequisites
The paper-era code is available two ways, and they hold the same code:

- Python 3.11+
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
- Git
- Access to an LLM provider (via LiteLLM, OpenAI, Anthropic, etc.)

### Install
**To reproduce the paper, use the frozen ref.** It is the repository exactly as
it stood at publication, with the original paths intact:

```bash
git clone <repo-url> && cd vero

# Install core library
cd vero && uv sync --extra optimize

# Install benchmarking tools
cd ../vero-benchmarking && uv sync --all-extras
git checkout paper-v1 # tag; the paper/v1 branch points at the same commit
```

### Run Your First Optimization

```python
from agents import Agent as OAIAgent
from vero.policy import Policy
from vero.agents.vero import VeroAgent

policy = Policy(
project_path="/path/to/my-agent",
dataset="/path/to/my-dataset",
agent=VeroAgent(
oai_agent=OAIAgent(name="VeroAgent", model="anthropic/claude-sonnet-4-5-20250929"),
),
task="main",
train_budget=10,
max_turns=200,
)

best = await policy.run()
print(f"Best commit: {best.commit}, score: {best.score}")
```
**To read that code alongside the current system, use [`legacy/`](legacy/).** The
v0.5 redesign relocated the paper-era tree into that directory rather than
deleting it, so it sits in this branch next to the code that replaced it. Both
the frozen ref and `legacy/` include the paper-era `vero-agents` and
`vero-benchmarking` directories; their Harbor-native replacement is
[`harness-engineering-bench/`](harness-engineering-bench/).

Prefer the frozen ref for reproduction, since it is the state that was actually
published. Either way, note that both packages are named `scale-vero` and both
import as `vero` (0.4.7 in `legacy/vero`, 0.5.0 in `vero/`), so **they cannot be
installed into the same environment** — give the legacy package its own
virtualenv. Development of the current system continues on `main`.

## Citation

```bibtex
@article{ursekar2026vero,
title={VeRO: An Evaluation Harness for Agents to Optimize Agents},
title={VeRO: A Harness for Agents to Optimize Agents},
author={Ursekar, Varun and Shanker, Apaar and Chatrath, Veronica and Xue, Yuan (Emily) and Denton, Sam},
journal={arXiv preprint arXiv:2602.22480},
year={2026}
}
```

## License

[MIT](LICENSE)
VeRO is licensed under the [MIT License](LICENSE).
11 changes: 11 additions & 0 deletions legacy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,14 @@ This directory archives the codebase as it existed before the v0.5 redesign —
it is the code for the **original VeRO paper**. It is kept for reference and
reproducibility only; it is not used by the current system, whose code lives at
the repository root (`vero/`, `harness-engineering-bench/`).

**Reproducing the paper?** Prefer the frozen ref, which is the repository exactly
as it stood at publication rather than relocated under this directory:

```bash
git checkout paper-v1 # tag; the paper/v1 branch points at the same commit
```

**Installing anything from here?** Give it its own virtualenv. `legacy/vero` is
`scale-vero` 0.4.7 and the current `vero/` is `scale-vero` 0.5.0; both import as
`vero`, so they cannot share an environment.
3 changes: 3 additions & 0 deletions runs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Local GAIA/harbor run outputs — inspectable, not committed.
*
!.gitignore
35 changes: 35 additions & 0 deletions vero-tasks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# scale-vero-tasks

`scale-vero-tasks` is the optional Python task protocol used by VeRO benchmark
targets. It contains no optimizer, workspace, session, dataset-store, or
experiment-database code.

```python
from vero_tasks import TaskOutput, TaskResult, create_task

task = create_task("exact_match")

@task.inference()
async def infer(case, context):
return TaskOutput(output=case["question"].upper())

@task.evaluation()
async def evaluate(case, output, context):
return TaskResult.from_task_output(
output,
score=float(output.output == case["answer"]),
)
```

The runner accepts a VeRO command-evaluation request and an external JSON/JSONL
case file, imports a task module, and writes a schema-v1 evaluation report. The
standard VeRO adapter runs this package in a trusted evaluator project while
overlaying the candidate package as an editable dependency. This keeps Python
benchmark ergonomics separate from both the target program and VeRO's
language-neutral evaluation kernel.

The runner applies VeRO's retry policy independently to each non-batch
inference and evaluation call. Provider rate limits, configured HTTP status
codes or messages, and timeouts can be retried with bounded exponential
backoff. Earlier failed attempts are retained in the canonical case error list;
they are non-terminal when a later attempt succeeds.
16 changes: 16 additions & 0 deletions vero-tasks/examples/matmul-eval/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[project]
name = "matmul-eval"
version = "0.1.0"
description = "Evaluation task for the matmul kernel — measures correctness and speed"
requires-python = ">=3.11"
dependencies = ["scale-vero-tasks>=0.2.0"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/matmul_eval"]

[tool.uv.sources]
scale-vero-tasks = { path = "../..", editable = true }
Empty file.
70 changes: 70 additions & 0 deletions vero-tasks/examples/matmul-eval/src/matmul_eval/matmul_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Matrix multiply evaluation task.
Measures correctness and execution speed of a matmul kernel.
Score = average time per multiply (lower is better).
Incorrect results get a penalty score of 999999.0.
"""

import time

from vero_tasks import (
TaskContext,
TaskOutput,
TaskParameters,
TaskResult,
create_task,
)


class MatmulParameters(TaskParameters):
n_repeats: int = 100


matmul_task = create_task("matmul", task_parameters_type=MatmulParameters)


@matmul_task.inference()
async def run_inference(task: dict, context: TaskContext) -> TaskOutput:
from matmul_kernel import multiply

a = task["matrix_a"]
b = task["matrix_b"]

parameters = context.parse_task_params(MatmulParameters)

# Warmup
multiply(a, b)

# Timed runs (like timeit)
start = time.perf_counter()
for _ in range(parameters.n_repeats):
result = multiply(a, b)
elapsed_ms = (time.perf_counter() - start) / parameters.n_repeats * 1000

return TaskOutput(output={"result": result, "time_ms": elapsed_ms})


@matmul_task.evaluation()
async def run_evaluation(
task: dict, output: TaskOutput, context: TaskContext
) -> TaskResult:
expected = task["expected"]
actual = output.output["result"]
time_ms = output.output["time_ms"]

# Check correctness (within floating point tolerance)
correct = all(
abs(a_val - e_val) < 1e-6
for a_row, e_row in zip(actual, expected)
for a_val, e_val in zip(a_row, e_row)
)

# Score = time if correct, penalty if wrong (lower is better)
score = time_ms if correct else 999999.0

return TaskResult.from_task_output(
output,
score=score,
metrics={"time_ms": time_ms, "correct": 1.0 if correct else 0.0},
feedback=f"{'Correct' if correct else 'Wrong'}. Time: {time_ms:.2f}ms",
)
Loading