fix: forward per-run agent env (--ae) to the optimizer's harbor run#48
fix: forward per-run agent env (--ae) to the optimizer's harbor run#48shehabyasser-scale wants to merge 1 commit into
Conversation
Add a `agent_env` build-config field and render it as harbor `--ae KEY=VALUE` on the optimizer's `harbor run`, so env vars reach the optimizer agent's own setup/install exec. Root cause: `run_command` in vero/src/vero/harbor/cli.py builds the optimizer's harbor command from a fixed list + `-m model` + the click `extra` passthrough and never reads any per-run agent env. `extra_harbor_args` was the only env-adjacent knob, but it is compiled solely into the eval sub-run (compiler.py writes it into serve.json, consumed by backend.py), a different `harbor run` with a different agent, so it never reaches the optimizer agent's install shell. Harbor's `--ae/--agent-env` flag populates the agent's extra_env, which harbor injects into the agent's setup/install exec via scoped_exec_env, so rendering `--ae` here is the supported channel. Motivation: there was no way to set e.g. UV_TOOL_BIN_DIR for the optimizer agent's install on a non-root sandbox (so `uv tool install` doesn't try to symlink into root-owned /usr/local/bin). Passing it via extra_harbor_args silently did nothing. `extra_harbor_args` is intentionally left unchanged to avoid overloading its meaning (eval sub-run args). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The SimpleNamespace config stubs in test_v05_harbor_http.py predate #48's agent_env field; run_command now reads config.agent_env, so give the stubs the same defaulted-empty field the real HarborBuildConfig has.
|
Landed on One small follow-up from consolidating it into the SSoT branch: two pre-existing Note it's a no-op for the current benchmark configs (none declare |
Root cause
When vero runs the optimizer it shells out to
uvx ... harbor runto launch the coding agent (codex / mini-swe-agent). There was no supported way to pass environment variables into that optimizer agent's setup/install shell from the build config.run_commandinvero/src/vero/harbor/cli.pybuilds the optimizer's harbor command from a fixed list +-m model+ the clickextrapassthrough (@click.argument("extra", nargs=-1)). It never reads any per-run agent env.config.extra_harbor_args(the only env-adjacent knob) is compiled solely into the evaluation sub-run the sidecar fires: the compiler writes it intoserve.json(vero/src/vero/harbor/build/compiler.py), consumed by the sidecar backend (vero/src/vero/harbor/backend.py). That is a differentharbor runwith a different agent, so args there never reach the optimizer agent's install shell.--ae/--agent-envflag (cli/trials.py) populates the agent'sextra_env, and harbor injects that env into the agent's setup/install exec by wrappinginstall()inscoped_exec_env(agent.extra_env)(trial/trial.py). So if vero rendered--ae KEY=VALUEonto the optimizer command, it would work; it just never did.Concrete motivation
There was no way to set e.g.
UV_TOOL_BIN_DIRfor the optimizer agent's install (needed on non-root sandboxes souv tool installdoesn't try to symlink into root-owned/usr/local/bin). Passing it viaextra_harbor_argssilently did nothing (wrong sub-run).Fix
agent_env: dict[str, str] = {}onHarborBuildConfig(alongsideextra_harbor_args), documented as "environment variables injected into the optimizer agent's shell (setup/install and run), rendered as harbor--ae KEY=VALUE".run_command, after appending-m modeland before theextrapassthrough, renderconfig.agent_envas repeated--ae KEY=VALUEargs, sorted by key for a deterministic command line.configis already in scope inrun_command, so no threading was needed.tests/test_v05_harbor_build.pyassertingrun_commandwithagent_env={"UV_TOOL_BIN_DIR": "/home/agent/.local/bin"}produces--ae UV_TOOL_BIN_DIR=/home/agent/.local/binon the harbor command.extra_harbor_argsis intentionally left unchanged to avoid overloading its meaning (it means "eval sub-run args"). This keeps the two concerns cleanly separate.Base branch note
This targets
pr2-add-verorather thanmain: the redesigned VeRO harbor code (src/vero/harbor/cli.py,build/config.py,build/compiler.py,backend.py) is introduced by PR #45 (pr2-add-vero) and does not exist onmainyet. The bug lives entirely in that code.Testing
tests/test_v05_harbor_build.py::test_run_command_forwards_agent_env_as_harbor_ae.tests/test_v05_harbor_build.pyis green (21 passed, 4 skipped for theharness-engineering-benchgate). Two secret-check tests only fail whenOPENAI_API_KEY/OPENAI_BASE_URLare unset; that is pre-existing on the base branch and unrelated to this change.ruff checkpasses on all three changed files. Env pinned to Python 3.12 (3.14 fails to build litellm/pyo3, see PR fix: cap requires-python <3.14 so uv can't pick a Python that fails to build litellm/pyo3 #47).🤖 Generated with Claude Code
Greptile Summary
This PR adds a dedicated
agent_env: dict[str, str]field toHarborBuildConfigand renders it as repeated--ae KEY=VALUEargs on the optimizer'sharbor runcommand, fixing a gap where there was no supported channel to inject environment variables (e.g.UV_TOOL_BIN_DIR) into the optimizer agent's setup/install shell.build/config.py: Adds theagent_envfield, clearly documented as distinct fromextra_harbor_args(eval sub-run) andtask_environment, with adefault_factory=dictdefault so existing configs are unaffected.cli.py: Inrun_command, iteratesconfig.agent_envsorted by key and extends the harbor command with--ae KEY=VALUEpairs, placed before theextrapassthrough so CLI-provided args can override them.test_v05_harbor_build.py: Adds a focused integration-style test monkeypatchingsubprocess.runandcompile_harbor_taskto verify the correct--aeargs appear in sorted order.Confidence Score: 5/5
Safe to merge — the change is additive, backward-compatible (default empty dict), and correctly threaded through an already-available config reference in run_command.
The addition is minimal: a new optional field on the config dataclass and a sorted loop in run_command that produces no output when agent_env is empty. Subprocess invocation uses a list (not a shell string), so values with spaces or special characters are passed safely. The test covers both the presence and the sort order of the generated args. No existing behavior is changed.
No files require special attention.
Important Files Changed
agent_env: dict[str, str]field with clear doc comment anddefault_factory=dict; backward-compatible and well-scoped.config.agent_envas--ae KEY=VALUEargs in sorted key order before theextrapassthrough; placement and logic are correct.--aeargs appear in the harbor command in sorted key order; assertions are correct for the chosen test values.Sequence Diagram
sequenceDiagram participant User participant CLI as vero harbor run (cli.py) participant Config as HarborBuildConfig (config.py) participant Harbor as harbor run (optimizer agent) participant Sidecar as eval sub-run (harbor sidecar) User->>CLI: vero harbor run --config build.yaml CLI->>Config: load_harbor_build_config() Config-->>CLI: config (incl. agent_env, extra_harbor_args) CLI->>CLI: build command list note over CLI: append -m model note over CLI: append --ae KEY=VALUE (from agent_env, sorted) note over CLI: append extra passthrough args CLI->>Harbor: "subprocess.run([uvx, harbor, run, ..., --ae KEY=VALUE])" Harbor->>Harbor: scoped_exec_env(agent.extra_env) on install/setup note over Harbor: agent_env vars available here Harbor->>Sidecar: launch eval sub-run (from serve.json) note over Sidecar: extra_harbor_args flow here (separate channel)Reviews (1): Last reviewed commit: "fix: forward per-run agent env (--ae) to..." | Re-trigger Greptile