Skip to content

feat(agents): add Hermes ACP adapter#942

Open
Nikhil (shadowfax92) wants to merge 8 commits into
devfrom
feat/acp-hermes
Open

feat(agents): add Hermes ACP adapter#942
Nikhil (shadowfax92) wants to merge 8 commits into
devfrom
feat/acp-hermes

Conversation

@shadowfax92
Copy link
Copy Markdown
Contributor

Summary

  • Add Hermes as a host-local ACP adapter in the server catalog, DB enum, ACPX prep, command resolver, and health probe.
  • Launch Hermes via hermes acp with HERMES_ACP_COMMAND override support.
  • Surface Hermes in the agent UI and block creation with an install prompt when the local CLI health probe fails.

Verification

  • bun run --filter @browseros/server test:agent
  • bun --env-file=apps/server/.env.development test apps/server/tests/lib/agents/agent-catalog.test.ts apps/server/tests/lib/agents/acpx-agent-adapter.test.ts apps/server/tests/lib/agents/acpx-runtime.test.ts apps/server/tests/lib/agents/adapter-health.test.ts apps/server/tests/api/routes/agents.test.ts
  • bun run --filter @browseros/server typecheck
  • bun run --filter @browseros/agent typecheck
  • bun run --filter @browseros/agent test
  • bunx biome check apps/server/src/lib/agents apps/server/tests/lib/agents apps/server/tests/api/routes apps/agent/entrypoints/app/agents apps/agent/entrypoints/app/agent-command apps/agent/entrypoints/sidepanel/index (exits 0; existing warnings remain in active-turn/route-test files)

Hermes ACP docs referenced: https://hermes-agent.nousresearch.com/docs/user-guide/features/acp

@shadowfax92
Copy link
Copy Markdown
Contributor Author

Greptile (@greptileai) review

@shadowfax92
Copy link
Copy Markdown
Contributor Author

Claude (@claude) review

@claude
Copy link
Copy Markdown

claude Bot commented May 5, 2026

Claude finished Nikhil (@shadowfax92)'s task in 2m 40s —— View job


PR Review: Add Hermes ACP Adapter

  • Gather context and understand the request
  • Review server-side changes (catalog, runtime, health, DB schema)
  • Review Hermes prepare/command resolution
  • Review UI changes (NewAgentDialog, agent display helpers)
  • Review tests
  • Post final review feedback

Overall this is a clean, well-structured addition that follows established patterns for host-local ACP adapters. Tests are thorough and coverage spans the full stack. A few items worth addressing before merge:


Issues

1. Dual env var names for command override (acpx-runtime.ts:763-764)

process.env.HERMES_ACP_COMMAND?.trim() ||
process.env.BROWSEROS_HERMES_ACP_COMMAND?.trim() ||

Two env var names for the same thing, with no docs explaining which is canonical. The PR description only mentions HERMES_ACP_COMMAND, but BROWSEROS_HERMES_ACP_COMMAND is also wired silently. This will confuse users who find one but not the other. Pick one canonical name (the HERMES_ACP_COMMAND prefix without the BROWSEROS_ prefix is fine and consistent with how other tools name their overrides), or document both explicitly.

Fix this →


2. Reasoning selector shown with only one option for Hermes (NewAgentDialog.tsx:259-276)

The model select is conditionally hidden when models: []:

{harnessModels.length > 0 ? (<div>...model select...</div>) : null}

But the reasoning select is always rendered regardless. For Hermes, reasoningEfforts has a single {id: 'default', label: 'Default'} entry, so users see a non-interactive dropdown with one choice. Either extend the same guard to hide the reasoning select when there's only one option, or add an empty reasoningEfforts: [] for Hermes and treat it the same as models.

Fix this →


3. Install command suggests editable dev install (hermes-install-prompt.ts:39)

installCommand: "pip install -e '.[acp]'",

The -e flag is an editable install from a local source checkout. New users installing Hermes from PyPI won't have a source tree to point at, so this command will fail with a confusing error. The Hermes ACP docs should be the reference for the correct install command. If the released package doesn't yet have an [acp] extra on PyPI, this should be documented rather than showing a command that only works in dev.

