# InferOptimal OpenEvolve tool

**Status:** Recommended for well-defined tasks with a reward that can be hill-climbed: a score you can compute for every candidate and want to raise.

Every harness measured side by side, on the same model: https://www.inferoptimal.com/tools/results

One of InferOptimal's swarm tools. A connected agent lists every agent tool, the subagent
tool included, with `list_agent_tools`.

Explicitly download, install, then run. Connecting an InferOptimal account or
endpoint never installs this tool. Requires Python 3.12+ and `make`; tested with
Python 3.12. Framework source and its direct dependencies are pinned in
`requirements.txt`; OpenEvolve commit is
`a1e9d91eecde612f0efc8e8e31f59b36998248c0`.

Install on the machine that owns the task files, with the InferOptimal subagent
tool's script (set that tool up first):

```sh
node ~/.inferoptimal/agents.mjs tool install openevolve
```

`node ~/.inferoptimal/agents.mjs guide openevolve` prints this guide with the
settings measured on your endpoint filled into the launch command. By hand, the
same install is:

```sh
mkdir -p ~/.inferoptimal/openevolve && cd ~/.inferoptimal/openevolve && curl -fsSLO https://www.inferoptimal.com/swarm/Makefile && make fetch install
```

From a source checkout, installation is `make -C swarm install`. The paired
environment is `swarm/.venv`, described by `swarm/requirements.txt`.

Use an existing InferOptimal inference endpoint and its key. This tool provisions
no hardware and creates no account. Put the endpoint key in a private text file
or the `INFEROPTIMAL_ENDPOINT_KEY` environment variable. Do not put it in a command
argument. An evaluator is local Python exposing `evaluate(program_path)` and
returning a metrics dictionary such as `{"combined_score": 0.8}`.

