Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ Changes are grouped by software version. Entries under Unreleased describe work

### Added

- Pi as a CLI Base Agent (`pi`): the acting agent `agent.base: pi` and the `pi` Evolver run Pi 1.5's `--mode json`
in its own home, offline, with a model reference as Pi's `models.json` provider (the key as `$VARIABLE`); the
call's tools are an MCP server offered directly; a failed request fails the session although Pi exits 0. Pi takes
no roles and has no web search; `image_input: true` declares a bound model that takes images. `hermit deploy
--host pi` declares the adapter's tools `exposure: direct`, with a 120 s timeout.
- Models in sandboxes as Harbor's agents get theirs: each sandbox gets its models' key variables and provider hosts
(an isolated network becomes an allowlist) and forwards a model meter on the loopback; what a run keeps (the
learning material, the step records, the adapter) is scrubbed of key values (`hermit/redact.py`). The allowlist
Expand Down Expand Up @@ -152,6 +157,9 @@ Changes are grouped by software version. Entries under Unreleased describe work

### Fixed

- A deployed workspace's tool server (`.codex/config.toml`, `.mcp.json`, `.pi/mcp.json`) in a task-sandboxed
acting run crashed at startup, so the adapter's tools never loaded: its sandboxed Session loads no adapter in
the server's process, and the server now reads the manifest from the Session.
- A workspace agent's run failed after its session had answered when tidying the kept workspace could not read or
remove an empty mount point yet (`PermissionError` on `docs/root_1`: Docker Desktop can hold a bind mount's target
a moment after its container exits); the answer was scored as a pipeline failure. Tidying now leaves such a
Expand Down
10 changes: 6 additions & 4 deletions docs/framework/agent-layers.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ How a model takes steps. Layer 2 holds only the framework's agents:
| `react` | The framework's tool loop: call the model, run the tools it asks for, call it again |
| `codex` | The Codex CLI, working in a workspace |
| `claude` | The Claude Code CLI, working in a workspace |
| `pi` | The Pi CLI, working in a workspace (no roles, no web search) |

API, the only one Layer 3 sees:

Expand Down Expand Up @@ -80,7 +81,7 @@ none), Codex's own sandbox mode, the CLI's home, the time limit (the full list i
leaves the agent as it was. Running a task again when the provider could not serve it is Layer 3's: the workspace
is placed anew first.

Codex and Claude Code share one runner, `CliAgent`: the isolation, the home, the sign-in, the tool server and the
Codex, Claude Code and Pi share one runner, `CliAgent`: the isolation, the home, the sign-in, the tool server and the
process are the same for every CLI. Each CLI is a subclass whose hooks give what is its own: its command, its home,
and how its event stream is read (the reply, the trajectory, the usage, whether the provider served it, and what a
session that was not served met: `outcome`). A new CLI is
Expand All @@ -98,8 +99,8 @@ What the Base Agent is used for. Two kinds:
record).
- The **Evolver Agent** learns. Its API to the Trainer is `step(ctx)` and `finalize(ctx)`. It reads the acting
runs' trajectories and writes a new adapter, calling a Base Agent: `direct` for methods that decide every step in
their own code (GEPA, SkillOpt, ReHarness, Continual Harness), `codex` or `claude` for methods whose learner is an
agent (Meta-Harness Adapter, the `codex` and `claude` Evolvers). The run's model reaches an Evolver as
their own code (GEPA, SkillOpt, ReHarness, Continual Harness), `codex`, `claude` or `pi` for methods whose learner
is an agent (Meta-Harness Adapter, the `codex`, `claude` and `pi` Evolvers). The run's model reaches an Evolver as
`ctx.agent`, a `direct` Base Agent metered against the budget; `ask(ctx.agent, messages, max_tokens=...)` returns
the reply as the `llm` tool does.

Expand Down Expand Up @@ -140,7 +141,7 @@ Each Base Agent offers the tools to the model in its own way:
|---|---|---|
| `direct` | Their schemas in the API request | Layer 3, which then calls `direct` again |
| `react` | Their schemas in the API request | `react`, in its loop |
| `codex`, `claude` | The framework's tool server, over MCP (streamable HTTP) | The tool server |
| `codex`, `claude`, `pi` | The framework's tool server, over MCP (streamable HTTP) | The tool server |