Fix this →


Minor Observations

Hermes and OpenClaw share the same Bot icon (AdapterIcon.tsx:23-24)

Both map to <Bot>. Not a blocker, but as the adapter list grows it helps users visually distinguish adapters at a glance.

NewAgentDialog.tsx adapter guard is hand-coded (NewAgentDialog.tsx:157-164)

if (value === 'openclaw' || value === 'claude' || value === 'codex' || value === 'hermes') {

This needs to be updated manually when new adapters are added. The HarnessAgentAdapter union already guards this at compile time via onRuntimeChange's type — consider using a Set<HarnessAgentAdapter> or the catalog to derive the check and prevent future drift. Pre-existing pattern though, not introduced in this PR.

DB schema enum is TypeScript-level only — no migration file needed. The SQLite column is text NOT NULL (confirmed in 0000_zippy_psylocke.sql), so the Drizzle enum annotation is a TS-level check that won't break existing installs. ✅


What's Well Done

  • hermes/prepare.ts is minimal and correct — reuses prepareBrowserosManagedContext + finishBrowserosManagedContext exactly like the other managed adapters.
  • adapter-health.ts in-flight dedup and TTL cache is solid; Hermes probe is properly wired to hermes --version with timeout.
  • Test coverage is thorough: health dedup/cache, command resolution, env override, install prompt gating, catalog entries, runtime integration, and sidepanel label rendering are all covered.
  • The HERMES_ACP_COMMAND override is a good escape hatch for local development.
  • applyPermissionBypass correctly stays claude-only; no silent bypass for Hermes.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

✅ Tests passed — 1110/1114

Suite Passed Failed Skipped
agent 82/82 0 0
build 9/9 0 0
eval 93/93 0 0
server-agent 261/261 0 0
server-api 164/164 0 0
server-browser 4/4 0 0
server-integration 9/10 0 1
server-lib 166/166 0 0
server-root 60/63 0 3
server-skills 31/31 0 0
server-tools 231/231 0 0

View workflow run

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 5, 2026

Greptile Summary

This PR registers Hermes as a host-local ACP adapter across the full stack: DB enum, server catalog, ACPX prep/command resolver, health probe, and agent UI with an install-prompt gate. The integration follows the same patterns established by Claude Code and Codex adapters.

  • Health probe gap (P1): adapter-health.ts probes hermes --version, which only confirms the base CLI is present. The ACP subcommand requires the [acp] extra installed separately; a user with base Hermes will show healthy, skip the install prompt, and hit a spawn failure at runtime when BrowserOS executes hermes acp.
  • Dead env var (P2): resolveHermesAcpCommand checks BROWSEROS_HERMES_ACP_COMMAND as an undocumented, untested second fallback — this should be removed per the team's dead-code policy.

Confidence Score: 3/5

Mostly safe but the health probe for Hermes is insufficient, creating a silent path to runtime failures for users with base Hermes installed without the ACP extra.

One P1 finding (health probe doesn't confirm ACP availability, bypasses the install-prompt gate) pulls the score below 4. The rest of the integration is clean, well-tested, and consistent with existing adapter patterns.

packages/browseros-agent/apps/server/src/lib/agents/adapter-health.ts — probe command should verify ACP availability, not just base CLI presence.

Important Files Changed

Filename Overview
packages/browseros-agent/apps/server/src/lib/agents/adapter-health.ts Adds hermes to the health probe map using hermes --version, but this doesn't confirm the ACP extra is installed — users with base Hermes will show healthy and hit a runtime failure.
packages/browseros-agent/apps/server/src/lib/agents/acpx-runtime.ts Adds Hermes command resolution with env-var override support; BROWSEROS_HERMES_ACP_COMMAND fallback is untested dead code.
packages/browseros-agent/apps/server/src/lib/agents/hermes/prepare.ts New prepare function for Hermes ACP context; straightforward delegation to shared BrowserOS-managed context helpers with AGENT_HOME env var set.
packages/browseros-agent/apps/server/src/lib/db/schema/agents.ts Adds 'hermes' to the adapter enum; SQLite stores this as plain text with no CHECK constraint in the migration, so no schema migration file is required.
packages/browseros-agent/apps/agent/entrypoints/app/agents/hermes-install-prompt.ts New install-prompt helper for Hermes; correctly gates on adapter id + unhealthy status; install command matches official Hermes ACP docs.
packages/browseros-agent/apps/server/src/lib/agents/agent-catalog.ts Adds Hermes descriptor with best-effort model control and a single 'default' reasoning effort; isAgentAdapter guard updated correctly.
packages/browseros-agent/apps/agent/entrypoints/app/agents/NewAgentDialog.tsx Adds Hermes to the runtime selector and wires the install-prompt blocking guard; model section is now conditionally rendered when models list is non-empty.
packages/browseros-agent/apps/server/src/lib/agents/acpx-agent-adapter.ts Registers Hermes adapter with its prepare function; no maybeHandleTurn override, consistent with the simple adapters pattern.

Sequence Diagram

sequenceDiagram
    participant UI as NewAgentDialog (UI)
    participant AH as AdapterHealthChecker
    participant RT as AcpxRuntime
    participant HK as resolveHermesAcpCommand
    participant HP as prepareHermesContext
    participant CLI as hermes acp (host CLI)

    UI->>AH: getHealth('hermes')
    AH->>CLI: hermes --version
    CLI-->>AH: exit 0 / error
    AH-->>UI: AdapterHealth { healthy, reason }

    alt unhealthy
        UI->>UI: show HermesInstallPrompt (blocks create)
    else healthy
        UI->>RT: send({ agent, message })
        RT->>HK: resolveHermesAcpCommand()
        HK-->>RT: HERMES_ACP_COMMAND env || 'hermes acp'
        RT->>HP: prepareHermesContext(input)
        HP-->>RT: PreparedAcpxAgentContext { commandEnv: { AGENT_HOME } }
        RT->>CLI: env AGENT_HOME=... hermes acp
        CLI-->>RT: ACP stream events
    end
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
packages/browseros-agent/apps/server/src/lib/agents/adapter-health.ts:119-122
**Health probe insufficient for ACP availability**

`hermes --version` confirms the base Hermes CLI is installed, but does **not** verify the `[acp]` extra is present. The Hermes docs make clear that `hermes acp` only exists after `pip install -e '.[acp]'` is run separately. A user who has Hermes installed without the ACP extra will pass this probe (healthy = true, no install prompt shown), then hit a spawn failure at runtime when BrowserOS tries to execute `hermes acp`. Consider using `hermes acp --version` or a similar ACP-specific check as the probe command instead.

### Issue 2 of 2
packages/browseros-agent/apps/server/src/lib/agents/acpx-runtime.ts:761-767
`BROWSEROS_HERMES_ACP_COMMAND` is an undocumented second env-var fallback that has no test coverage and isn't mentioned in the PR description or any configuration docs. Per the team's policy on removing dead code, this silent fallback should be dropped. If there's a reason to keep a `BROWSEROS_`-namespaced override, it should be the *only* env var and should be tested.

```suggestion
function resolveHermesAcpCommand(): string {
  return process.env.HERMES_ACP_COMMAND?.trim() || 'hermes acp'
}
```

Reviews (1): Last reviewed commit: "fix(agents): align hermes override and p..." | Re-trigger Greptile

Comment thread packages/browseros-agent/apps/server/src/lib/agents/adapter-health.ts Outdated
@shadowfax92 Nikhil (shadowfax92) changed the title Add Hermes ACP adapter feat(agents): add Hermes ACP adapter May 5, 2026
@shadowfax92
Copy link
Copy Markdown
Contributor Author

Addressed review feedback in 409e0ee:

  • Hermes health now probes hermes acp --help, so ACP subcommand availability is checked before creation is allowed.
  • Removed the undocumented BROWSEROS_HERMES_ACP_COMMAND fallback; HERMES_ACP_COMMAND is now the only override.
  • Hid the reasoning selector when an adapter has only one reasoning option.
  • Kept the ACP-extra install command because the Hermes ACP docs use pip install -e '.[acp]', and changed the prompt copy to say to install Hermes normally first, then add the ACP extra.

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.

1 participant