Every run needs an evaluator. Prefer a fixed, measurable one (tests, timings,
labelled data, a simulator). When the objective is a research question with
no fixed metric, such as a ruling to find across many documents, use the opt-in
[OpenResearch add-on](https://www.inferoptimal.com/openresearch/README.md): it
writes the seed brief and an `evaluator.py` for this tool, and its research
agents run through the InferOptimal subagent tool. This tool never installs or
starts it. Never let the proposing model grade its own candidates.

Launch one swarm:

```sh
~/.inferoptimal/openevolve/.venv/bin/python \
  ~/.inferoptimal/openevolve/inferoptimal_openevolve.py run \
  /absolute/path/initial_program.py /absolute/path/evaluator.py \
  --base-url https://YOUR-ENDPOINT.inferoptimal.com/v1 \
  --model YOUR-SERVED-MODEL \
  --key-file /absolute/private/path/endpoint-key.txt \
  --islands 2 --population-per-island 8 \
  --active-evaluations 4 --max-inflight 4 \
  --iterations 20 --temperature 1.0 --top-p 0.95 \
  --system-message-file /absolute/path/task.txt \
  --hardware-label YOUR-HARDWARE-IDENTITY \
  --output-dir /absolute/path/new-run-output
```

Defaults, each overridable:

- Plain OpenEvolve iterations: every request carries only the parent, its
  inspirations and evaluator feedback, with no conversation memory.
  `--agent-memory` (with `--agent-history full-resend|delta-append`) is opt-in.
  In measured runs, long agent conversations degraded on later turns while the
  same prompts sent statelessly stayed clean; the measured settings for
  your endpoint come from `node ~/.inferoptimal/agents.mjs guide openevolve`.
- SEARCH/REPLACE edits (`--diff-based`). `--full-rewrite` asks for whole programs
  instead, which costs about one program of output tokens per answer.
- Requests stream from the endpoint, so long generations are not cut by edge
  timeouts. `--max-tokens` defaults to 32768 and `--reasoning-effort` to `high`,
  sent as `chat_template_kwargs.reasoning_effort`, together with any
  `--chat-template-kwargs`, on every request: chat completions or Responses (which
  also gets `reasoning.effort`), and the token count that admits it. Which values a model accepts
  depends on its chat template; `node ~/.inferoptimal/agents.mjs guide openevolve`
  gives the value measured on your endpoint.
- `--temperature` / `--top-p` are sent on every request when given; omitted,
  OpenEvolve's own values are sent. `node ~/.inferoptimal/agents.mjs guide openevolve`
  gives the sampling measured on your endpoint.
- Prompt size: every prompt carries the parent plus `--num-top-programs`
  (OpenEvolve default 3) and `--num-diverse-programs` (default 2, the diverse
  programs and inspirations) whole programs, and up to `--max-artifact-bytes`
  (default 20480; 0 leaves them out) of evaluator output. With a large seed,
  `--num-top-programs 1 --num-diverse-programs 0` keeps prompts near one or two
  programs long.
- `--request-timeout` (default 1800 s) bounds one model request; `--eval-timeout`
  (default 300 s) bounds one evaluation. `--timeout` is a deprecated alias for both.
- `--system-message` or `--system-message-file` gives the task description to
  every iteration, so it need not live in the seed program's docstring.
- `--max-code-length` defaults to four times the initial program, at least 10000
  characters.
- `--max-inflight` is inference concurrency: simultaneous model requests, one per
  OpenEvolve worker. `--active-evaluations` is evaluator concurrency on this
  machine and is CPU-bound. They are independent: with more workers than
  evaluation slots, evaluations queue for a slot while requests keep flowing.
- `--usage-log` lines carry `looped`, `loop_reasoning`, `loop_content` and
  `search_replace` per generation. A reply counts as looped when a 2000-character
  window compresses below 5% with zlib or more than half the 4-word sequences in a
  200-word window repeat.

These numbers demonstrate syntax. They are not measured recommendations.
Islands hold evolving candidate programs. `population-per-island` sets the target
used to compute OpenEvolve's total population capacity; the framework's island
selection/migration rules determine actual membership. OpenEvolve runs
`max-inflight` process workers (or `active-evaluations`, when that is larger), and
the proxy caps simultaneous model requests at `max-inflight`, so the endpoint can be
kept at its useful inference concurrency. `active-evaluations` caps how many
evaluations run at once on this machine; the others wait for a slot. A hardware
label records caller input;
it does not establish a measured result.

The real framework uses OpenAI-compatible generation through a local loopback
proxy. The default remote protocol is chat completions. For a provider configured
for Responses, pass `--wire-api responses`; the proxy adapts the framework's chat
request to that same provider's `/responses` route and returns its final text to
OpenEvolve. It never switches endpoints, models or billing modes automatically.
Files, evaluators, candidate selection and checkpoints stay local;
prompts and generated candidates cross the existing remote inference API. The
loopback token is generated per run; the endpoint key is kept out of framework
configuration, run summaries and command output.

For every active generation, the tool uses existing `POST /box/v1/turn` events
`start`, `turn` and `end`, plus `POST /box/v1/beat` for long requests. After
registration, native `POST /v1/messages/count_tokens` counts the prompt before
inference. Prompt tokens plus the requested output budget must fit the manager's
`limit_tokens`; its separate compaction reserve is not available for generation.
The tool reports the counted prompt in a numeric `turn` and checks the returned
allocation again. Unsupported counting, invalid allocations and insufficient room
refuse generation explicitly; prompts are never silently truncated. This is
numeric cache admission. Without `--agent-memory` it keeps no conversations;
with it, compaction follows the manager's `compact` signal or the context cap. The box manager receives only
numeric usage and opaque session IDs.

The default manager address for a direct endpoint is its origin plus `/box`.
A managed `/optimized/v1` endpoint instead uses `/optimized/v1/box`. The managed
proxy accepts only authenticated `turn` and `beat` requests, namespaces session
IDs per managed session, and returns no global pool or other tenant's metadata.
Override the same-origin address with `--manager-base-url` if necessary.
If an endpoint does not expose a manager, inference continues and the run receipt
reports zero registrations. Optional registration is retried for each generation,
so a startup API bridge can hand off to an available GPU manager within one run.
No API conversation/cache is transferred by the tool. Add `--require-manager`
when manager participation is required; then inference is refused if registration
fails. Manager failure does not trigger hardware provisioning.

Stdout contains one JSON result. Logs go to stderr. The output directory contains
the best program, real OpenEvolve checkpoints/artifacts, and `inferoptimal-run.json`
with population settings, request counts, peak concurrency, counted admission
totals, provider-reported cached tokens (null when unavailable), and cleanup state.
Backend response counts use the managed endpoint's `X-InferOptimal-Backend`
header (`api-bridge`, `gpu`, or `unreported`); they do not infer a backend from
manager availability. Only a distinct managed-session count is retained, never
the session identifiers. The ordinary endpoint key/base remain the same across
a managed startup handoff. `--require-manager` refuses the API-only phase.
An inference failure never returns the endpoint's raw error text or key. Ctrl-C
requests framework shutdown and cache release; an in-flight HTTP request may take
up to `--request-timeout` seconds (default 1800) to finish. A release not confirmed by the
manager remains visible in the receipt and makes the run fail.

Resume a retained OpenEvolve checkpoint using `--checkpoint /path/to/checkpoint`
and a new `--output-dir`. Existing output directories are never overwritten.
Use the same task/evaluator/profile when comparing resumed or independent runs.

Official integration contracts:

- [OpenEvolve API](https://github.com/algorithmicsuperintelligence/openevolve/blob/a1e9d91eecde612f0efc8e8e31f59b36998248c0/openevolve/api.py)
- [Configuration](https://github.com/algorithmicsuperintelligence/openevolve/blob/a1e9d91eecde612f0efc8e8e31f59b36998248c0/openevolve/config.py)
- [OpenAI backend](https://github.com/algorithmicsuperintelligence/openevolve/blob/a1e9d91eecde612f0efc8e8e31f59b36998248c0/openevolve/llm/openai.py)
