Skip to content

feat(agents): add the Hermes CLI agent harness - #87

Open
eugeneng04 wants to merge 7 commits into
kubernetes-sigs:mainfrom
eugeneng04:feat/agents-hermes-harness
Open

feat(agents): add the Hermes CLI agent harness#87
eugeneng04 wants to merge 7 commits into
kubernetes-sigs:mainfrom
eugeneng04:feat/agents-hermes-harness

Conversation

@eugeneng04

@eugeneng04 eugeneng04 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What

Adds a hermes CLI agent harness, ported from gke-labs/devops-bench#178 and rewired onto this repo's current interfaces.

Hermes (NousResearch/hermes-agent) is driven as a subprocess; everything the run needs is laid down in a run-scoped $HERMES_HOME so a benchmark run never reads or writes the developer's ~/.hermes.

How capabilities are wired

Capability Channel
MCP servers mcp_servers entries in $HERMES_HOME/config.yaml (plus KUBECONFIG passed through to each server's env)
Skills materialized to $HERMES_HOME/skills/<name>/SKILL.md
Rules prepended to the prompt — hermes chat has no system-prompt flag
Model auth config.api_key exported to the env vars the resolved ProviderSpec names

HERMES_HOME is <workspace>/.hermes, so hermes still runs with cwd set to the harness workspace (relative paths in a task resolve where the harness expects) while its config and session DB stay in a single subdirectory instead of scattering across the artifact diff.

Token buckets

Trajectory and usage are read back from the run's SQLite state.db. The sessions columns map onto the canonical buckets from devops_bench.agents.result:

sessions column bucket
input_tokens input
cache_read_tokens cached
cache_write_tokens cache_write
reasoning_tokens reasoning
output_tokens output
total (sum of the reported buckets)

Counts are summed across all session rows, since the DB is run-scoped and a run may write more than one. Unreported buckets stay None rather than becoming a fabricated 0 — a missing DB, an older schema without the token columns, or any read failure all yield all-None.

extract_tokens_from_db opens the DB read-only (mode=ro URI) so a live state.db is never locked.

Testing

46 unit tests in tests/unit/agents/test_agents_cli_hermes.py covering registration, provider/model argv mapping, config generation and merge, skills/MCP materialization, the four _execute exit paths (success, non-zero exit, timeout, missing binary), trajectory pairing and its malformed-input paths, and every token bucket. Two guards worth calling out:

  • test_tokens_fill_every_canonical_bucket fails if TOKEN_BUCKETS gains a bucket this parser skips.
  • test_tokens_reach_the_result_row_unchanged runs the parser output through normalize_tokens, so a renamed bucket fails loudly here instead of silently reading None on the dashboard row.

Full suite: 1227 passed. ruff check and ruff format clean.

Notes

  • The token mapping assumes hermes normalizes provider usage to the canonical split (input excluding cache reads, output excluding reasoning — the Anthropic convention its column names mirror). Hermes is multi-provider; if it instead stores provider-native usage on some backends, total would double-count there. Flagged in a comment in parsing.py; unverified against a live run.
  • The upstream PR's docs changes are dropped — neither target file exists in this repo.

Summary by CodeRabbit

  • New Features

    • Added support for running evaluations with the Hermes CLI agent.
    • Added provider-aware configuration and validation for Hermes.
    • Added isolated execution with configurable credentials, MCP servers, skills, and prompt rules.
    • Added token usage and execution trajectory reporting.
    • Registered Hermes in the default agent selection.
  • Bug Fixes

    • Improved MCP environment isolation for CLI agents, including cloud configuration settings.
    • Ensured Hermes runs use fresh evaluation configuration and reliable provider validation.
  • Tests

    • Expanded coverage for execution, configuration, error handling, token usage, and trajectory parsing.

Wraps the `hermes` binary as a first-class harness registered under the
`hermes` key, so the benchmark can run against Hermes with the same
capability wiring (MCP, skills, rules) and result contract as the other
CLI harnesses.

- Runs `hermes chat -q` in a run-scoped `$HERMES_HOME`, so config.yaml,
  .env and the state.db session store never leak into the user's
  ~/.hermes; `inherit_user_config` opts back into the ambient state.
- Maps the provider onto the CLI's `--provider` backend via the shared
  `resolve_provider`, with the Vertex transport named `vertex`.
- Reads the trajectory and token usage back from the run's SQLite
  state.db, mapping the `sessions` token columns onto the canonical
  TOKEN_BUCKETS (cache reads -> `cached`, cache writes -> `cache_write`).
  Every failure path yields all-None buckets rather than a fake 0.

Signed-off-by: Eugene Ng <ngeugene@google.com>
@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: eugeneng04
Once this PR has been reviewed and has the lgtm label, please assign janetkuo for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow
kubernetes-prow Bot requested a review from janetkuo August 11, 2026 18:36
@kubernetes-prow kubernetes-prow Bot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 11, 2026
@kubernetes-prow

Copy link
Copy Markdown

Hi @eugeneng04. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kubernetes-prow kubernetes-prow Bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 24 minutes.

View limit details

Limit details: You’ve used the included review currently available.

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 080ce82b-e076-4663-b54a-3a08c569877b

📥 Commits

Reviewing files that changed from the base of the PR and between 40f2faf and a6a8f22.

📒 Files selected for processing (4)
  • devops_bench/agents/cli/hermes/agent.py
  • devops_bench/agents/shared/cli_capabilities.py
  • devops_bench/core/model_providers.py
  • devops_bench/core/run_env.py
📝 Walkthrough

Walkthrough

Added a builtin Hermes CLI agent with isolated run state, provider metadata, shared MCP and prompt handling, timeout support, and SQLite parsing for trajectories and token usage.

Changes

Hermes CLI agent

Layer / File(s) Summary
Provider metadata and shared CLI capabilities
devops_bench/core/model_providers.py, devops_bench/agents/shared/cli_capabilities.py, docs/how-to/add-a-model-provider.md, tests/unit/agents/shared/test_cli_capabilities.py, tests/unit/models/test_models_base.py
ProviderSpec now defines Hermes provider names. Shared helpers resolve MCP isolation variables and prepend granted rules to prompts. Documentation and tests cover the new contract.
Hermes execution harness and configuration
devops_bench/agents/cli/hermes/__init__.py, devops_bench/agents/cli/hermes/agent.py, tests/unit/agents/test_agents_cli_hermes.py
The package exports the agent and parsers. HermesAgent creates fresh configuration, disables repo-local skill discovery, validates providers, forwards isolated MCP variables, runs hermes chat, handles failures and timeouts, and returns parsed results.
Hermes state parsing
devops_bench/agents/cli/hermes/parsing.py, tests/unit/agents/test_agents_cli_hermes.py
SQLite parsers aggregate token usage across sessions and extract ordered tool-call trajectories. They normalize arguments, match responses, preserve orphaned results, and report malformed or unreadable state.
Builtin and OpenClaw integration
devops_bench/evalharness/default.py, devops_bench/agents/cli/openclaw/agent.py, tests/unit/agents/test_agents_cli_openclaw.py
The default registry discovers Hermes. OpenClaw uses the shared MCP environment and prompt rule helpers, including both supported isolation variables.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🔵 Low · up to 40f2f

Low risk: the new CLI harness is mergeable with explicit owner follow-up because existing provider-spec callers may break and MCP child processes may not receive configured isolation settings; the remaining concerns are limited to documentation and code organization.

Suggested reviewers: janetkuo, richackard

Sequence Diagram(s)

sequenceDiagram
  participant AgentHarness
  participant HermesAgent
  participant HermesCLI
  participant HermesSQLite
  AgentHarness->>HermesAgent: execute prompt and workspace
  HermesAgent->>HermesCLI: run hermes chat with isolated configuration
  HermesCLI-->>HermesSQLite: write session and message state
  HermesAgent->>HermesSQLite: parse trajectory and tokens
  HermesAgent-->>AgentHarness: return execution result and metadata
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.70% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 92 functions across 9 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding the Hermes CLI agent harness.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 58.70% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 92 functions across 9 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@janetkuo janetkuo added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
devops_bench/agents/cli/hermes/parsing.py (1)

47-49: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Optional: build the read-only URI with escaping.

f"file:{db_path}?mode=ro" breaks if the path contains ? or #. Run directories are harness-generated today, so this is defensive only.

♻️ Proposed hardening
+from urllib.parse import quote
+
 def _connect_ro(db_path: Path) -> sqlite3.Connection:
     """Open ``db_path`` read-only, so a live ``state.db`` is never locked."""
-    return sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
+    return sqlite3.connect(f"file:{quote(str(db_path))}?mode=ro", uri=True)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devops_bench/agents/cli/hermes/parsing.py` around lines 47 - 49, Update
_connect_ro to construct the SQLite read-only URI with proper path escaping,
preserving the existing mode=ro and uri=True behavior so db_path values
containing ? or # remain valid.
devops_bench/agents/cli/hermes/agent.py (1)

216-216: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: format the timeout seconds for the error message.

timeout_sec defaults to 600.0, so the default run reports "hermes agent timed out after 600.0s". Use {self.config.timeout_sec:g} for "600s".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devops_bench/agents/cli/hermes/agent.py` at line 216, Update the timeout
error construction in the Hermes agent flow to format self.config.timeout_sec
with general numeric formatting, so whole-number defaults such as 600.0 appear
as 600 while preserving meaningful fractional values.
tests/unit/agents/test_agents_cli_hermes.py (1)

74-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Annotate the test helpers and the fake_run stubs.

The test functions carry -> None, but the helpers and mocks do not. Add annotations to _insert_session, _insert_message, _seed_state_db, mock_exists, and every fake_run signature. The fake_run stubs stand in for devops_bench.core.subprocess.run, so typed parameters also catch a future signature change at review time.

♻️ Proposed annotations
-def _insert_session(path: Path, session_id: str, *counts) -> None:
+def _insert_session(path: Path, session_id: str, *counts: int | None) -> None:
-def _insert_message(path: Path, session_id: str, role: str, **fields) -> None:
+def _insert_message(path: Path, session_id: str, role: str, **fields: str | None) -> None:
-def _seed_state_db(home: Path, *, counts=(2748, 11267, 152, 334987, 12000)) -> None:
+def _seed_state_db(
+    home: Path, *, counts: tuple[int, ...] = (2748, 11267, 152, 334987, 12000)
+) -> None:

As per path instructions: "Ensure test functions have proper type annotations and clean structure."

Also applies to: 256-259

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/agents/test_agents_cli_hermes.py` around lines 74 - 96, Annotate
the test helpers and stubs with explicit return and parameter types: update
_insert_session, _insert_message, _seed_state_db, mock_exists, and every
fake_run signature. Type each fake_run parameter according to the
subprocess.run-compatible interface so future signature changes are detected,
while preserving the existing test behavior and structure.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@devops_bench/agents/cli/hermes/agent.py`:
- Around line 142-163: Validate the result loaded by _yaml.load in
_prepare_config before using mapping operations: retain it only when it is a
mapping, otherwise replace it with an empty mapping. Ensure seeded list or
scalar config.yaml content still allows MCP server merging and writes a valid
mapping, and add coverage for a YAML list such as “- a\n- b\n”.
- Around line 20-23: Update the module docstring’s “State isolation” description
to reflect that _execute() creates <workspace>/.hermes after snapshotting,
causing config.yaml and state.db to be collected under generated_files/, and
that inherit_user_config=True also copies SOUL.md; remove the inaccurate claim
that these files stay out of collected artifacts.

In `@devops_bench/agents/cli/hermes/parsing.py`:
- Around line 27-44: The _SESSION_TOKEN_COLUMNS mapping currently assigns
output_tokens directly to the output bucket while reasoning_tokens is also
counted separately. Update the parsing logic using _SESSION_TOKEN_COLUMNS so
visible output subtracts reasoning_tokens from output_tokens, or reuse Hermes’s
prompt-plus-completion total, ensuring total does not double-count reasoning
tokens.

---

Nitpick comments:
In `@devops_bench/agents/cli/hermes/agent.py`:
- Line 216: Update the timeout error construction in the Hermes agent flow to
format self.config.timeout_sec with general numeric formatting, so whole-number
defaults such as 600.0 appear as 600 while preserving meaningful fractional
values.

In `@devops_bench/agents/cli/hermes/parsing.py`:
- Around line 47-49: Update _connect_ro to construct the SQLite read-only URI
with proper path escaping, preserving the existing mode=ro and uri=True behavior
so db_path values containing ? or # remain valid.

In `@tests/unit/agents/test_agents_cli_hermes.py`:
- Around line 74-96: Annotate the test helpers and stubs with explicit return
and parameter types: update _insert_session, _insert_message, _seed_state_db,
mock_exists, and every fake_run signature. Type each fake_run parameter
according to the subprocess.run-compatible interface so future signature changes
are detected, while preserving the existing test behavior and structure.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f0fc2e0-1876-4c1f-a8b4-f887e7fc4458

📥 Commits

Reviewing files that changed from the base of the PR and between 4670d76 and d80fc8c.

📒 Files selected for processing (5)
  • devops_bench/agents/cli/hermes/__init__.py
  • devops_bench/agents/cli/hermes/agent.py
  • devops_bench/agents/cli/hermes/parsing.py
  • devops_bench/evalharness/default.py
  • tests/unit/agents/test_agents_cli_hermes.py

Comment thread devops_bench/agents/cli/hermes/agent.py Outdated
Comment thread devops_bench/agents/cli/hermes/agent.py Outdated
Comment thread devops_bench/agents/cli/hermes/parsing.py
Hermes stores output_tokens as the provider's full completion count with
reasoning_tokens as a subset of it, while the canonical output bucket
excludes reasoning. Subtract it out so total counts reasoning once and
matches Hermes's own prompt-plus-completion figure.

Also from PR review:
- ignore a seeded config.yaml that parses to a non-mapping instead of
  aborting the run on the merge
- percent-encode the state.db path in the read-only SQLite URI
- correct the module docstring's state-isolation claim
- format the timeout seconds with :g
- annotate the test helpers and subprocess stubs

Signed-off-by: Eugene Ng <ngeugene@google.com>
@eugeneng04

Copy link
Copy Markdown
Contributor Author

Thanks — addressed all six in 6b9daf5.

parsing.py — reasoning double-count. Real bug, and the most important one here. Confirmed against NousResearch/hermes-agent@main:agent/usage_pricing.py: CanonicalUsage.total_tokens is prompt_tokens + output_tokens, where output_tokens is the provider completion total and reasoning_tokens is a slice of it — reasoning is never added on top. Our canonical output bucket excludes reasoning, so the parser now derives output = output_tokens - reasoning_tokens (clamped at 0). total now equals Hermes's own figure. Also dropped the now-obsolete "unverified" caveat comment, and added a clamp test for a provider reporting reasoning > completion.

agent.py — non-mapping seeded config.yaml. Real; or {} only catches None. Guarded with an isinstance(loaded, dict) check plus a warning, with a test seeding - a\n- b\n.

agent.py — state-isolation docstring. Correct, the claim was wrong: the collector does include dot-directories. Reworded to say .hermes is collected, as a single directory rather than scattered across the diff — which is the actual reason it moved out of the workspace root.

Nitpicks — all three taken: quote() on the SQLite URI path (with a run?id=1 regression test), :g on the timeout seconds, and type annotations on the test helpers and every fake_run stub.

1230 tests pass; ruff check and ruff format clean.

Three defects found while running the harness end-to-end against a real
hermes binary:

* ``--provider`` was derived from ``ProviderSpec.adapter_family``, which
  only coincidentally matches hermes's own provider names. ``openai``
  emitted ``openai`` (hermes wants ``openai-api``) and hard-failed,
  ``anthropic-bedrock`` emitted ``claude`` and resolved to the direct
  Anthropic API instead of Bedrock, and ``anthropic-vertex`` emitted
  ``vertex``, which hermes serves with Gemini only. Map explicitly and
  raise ``ConfigError`` for the provider hermes cannot serve.
* hermes exits 0 on a rejected API key, an unknown provider, and an API
  call whose retries all failed, so those runs reached the metrics as a
  genuinely bad answer. Flag a zero exit that recorded no model usage.
* Only ``KUBECONFIG`` was forwarded into the MCP server env block, so a
  gcloud-backed server read the ambient developer config under
  ``--parallel``. Forward ``CLOUDSDK_CONFIG`` as well.
…acts

Hermes installs its own 82-skill catalog into HERMES_HOME on first run and
sources repo-local skills when the session starts inside a checkout, so a
task granted no skills was still offered a ``devops`` pack. Write the
``.no-bundled-skills`` marker and set ``skills.project_discovery: false``,
leaving the granted skills as the only ones advertised (verified: the
prompt index drops from 82 skills to 1).

The run home also carried hermes's vendored binary, models.dev catalog
download, and request cache into the workspace snapshot -- 31 MB of
``generated_files`` per task. Drop them once the state DB has been read;
the run's evidence (state.db, config.yaml, logs) is kept, and the home
lands at 1.3 MB.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

Inline comments:
In `@devops_bench/agents/cli/hermes/agent.py`:
- Line 262: Update the mcp_servers merge in the configuration setup to validate
the existing config_data["mcp_servers"] value before dictionary expansion. Reuse
it only when it is a mapping; otherwise substitute an empty mapping, emit a
warning, and then merge servers so Hermes startup continues.
- Around line 257-262: Update _prepare_config to use the effective isolation
values from AgentConfig.extra_env, including KUBECONFIG and CLOUDSDK_CONFIG,
when populating each MCP server’s env entries before assigning
config_data["mcp_servers"]; add a regression test covering extra_env propagation
through _execute.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 93c1c2a2-e3c9-4c97-81bb-1b352922edfd

📥 Commits

Reviewing files that changed from the base of the PR and between d80fc8c and a92ab0e.

📒 Files selected for processing (3)
  • devops_bench/agents/cli/hermes/agent.py
  • devops_bench/agents/cli/hermes/parsing.py
  • tests/unit/agents/test_agents_cli_hermes.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread devops_bench/agents/cli/hermes/agent.py Outdated
Comment thread devops_bench/agents/cli/hermes/agent.py Outdated
…rvers

The isolation vars handed to each MCP server were read from os.environ
only, so an operator override in extra_env -- which wins for hermes
itself in _build_env -- left the servers on a different cluster. Resolve
both in the same precedence. Also skip a seeded mcp_servers that is not
a mapping (e.g. 'mcp_servers: disabled') instead of raising TypeError on
the merge before hermes starts.
Consolidate the MCP run-isolation vars into one shared list owned by
`mcp_isolation_env` and drop the per-agent `keys` argument. openclaw was
forwarding only KUBECONFIG, so a gcloud-backed MCP server it spawned read
the operator's ambient credentials instead of the run's CLOUDSDK_CONFIG.
Both vars narrow what the child can reach, so a shorter list is a looser
sandbox rather than a tighter one.

Also carries the rest of the review fixes across hermes, its parsing, and
the provider contract.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

Inline comments:
In `@devops_bench/agents/cli/hermes/agent.py`:
- Around line 217-219: Update the docstring near the bundled-skill catalog setup
to clarify that granted skills are the only additional skills available, while
preserving that Hermes retains the essential hermes-agent skill.

In `@devops_bench/agents/shared/cli_capabilities.py`:
- Around line 15-20: Remove provider-specific CLI names and direct
CLOUDSDK_CONFIG access from the shared capability layer, including the affected
environment and launch-map handling. Resolve provider-specific environment
values in the appropriate provider or deployer module, then pass a neutral
environment mapping into the shared capability helpers while preserving existing
capability behavior.

In `@devops_bench/core/model_providers.py`:
- Line 70: Update the ProviderSpec.hermes_provider field to retain constructor
compatibility by assigning it a default value of None while keeping its str |
None type.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5153fba4-fe4b-442d-9637-e5033cc625c9

📥 Commits

Reviewing files that changed from the base of the PR and between a92ab0e and 40f2faf.

📒 Files selected for processing (10)
  • devops_bench/agents/cli/hermes/agent.py
  • devops_bench/agents/cli/hermes/parsing.py
  • devops_bench/agents/cli/openclaw/agent.py
  • devops_bench/agents/shared/cli_capabilities.py
  • devops_bench/core/model_providers.py
  • docs/how-to/add-a-model-provider.md
  • tests/unit/agents/shared/test_cli_capabilities.py
  • tests/unit/agents/test_agents_cli_hermes.py
  • tests/unit/agents/test_agents_cli_openclaw.py
  • tests/unit/models/test_models_base.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread devops_bench/agents/cli/hermes/agent.py
Comment on lines +15 to +20
"""Capability materialization shared by the CLI agents (Gemini, openclaw, hermes).

Both CLI agents render granted MCP bindings into a ``{name: {command, args}}``
launch map and copy discovered ``SKILL.md`` files into the binary's workspace
skills tree. Importing this module pulls no provider SDK.
The CLI agents render granted MCP bindings into a ``{name: {command, args}}``
launch map, copy discovered ``SKILL.md`` files into the binary's workspace skills
tree, prepend the granted rules to the prompt, and forward the run's isolation
env vars to the MCP children. Importing this module pulls no provider SDK.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Move provider-specific environment policy out of the shared layer.

This generic module names provider-specific CLIs and reads CLOUDSDK_CONFIG directly. Keep the shared helper neutral. Resolve provider-specific variables in a provider or deployer module, then pass a neutral environment mapping into shared capability code.

As per coding guidelines, “provider-specific terms and environment variables belong only in provider-specific modules, deployer implementations, or tf/.” As per path instructions, generic layers must not read provider-specific environment variables.

Also applies to: 50-54, 122-155

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@devops_bench/agents/shared/cli_capabilities.py` around lines 15 - 20, Remove
provider-specific CLI names and direct CLOUDSDK_CONFIG access from the shared
capability layer, including the affected environment and launch-map handling.
Resolve provider-specific environment values in the appropriate provider or
deployer module, then pass a neutral environment mapping into the shared
capability helpers while preserving existing capability behavior.

Sources: Coding guidelines, Path instructions

Comment thread devops_bench/core/model_providers.py Outdated
- Move the child-scoped env list to `core.run_env` as `CHILD_SCOPED_ENVS`.
  The shared CLI capability layer no longer names provider-specific vars,
  and the list now lives in the module that points them at per-run paths,
  so adding a var there has one place to update rather than two.
- `ProviderSpec.hermes_provider` defaults to `None`. The model is public and
  frozen; a required new field breaks every external constructor, and
  "hermes cannot serve this provider" is the right default.
- Correct `_prepare_config`'s docstring: the bundled-catalog marker cannot
  remove hermes's own `hermes-agent` skill, so granted skills are the only
  *additional* ones the agent sees.
@eugeneng04

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants