Skip to content

feat(nemo-agents-plugin): add hermes adapter to nemo-agents plugin#500

Merged
mmogallapalli merged 2 commits into
mainfrom
mmogallapall/aircore-849-add-hermes-adapter-to-nemo-agents
Jun 29, 2026
Merged

feat(nemo-agents-plugin): add hermes adapter to nemo-agents plugin#500
mmogallapalli merged 2 commits into
mainfrom
mmogallapall/aircore-849-add-hermes-adapter-to-nemo-agents

Conversation

@mmogallapalli

@mmogallapalli mmogallapalli commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds experimental Hermes agent support to nemo-agents by vendoring the NAT
Hermes adapter and wiring it into the plugin package, following the same pattern
used for the Codex, Cursor, and Claude Code adapters.

This PR:

  • Vendors the upstream Hermes adapter into plugins/nemo-agents
  • Exposes the adapter through the nat.components entry point
  • Recognizes hermes_agent in nemo-agents config validation
  • Adds a Hermes example config and README
  • Adds tests for adapter registration and example config validation
  • Records upstream provenance for the vendored Hermes adapter, matching the
    existing vendoring approach

User Flow

Users install/use nemo-agents as usual, then provide a config with:

workflow:
  _type: hermes_agent

The included example is:

plugins/nemo-agents/examples/hermes-agent/hermes-agent.yml

The Hermes adapter requires uvx and nemo-relay to be installed on PATH,
with Hermes Agent authentication/model configuration already set up. Relay is
used internally by the adapter to run Hermes and bridge Hermes events into NAT
telemetry.

The example config uses:

workflow:
  _type: hermes_agent
  command: uvx
  command_args: ["--from", "hermes-agent", "hermes"]
  working_directory: .

Model Passthrough Note

The spike called out that Hermes owns provider/model configuration outside of
NAT's normal llms: primitive. That concern is still valid: the Hermes adapter
does not use llm_name to resolve a NAT LLM.

There is, however, a practical passthrough path. The adapter accepts
Hermes-specific provider and model fields and forwards them to the Hermes
CLI as --provider and --model.

For example:

workflow:
  _type: hermes_agent
  command: uvx
  command_args: ["--from", "hermes-agent", "hermes"]
  working_directory: .
  provider: nvidia_nim
  model: nvidia/nvidia-nemotron-nano-9b-v2

If those fields are omitted, Hermes falls back to its own local auth/model
configuration. So platform/NAT model capabilities still cannot be attached
uniformly through the standard NAT llms: path, but users can override the
Hermes provider/model through adapter-level passthrough fields.

Validation

Focused tests:

uv run --frozen pytest plugins/nemo-agents/tests/unit/test_hermes_adapter_packaging.py plugins/nemo-agents/tests/unit/test_claude_code_adapter_packaging.py plugins/nemo-agents/tests/unit/test_codex_adapter_packaging.py plugins/nemo-agents/tests/unit/test_cursor_adapter_packaging.py plugins/nemo-agents/tests/unit/test_container.py -q

Result:

110 passed, 1 warning

Additional checks:

tools/lint/lint-python-style.sh
uv run nemo agents package --agent plugins/nemo-agents/examples/hermes-agent/hermes-agent.yml --no-build --output /tmp/nemo-hermes-agent.Dockerfile
git diff --check

Manual smoke tests:

  • uvx --from hermes-agent hermes setup
  • uvx --from hermes-agent hermes auth
  • uvx --from hermes-agent hermes model
  • uvx --from hermes-agent hermes status
  • nemo agents create --name hermes-agent --agent-config plugins/nemo-agents/examples/hermes-agent/hermes-agent.yml
  • nemo agents deploy --agent hermes-agent
  • nemo agents invoke --agent hermes-agent --input "Read pyproject.toml and say only the project name. Do not edit files."

Invoke returned:

The project name in pyproject.toml is **nemoplatform**.

Summary by CodeRabbit

  • New Features
    • Added support for a new Hermes-backed workflow type (hermes_agent) for agent runs.
    • Added a ready-to-use Hermes example configuration and run/deploy documentation.
    • Packaged the Hermes adapter so it’s included with the plugin and available via the plugin component entry point.
  • Bug Fixes
    • Updated configuration validation to recognize hermes_agent, preventing “unknown type” warnings.
  • Documentation
    • Refreshed prerequisites in multiple agent examples to improve NeMo Relay installation and smoke-test PATH behavior.
  • Tests
    • Added unit tests covering workflow type registration, config loading, and packaging for the Hermes adapter and example.

@mmogallapalli mmogallapalli self-assigned this Jun 29, 2026
@mmogallapalli mmogallapalli requested a review from a team as a code owner June 29, 2026 14:57
@mmogallapalli mmogallapalli requested a review from a team as a code owner June 29, 2026 14:57
Signed-off-by: Manjesh Mogallapalli <mmogallapall@nvidia.com>
@mmogallapalli mmogallapalli force-pushed the mmogallapall/aircore-849-add-hermes-adapter-to-nemo-agents branch from 2c040a1 to 52a55a7 Compare June 29, 2026 15:00
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d5a4f8a3-4f9b-4187-a9fe-1c335b5b9a4c

📥 Commits

Reviewing files that changed from the base of the PR and between 52a55a7 and fde68b8.

📒 Files selected for processing (4)
  • plugins/nemo-agents/examples/claude-code-agent/README.md
  • plugins/nemo-agents/examples/codex-agent/README.md
  • plugins/nemo-agents/examples/cursor-agent/README.md
  • plugins/nemo-agents/examples/hermes-agent/README.md
✅ Files skipped from review due to trivial changes (3)
  • plugins/nemo-agents/examples/cursor-agent/README.md
  • plugins/nemo-agents/examples/claude-code-agent/README.md
  • plugins/nemo-agents/examples/hermes-agent/README.md

📝 Walkthrough

Walkthrough

Adds a vendored Hermes workflow adapter, registers hermes_agent as a NAT component, updates validation and packaging, and adds an example workflow config plus setup documentation.

Changes

Hermes Agent Adapter Integration

