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
3 changes: 0 additions & 3 deletions packages/nemo_platform/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,10 @@ nemo-deployments-plugin = [
nemo-eval-author-plugin = [
"pydantic>=2",
"harbor>=0.18",
"nooa>=0.0.9",
"nemo-experimentalist-plugin",
"nemo-insights-plugin",
"nemo-platform-plugin",
"pyyaml>=6.0.3",
"tomlkit>=0.13.3",
]

# Generated from [tool.bundle-package]; do not edit by hand.
Expand Down Expand Up @@ -342,7 +340,6 @@ nemo-experimentalist-plugin = [
"protobuf>=6.0.0",
"nooa>=0.0.9",
"pyyaml>=6.0.3",
"nemo-eval-author-plugin",
"nemo-insights-plugin",
"nemo-platform-plugin",
"tomlkit>=0.13.3",
Expand Down
62 changes: 13 additions & 49 deletions plugins/nemo-eval-author/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,24 @@

# NeMo Eval Author Plugin

Library-only plugin that owns the Eval Author agent (`eval_author/`).
Owns the `nemo agents eval-author` command group, registered under `nemo.cli.agents` and
mounted by the agents plugin. `discover` is implemented; `audit`, `propose`, `run`, and
`doctor` are placeholders.

## Direction of travel

**Eval Author is meant to become standalone, with nothing imported from
Experimentalist.** Prefer duplicating a helper over sharing one, even when sharing
looks tidier.
Use `discover` only with a trusted repository, because importing an agent runs
module top-level code.

Right now the two packages depend on each other:
The Eval Author agent moved into the Experimentalist plugin, at
[`nemo_experimentalist_plugin.eval_author`](../nemo-experimentalist/src/nemo_experimentalist_plugin/eval_author/README.md).
Experimentalist insight mode is its only caller, so the agent sits beside the evaluator,
staging, and trace helpers it depends on.

| Arrow | Status | Why |
| --- | --- | --- |
| Experimentalist → Eval Author | permanent | insight mode imports `EvalAuthor` and `EvalAuthorConfig` at module scope |
| Eval Author → Experimentalist | temporary | still borrows evaluator/Harbor, staging, trace, tools, cache, backend |
## Direction of travel

[`tests/test_plugin_boundary.py`](tests/test_plugin_boundary.py) pins the second list
so it can only shrink, and names what each remaining import is still for. `uv`
resolves the current cycle; install both packages with:
The dependency is one arrow. `discovery/run.py` borrows `make_client` from Experimentalist,
and Experimentalist imports nothing from here, so there is no package cycle for `uv` to
resolve. Install both plugins with:

```bash
uv sync --group experimentalist
```

## Public API

```python
from nemo_eval_author_plugin.eval_author.agent import EvalAuthor, build_eval_author_agent
from nemo_eval_author_plugin.eval_author.models import EvalAuthorConfig, EvalAuthorResult
from nemo_eval_author_plugin.eval_author.run import run_eval_author

# Still borrowed from Experimentalist, and on the way out. Treat these as Eval Author's
# own types once they move; do not build new code on the Experimentalist paths.
from nemo_experimentalist_plugin.entities import Dataset, DatasetRef
from nemo_experimentalist_plugin.experimentalist.components.dataset_staging import stage_eval_author_inputs
from nemo_experimentalist_plugin.experimentalist.components.trace_analyzer import TraceAnalyzer
from nemo_experimentalist_plugin.experimentalist.components.trace_explorer import TraceExplorer
```

## Agent models

Run `nemo setup` and select the default and fast models for the active Platform
context. Eval Author uses the default model for authoring and the fast model for
summarization. Press Enter at the fast-model prompt to reuse the default model.

The selections are workspace-qualified Platform Model Entity IDs. The Platform
routes each request to the provider registered for that entity and reads its
credential from Platform Secrets; Eval Author does not accept separate provider,
endpoint, key, or model environment variables.

For non-interactive and isolated environments, `NEMO_DEFAULT_MODEL` and
`NEMO_FAST_MODEL` can override the stored selections. Values must still use
`workspace/model-name` and refer to Model Entities on the target Platform.

A `nemo agents eval-author` CLI is registered under `nemo.cli.agents` and
mounted by the agents plugin. `discover` is implemented; `audit`, `propose`,
`run`, and `doctor` remain placeholders. The library runner already uses the
configured Platform model pair.
4 changes: 1 addition & 3 deletions plugins/nemo-eval-author/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@
[project]
name = "nemo-eval-author-plugin"
version = "0.1.0"
description = "Eval Author agent for NeMo Platform (hard-depends on Experimentalist for evaluator/trace helpers)."
description = "Eval Author commands for NeMo Platform (borrows the Experimentalist platform client)."
requires-python = ">=3.12,<3.14"
dependencies = [
"pydantic>=2",
# Harbor 0.18 provides the discovery APIs used by this plugin.
"harbor>=0.18",
"nooa>=0.0.9",
"nemo-experimentalist-plugin",
"nemo-insights-plugin",
"nemo-platform",
"nemo-platform-plugin",
"pyyaml>=6.0.3",
"tomlkit>=0.13.3",
]

[project.entry-points."nemo.cli.agents"]
Expand Down
92 changes: 0 additions & 92 deletions plugins/nemo-eval-author/tests/test_plugin_boundary.py

This file was deleted.

52 changes: 31 additions & 21 deletions plugins/nemo-experimentalist/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,27 @@ Inherited from the NeMo Platform monorepo that now hosts this plugin:

## Active migrations

### 2026-08-19: Eval Author agent moved back into this plugin

`nemo_experimentalist_plugin.eval_author` owns the Eval Author agent again, along with
`eval_author/traces.py`. The 2026-07-28 extraction aimed at a standalone Eval Author
plugin. That goal is retired: the customer-facing path is a skill rather than a plugin
install, and insight mode was the agent's only caller.

**The dependency is one arrow, and it points out of the Eval Author plugin.**
Experimentalist imports nothing from `nemo-eval-author-plugin`, so the package cycle that
`uv` had to resolve is gone.

- The agent's borrows of the evaluator, staging, trace, tools, and reporting helpers are
intra-package imports. The Eval Author plugin's boundary ratchet existed to drive those
ten borrows to zero, so it went away with them.
- `tests/test_contract_dependency.py` asserts that this plugin never declares
`nemo-eval-author-plugin` as a dependency, which is what keeps the cycle broken.
- `plugins/nemo-eval-author/` keeps the `nemo agents eval-author` command group and its
`discovery/` package, whose one remaining borrow is `make_client`.
- Agent tests live in `tests/eval_author/`. This plugin's `conftest.py` already covers the
isolation those tests need, so the Eval Author copy went away.

### 2026-07-31: Command group nested under `nemo agents`

The only path is `nemo agents experimentalist <verb>`. `ExperimentalistCLI` is
Expand All @@ -25,28 +46,17 @@ Analyst and Eval Author follow the same rule: `nemo agents analyst run` (was
`ctx.command_path` over a hardcoded path when a message quotes the command back
to the user.

### 2026-07-28: Eval Author extracted to its own plugin, heading for standalone

`plugins/nemo-eval-author/` (`nemo-eval-author-plugin`) owns the Eval Author agent package
(`eval_author/`).
### 2026-07-28: Eval Author extracted to its own plugin, heading for standalone (superseded)

**The target is one arrow: Experimentalist → Eval Author.** Eval Author is meant to stop
depending on Experimentalist entirely, even where that means duplicating code. Today the
arrow points both ways:
Superseded by the 2026-08-19 entry, which moved the agent back.

- Experimentalist → Eval Author is permanent. Insight mode imports `EvalAuthor` in
`components/loop.py` and `EvalAuthorConfig` in `resolve.py`, both at module scope, so
the dependency is declared in `pyproject.toml`.
- Eval Author → Experimentalist is temporary. It still borrows the evaluator/Harbor
abstractions, dataset staging, trace analyzer/explorer, `GuardedShellTools`, the cache,
and the backend factory.
`plugins/nemo-eval-author/` took ownership of the `eval_author/` package, targeting a
standalone plugin that imported nothing from Experimentalist. Both arrows pointed at each
other for the duration, and `uv` resolved the cycle.

`plugins/nemo-eval-author/tests/test_plugin_boundary.py` pins that second list so it can
only shrink. **Do not share Eval Author implementation helpers with Experimentalist.**
The Platform-owned model client integration is intentionally different: both plugins use
`nemo_platform_plugin.nooa_model_client` so provider routing, Platform authentication,
and configured model selection have one owner outside either plugin. `uv` resolves the
remaining package cycle; install both with `uv sync --group experimentalist`.
One rule from that entry still holds: both plugins use
`nemo_platform_plugin.nooa_model_client`, so provider routing, Platform authentication,
and configured model selection have one owner outside either plugin.

### 2026-07-24: Optimizer renamed to Experimentalist

Expand Down Expand Up @@ -87,7 +97,7 @@ including components registered by a separately installed package.
The Curator agent was renamed directly to Eval Author in ASE-643. This is a
breaking rename with no compatibility aliases or migration layer:

- `nemo_experimentalist_plugin.curator` → `nemo_eval_author_plugin.eval_author` (was `nemo_experimentalist_plugin.eval_author` before extraction)
- `nemo_experimentalist_plugin.curator` → `nemo_experimentalist_plugin.eval_author` (briefly `nemo_eval_author_plugin.eval_author` while the agent had its own plugin)
- `Curator`, `CuratorConfig`, and `CuratorResult` → `EvalAuthor`,
`EvalAuthorConfig`, and `EvalAuthorResult`
- `run_curator(...)` and `build_curator_agent(...)` →
Expand All @@ -112,7 +122,7 @@ instead of restoring Curator imports, configuration, or aliases. The obsolete
- `nooa` comes from PyPI. This plugin's `pyproject.toml` declares the floor
(`nooa>=0.0.9`), which is the first release carrying the callable
`@strategy(llm=...)` support the components depend on. When raising the floor,
move it in this plugin, `nemo-insights`, `nemo-eval-author`, and
move it in this plugin, `nemo-insights`, and
`examples/tau3-nooa-agent/pyproject.toml`, update the tag quoted in
`framework-skills/nooa/SKILL.md`, and relock both lock files together. Keep the
Platform-supplied Insights plugin separate.
Expand Down
7 changes: 5 additions & 2 deletions plugins/nemo-experimentalist/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ single leader, so complementary strengths stay alive across rounds.
failure pattern inferred from traces — that the Experimentalist optimizes
against. Run `nemo agents analyst run` first. The Experimentalist does not
analyze traces or host an Insight API.
- [NeMo Eval Author](../nemo-eval-author/README.md) builds the
Insight-specific evaluation suite, invoked automatically in Insight mode.
- [Eval Author](src/nemo_experimentalist_plugin/eval_author/README.md) builds the
Insight-specific evaluation suite, and Insight mode invokes it automatically. It
ships inside this plugin; the separate
[Eval Author plugin](../nemo-eval-author/README.md) owns the
`nemo agents eval-author` commands.
- **Harbor** runs the task containers that score every candidate.
- **NeMo Experiments** mirrors each run and its candidates as an experiment
group, so the lineage is visible in Studio. Structure only — rewards and
Expand Down
1 change: 0 additions & 1 deletion plugins/nemo-experimentalist/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ dependencies = [
"protobuf>=6.0.0",
"nooa>=0.0.9",
"pyyaml>=6.0.3",
"nemo-eval-author-plugin",
"nemo-insights-plugin",
"nemo-platform",
"nemo-platform-plugin",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
from pathlib import Path
from typing import Any, Self

from nemo_eval_author_plugin.eval_author.models import EvalAuthorConfig
from nemo_experimentalist_plugin.entities import MetricTarget
from nemo_experimentalist_plugin.eval_author.models import EvalAuthorConfig
from nemo_experimentalist_plugin.experimentalist.components.models import ( # noqa: F401 - re-exported
has_metric_dimensions,
pareto_objectives,
Expand Down
Loading
Loading