The tool server (`hermit/agent/base/tool_server.py`) is started for the one call and stopped after it. It carries a
token in its URL, so that only the session it was started for can call it, and tells Codex to approve its tools
Expand Down Expand Up @@ -223,6 +224,7 @@ accepted; a key given in two layers is refused. On the command line a layer's se
| OfficeQA in direct chat | Acting Agent running SkillOpt's chat loop | `direct`, per turn |
| GEPA, SkillOpt, ReHarness, Continual Harness, OPRO | Evolver Agent | `direct` (`ctx.agent`); OPRO in OfficeQA: `codex` through `llm: {cli: codex}` |
| Meta-Harness Adapter, `codex` and `claude` Evolvers | Evolver Agent | `codex` or `claude` |
| `pi` Evolver | Evolver Agent | `pi` |
| RRSI Adapter | Evolver Agent: upstream's rules and roles, the proposer's prompt | `codex` or `claude` for the proposer, and the same, one call per upstream `generate`, for the analyst, digesters and critic |
| AHE Adapter | Evolver Agent: the Evolve Agent and the Agent Debugger | `codex` or `claude`, one session per step and per task |
| CL-Bench, ServeLearnBench | Acting Agent running the benchmark's loop | `direct`, per call, through the local endpoint |
Expand Down
2 changes: 1 addition & 1 deletion docs/framework/custom-evolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ You can reuse a launcher instead of implementing a new Python learning loop:
| `hermit.agent.evolver.agent:AgentEvolver` | Backend, prompt files, model selection, and host arguments. | The learner agent edits the working directory. |
| `hermit.agent.evolver.agent:CommandEvolver` | An external command and optional environment values. | The program edits the working directory and may write a result file. |

`AgentEvolver` supports `codex` and `claude`. Its parameters include `backend`, `prompt`, `resume_prompt`, `model`,
`AgentEvolver` supports `codex`, `claude` and `pi`. Its parameters include `backend`, `prompt`, `resume_prompt`, `model`,
`args`, and `home`. Prompt placeholders include the workspace paths, `message`, `epoch`, and `step`.
The bundled definitions are under `hermit/agent/evolver/methods/`.

Expand Down
2 changes: 1 addition & 1 deletion docs/framework/evolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ For selection guidance, setup, and the complete parameter defaults, use [Choose

| `evolver.name` | Method | Needs |
|---|---|---|
| `codex`, `claude` | A Codex or Claude Code agent edits the adapter from the learning material; `codex` on the `prompt-only@1.0` template is the [prompt-only](../methods/prompt-only.md) method. | The agent CLI |
| `codex`, `claude`, `pi` | A Codex, Claude Code or Pi agent edits the adapter from the learning material; `codex` on the `prompt-only@1.0` template is the [prompt-only](../methods/prompt-only.md) method. | The agent CLI |
| `gepa` | [GEPA](https://github.com/gepa-ai/gepa): one iteration per step. It reflects on the step's trajectories, keeps a child that does better on the same tasks, scores it on validation, and hands back the next parent from its Pareto front. | `llm`, `data.val`, `python -m pip install -e . --group gepa` |
| `skillopt` | [SkillOpt](https://github.com/microsoft/SkillOpt): one SkillOpt step per training step. It turns the step's trajectories into a few bounded edits under its learning rate (decaying when `total_steps` is set) and keeps them only if the validation score improves; the slow update and meta skill run at each epoch's end. | `llm`, `data.val`, `python -m pip install -e . --group skillopt` |
| `ace` | [ACE](https://github.com/ace-agent/ace): per rollout, a Reflector tags the playbook bullets the agent named and diagnoses the attempt (a wrong answer is run again with the reflection, up to `max_num_rounds`), and a Curator adds bullets; the playbook grows by deltas. See `docs/methods/ace.md`. | `llm`; `data.val` to keep the best validation playbook |
Expand Down
2 changes: 1 addition & 1 deletion docs/framework/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ agent:
| `agent.name` | Agent | Settings |
|---|---|---|
| `react` | a chat-completions tool-calling loop over the task's tools and the adapter's tools | `model`, `prompt`, `tools`, `user`, `max_turns`, `max_output_tokens`, `max_tokens`, `temperature`, `answer_tag`, `tool_result_chars`, `logs` |
| `codex`, `claude-code` | Codex or Claude Code run in a fresh workspace the adapter is deployed into | `model`, `login`, `effort`, `prompt`, `files`, `mounts`, `prepare`, `answer`, `collect`, `context_query`, `project_doc_max_bytes`, `args`, `env`, `price`, `timeout_s`, `retries`, `retry_wait_s`, `workspaces` |
| `codex`, `claude-code`, `pi` | Codex, Claude Code or Pi run in a fresh workspace the adapter is deployed into (Pi: no `login`, no roles; its project's `.pi/` is trusted for the session) | `model`, `login`, `effort`, `prompt`, `files`, `mounts`, `prepare`, `answer`, `collect`, `context_query`, `project_doc_max_bytes`, `args`, `env`, `price`, `timeout_s`, `retries`, `retry_wait_s`, `workspaces` |

### A coding-agent CLI as the acting agent

Expand Down
1 change: 1 addition & 0 deletions docs/get-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ never shown).
| Codex / Claude learner | Selected authenticated CLI and supported program-execution environment |
| MWM | Linux learner environment, Codex or Claude Code, evidence store, task deployment contract, model access |
| Acting and learning on a Claude subscription | Claude Code 2.1.248 or later, `claude setup-token`, Linux with bubblewrap for its sandboxes; see [Claude subscription](../guides/claude-subscription.md) |
| Pi acting agent or learner | The `pi` release binary on `PATH` (GitHub release `pi-linux-x64.tar.gz`, checked against its `SHA256SUMS`) and a model reference |
| Benchmark recipe | Its dataset, scorer, model settings, and environment; see [catalog](../recipes/index.md) |

Core installation and the deterministic tutorial work on macOS. The sandboxes (the acting agent's, the judge's, the
Expand Down
18 changes: 12 additions & 6 deletions docs/guides/model-backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ hermit train --config run.yaml model=vllm/Qwen/Qwen3-30B-A3B-Instruct-2507-FP8
| `agent.params.model` (or `agent.model`) with `agent.name: react` | the built-in tool-calling agent | chat completions |
| `agent.params.model` (or `agent.model`) with `agent.name: codex` / `claude-code` | the CLI acting agent | Responses API / Messages API |
| `evolver.params.model` of the `codex`, `claude` and `mwm` Evolvers | the learner's CLI session | Responses API / Messages API |
| `agent.params.model` with `agent.name: pi`, `evolver.params.model` of the `pi` Evolver | Pi | chat completions, else the Messages API, else the Responses API: the first the backend serves |
| `model` (top level) | the default for all of the above when they name none | |
| the examples' task agents (`agent.params.model`, or the launchers' `MW_MODEL`) | CL-Bench's litellm host, ServeLearnBench's loop, the SkillOpt rollout | chat completions |

Expand All @@ -36,6 +37,11 @@ extra_body}` still works for the chat-completions callers and names the endpoint
A reference's first segment is the backend; the rest is the model's id on it, with whatever slashes the backend
uses (`fireworks/accounts/fireworks/models/glm-5p3-flash`, `vllm/Qwen/Qwen3-30B-A3B-Instruct-2507-FP8`). A
backend may define aliases (`models: {qwen: Qwen/Qwen3-30B-A3B-Instruct-2507-FP8}`), so `vllm/qwen` works too.
For Pi a reference becomes its `models.json` provider `hermit`: the backend's URL, the key as `$VARIABLE` (Pi reads it
at each request, so no file holds the key) and the backend's price. The cost recorded follows the price (the agent's
own `price`, else the backend's), not Pi's own figure. Pi sends such a model text only; for a model that takes images
(a tool's result, such as a screenshot), set `image_input: true` in `agent.pi` or `evolver.pi`.

A string whose first segment is no backend's name is not a reference: for a Codex or Claude Code agent it is a
model of the CLI's own provider (`gpt-5.4`), as before. So a provider id that happens to start with a backend's
name (`openai/...`) is read as a reference to that backend.
Expand Down Expand Up @@ -93,12 +99,12 @@ lab-sglang: # a new one, like the built-in sglang at

## Dialects: what Codex and Claude Code need

The framework's own client, the react agent and the examples' task agents speak **chat completions**. The CLI
agents do not: **Codex speaks the OpenAI Responses API only** (`wire_api = "chat"` is rejected since Codex 0.95),
and **Claude Code speaks the Anthropic Messages API only**. A backend's `apis` says what it serves, and the
framework checks a model's dialect against its backend before a run starts: `hermit check` reports it,
`train` refuses to start on a mismatch, and `hermit backends check <ref>` sends one short request in each
dialect (and lists `GET /models`) so a wrong claim shows up before anything is spent.
The framework's own client, the react agent and the examples' task agents speak **chat completions**, and so does Pi
where the backend serves them. Codex and Claude Code do not: **Codex speaks the OpenAI Responses API only**
(`wire_api = "chat"` is rejected since Codex 0.95), and **Claude Code speaks the Anthropic Messages API only**. A
backend's `apis` says what it serves, and the framework checks a model's dialect against its backend before a run
starts: `hermit check` reports it, `train` refuses to start on a mismatch, and `hermit backends check <ref>` sends
one short request in each dialect (and lists `GET /models`) so a wrong claim shows up before anything is spent.

| Backend | chat | responses (Codex) | messages (Claude Code) |
|---|---|---|---|
Expand Down
11 changes: 6 additions & 5 deletions docs/methods/agent.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Codex and Claude agent learners
# Codex, Claude and Pi agent learners

Use `evolver.name: codex` or `claude` when a learner should inspect trajectories, use tools, and edit an adapter
directory over several actions. This is useful for skills, multiple files, and tool code that a single text rewrite
does not capture well. On the single-file prompt-only template, the Codex learner is the [prompt-only](prompt-only.md)
method.
Use `evolver.name: codex`, `claude` or `pi` when a learner should inspect trajectories, use tools, and edit an
adapter directory over several actions. This is useful for skills, multiple files, and tool code that a single text
rewrite does not capture well. The `pi` learner signs in through a model reference (`evolver.base: pi` with
`evolver.model: <backend>/<model>`, or `evolver.params.model`); it copies no login from `~/.pi/agent` (`home: []`).
On the single-file prompt-only template, the Codex learner is the [prompt-only](prompt-only.md) method.

## Requirements and setup

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ numbers alone may not distinguish unreleased changes.
| Local deterministic Quick Start | No model account, GPU, external dataset, or host CLI |
| Context-only workspace generation | macOS and Linux |
| Sandboxed learner programs | Linux with bubblewrap and permitted namespaces |
| Built-in methods | Prompt-only (the Codex learner on the prompt-only template), Codex, Claude, GEPA, SkillOpt, MWM, Harness², Continual Harness, ReHarness, Meta-Harness Adapter, ACE, AHE Adapter, RRSI Adapter, EvoSafeHarness, OPRO |
| Built-in methods | Prompt-only (the Codex learner on the prompt-only template), Codex, Claude, Pi, GEPA, SkillOpt, MWM, Harness², Continual Harness, ReHarness, Meta-Harness Adapter, ACE, AHE Adapter, RRSI Adapter, EvoSafeHarness, OPRO |
| Workspace deployment | Codex, Claude Code, and Pi |
| A subscription instead of an API key | Codex (`login: chatgpt`) and Claude Code (`login: claude`, CLI 2.1.248 or later, tested on 2.1.318), acting and learning; see [Claude subscription](../guides/claude-subscription.md) |
| Native plugin conversion | Claude Code, Codex, Pi, Hermes, with export restrictions |
Expand Down
Loading
Loading