Layer / File(s) Summary
Hermes workflow adapter and runtime
plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/*
Defines HermesAgentWorkflowConfig, prompt/response helpers, Relay command construction, async _run_hermes_agent, and the registered hermes_agent workflow.
Packaging, validator, tests, and examples
plugins/nemo-agents/pyproject.toml, packages/nemo_platform/pyproject.toml, plugins/nemo-agents/src/nemo_agents_plugin/container/validator.py, plugins/nemo-agents/tests/unit/*, plugins/nemo-agents/examples/hermes-agent/*, plugins/nemo-agents/vendor/hermes_agent_adapter/README.md, plugins/nemo-agents/examples/*-agent/README.md
Registers the entry point, bundles the vendored package, allowlists hermes_agent, and adds tests, example config, and setup docs.

Possibly related PRs

Suggested reviewers

  • stefan-kickoff
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. 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 matches the main change: adding the Hermes adapter to the nemo-agents plugin.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mmogallapall/aircore-849-add-hermes-adapter-to-nemo-agents

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

@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 (2)
plugins/nemo-agents/tests/unit/test_hermes_adapter_packaging.py (1)

19-22: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Load the entry point in this test. entry_points(group="nat.components") only checks metadata; ep.load() catches import failures that runtime discovery would skip.

🤖 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 `@plugins/nemo-agents/tests/unit/test_hermes_adapter_packaging.py` around lines
19 - 22, The test only verifies entry point metadata via
entry_points(group="nat.components"), so it can miss import/load failures.
Update test_hermes_adapter_nat_components_entry_point_registered to also call
ep.load() on the nat_hermes_agent_adapter entry point, using the same entry
point lookup, so packaging/import issues are caught during the test.
plugins/nemo-agents/examples/hermes-agent/README.md (1)

1-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep this page as one HOW-TO and add the required sections.

This mixes explanation with task steps and omits the required Python SDK/CLI tab set and Next Steps section. Split the packaging note into a separate explanation/reference page, keep this README task-focused, and end with cross-links. As per coding guidelines, "Each documentation page should fit ONE Diataxis quadrant; do not mix tutorials with reference tables or how-tos with architecture explanations; use cross-links instead", "Provide both Python SDK and CLI examples in tab-sets for consistency and to support multiple user workflows", and "Include 'Next Steps' section at the end with cross-links to related documentation content".

🤖 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 `@plugins/nemo-agents/examples/hermes-agent/README.md` around lines 1 - 57,
This README mixes a how-to with explanatory/reference content, so split the
Hermes packaging note into a separate reference/explanation page and keep this
page focused on task steps. Update the Hermes Agent README to include the
required Python SDK and CLI tab-set examples in the main workflow sections, then
add a closing Next Steps section with cross-links to related docs. Make sure the
content stays aligned with the existing Hermes Agent instructions and the
deployment/invocation flow while removing non-actionable architecture-style
explanation.

Source: Coding guidelines

🤖 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 `@plugins/nemo-agents/examples/hermes-agent/README.md`:
- Around line 22-33: The NeMo Relay install snippet is not runnable as written
because `cargo install --root .venv` only drops binaries into `.venv/bin` and
does not create an activatable virtualenv. Update the README in the
`hermes-agent` setup section so the install path is either explicitly tied to an
existing `VIRTUAL_ENV` or the snippet exports the bin directory onto `PATH`
before running `nemo-relay --help`. Make sure the `cargo install` and smoke-test
commands in the `nemo-relay` setup flow are consistent with the environment they
actually create.

In
`@plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/register.py`:
- Around line 155-173: The relay ATOF config in _relay_plugin_config currently
hardcodes the same events.jsonl target with overwrite mode, so concurrent calls
to register/inject_atof_jsonl can collide. Update _relay_plugin_config (and the
call sites that pass relay_atof_output_dir) to create a unique per-invocation
subdirectory or filename for each request, then point the ATOF
output_directory/filename at that unique path so each run writes and reads its
own file.
- Around line 194-203: The launcher hint in _diagnose_empty_output is using the
Relay wrapper prefix from command[:4], which can mislead operators when command
or command_args are overridden. Update this helper to derive the displayed
prefix from the configured Hermes launcher command instead of the nemo-relay
invocation, so the message references the actual executable the user should
test.

---

Nitpick comments:
In `@plugins/nemo-agents/examples/hermes-agent/README.md`:
- Around line 1-57: This README mixes a how-to with explanatory/reference
content, so split the Hermes packaging note into a separate
reference/explanation page and keep this page focused on task steps. Update the
Hermes Agent README to include the required Python SDK and CLI tab-set examples
in the main workflow sections, then add a closing Next Steps section with
cross-links to related docs. Make sure the content stays aligned with the
existing Hermes Agent instructions and the deployment/invocation flow while
removing non-actionable architecture-style explanation.

In `@plugins/nemo-agents/tests/unit/test_hermes_adapter_packaging.py`:
- Around line 19-22: The test only verifies entry point metadata via
entry_points(group="nat.components"), so it can miss import/load failures.
Update test_hermes_adapter_nat_components_entry_point_registered to also call
ep.load() on the nat_hermes_agent_adapter entry point, using the same entry
point lookup, so packaging/import issues are caught during the test.
🪄 Autofix (Beta)

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: Enterprise

Run ID: 1fa95eab-8e8f-4585-b4fc-7a6a24e6a36a

📥 Commits

Reviewing files that changed from the base of the PR and between a012393 and 2c040a1.

📒 Files selected for processing (10)
  • packages/nemo_platform/pyproject.toml
  • plugins/nemo-agents/examples/hermes-agent/README.md
  • plugins/nemo-agents/examples/hermes-agent/hermes-agent.yml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/container/validator.py
  • plugins/nemo-agents/tests/unit/test_container.py
  • plugins/nemo-agents/tests/unit/test_hermes_adapter_packaging.py
  • plugins/nemo-agents/vendor/hermes_agent_adapter/README.md
  • plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/__init__.py
  • plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/register.py

Comment thread plugins/nemo-agents/examples/hermes-agent/README.md

@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

🧹 Nitpick comments (1)
plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/register.py (1)

299-304: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Use the two-argument AsyncGenerator form here. AsyncGenerator[ChatResponseChunk] raises TypeError on this repo’s Python 3.11 target; change it to AsyncGenerator[ChatResponseChunk, None] to match the other annotation.

🤖 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
`@plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/register.py`
around lines 299 - 304, The _stream_fn return annotation uses the one-argument
AsyncGenerator form, which is invalid on the Python 3.11 target used here.
Update the _stream_fn signature in nat_hermes_agent_adapter/register.py to use
AsyncGenerator[ChatResponseChunk, None] so it matches the repo’s other generator
annotations and avoids the TypeError.
🤖 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
`@plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/register.py`:
- Around line 247-256: The timeout handling around
asyncio.wait_for(process.communicate(), timeout=config.timeout_seconds) in the
Hermes CLI runner only catches TimeoutError, so a CancelledError can leave the
subprocess running and skip cleanup. Update the try/except in the register.py
flow to also handle asyncio.CancelledError alongside the existing timeout path,
ensuring process.kill(), await process.wait(),
_inject_relay_events(relay_atof_path), and relay_temp_dir.cleanup() still run
before re-raising the cancellation.
- Around line 141-147: The prompt is currently being passed through
_build_hermes_args into the chat command argv, which exposes user content in
process listings and logs. Update the Hermes invocation path in
_build_hermes_args/register.py to avoid placing the prompt on the command line;
instead route it through stdin or a prompt file if Hermes supports it, or add
clear documentation/explicit handling of the privacy tradeoff if no safer input
path exists. Keep the provider/model argument handling intact.

---

Nitpick comments:
In
`@plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/register.py`:
- Around line 299-304: The _stream_fn return annotation uses the one-argument
AsyncGenerator form, which is invalid on the Python 3.11 target used here.
Update the _stream_fn signature in nat_hermes_agent_adapter/register.py to use
AsyncGenerator[ChatResponseChunk, None] so it matches the repo’s other generator
annotations and avoids the TypeError.
🪄 Autofix (Beta)

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: Enterprise

Run ID: 2f4d033d-4741-4abd-a5eb-378c46d17255

📥 Commits

Reviewing files that changed from the base of the PR and between 2c040a1 and 52a55a7.

📒 Files selected for processing (10)
  • packages/nemo_platform/pyproject.toml
  • plugins/nemo-agents/examples/hermes-agent/README.md
  • plugins/nemo-agents/examples/hermes-agent/hermes-agent.yml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/container/validator.py
  • plugins/nemo-agents/tests/unit/test_container.py
  • plugins/nemo-agents/tests/unit/test_hermes_adapter_packaging.py
  • plugins/nemo-agents/vendor/hermes_agent_adapter/README.md
  • plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/__init__.py
  • plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/register.py
✅ Files skipped from review due to trivial changes (5)
  • plugins/nemo-agents/vendor/hermes_agent_adapter/src/nat_hermes_agent_adapter/init.py
  • plugins/nemo-agents/examples/hermes-agent/hermes-agent.yml
  • plugins/nemo-agents/vendor/hermes_agent_adapter/README.md
  • plugins/nemo-agents/tests/unit/test_container.py
  • plugins/nemo-agents/examples/hermes-agent/README.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/tests/unit/test_hermes_adapter_packaging.py
  • plugins/nemo-agents/src/nemo_agents_plugin/container/validator.py
  • packages/nemo_platform/pyproject.toml

Signed-off-by: Manjesh Mogallapalli <mmogallapall@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 21898/28725 76.2% 61.0%
Integration Tests 12583/27405 45.9% 19.2%

Comment thread plugins/nemo-agents/examples/codex-agent/README.md
@mmogallapalli mmogallapalli added this pull request to the merge queue Jun 29, 2026
Merged via the queue into main with commit 774a0e7 Jun 29, 2026
54 checks passed
@mmogallapalli mmogallapalli deleted the mmogallapall/aircore-849-add-hermes-adapter-to-nemo-agents branch June 29, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants