Skip to content

Host support: Hermes Agent — portable package conformance and optional native Python hooks #697

Description

@ScriptedAlchemy

Scope / research status

P2 feature expansion. Research date 2026-09-06; Agent Bundle baseline 5fc8de37c9695b816d55bdcf18a6bcb1dfee69f5. Documentation research only; no Hermes installation or authenticated run. This issue covers Hermes Agent from Nous Research, not similarly named products.

Important correction to the initial Ponytail comparison: current Hermes documentation describes an Agent Plugins v1 compatibility subset as well as native Python plugins. First establish whether existing portable Agent Bundle output already satisfies that subset; do not build a Python wrapper for capabilities that need none.

Authoritative documentation / specifications

Record immutable upstream parser/API revisions before claiming a supported release range. The developer guide describes additive compatibility and also optional manifest v2/API-generation fields; do not invent a mandatory global API version from those different concepts.

Two supported implementation tiers to evaluate

A. Portable directory package

Documented components are root plugin.json, immediate skills/*/SKILL.md directories and root mcp.json. Hermes namespaces read-only skills and provides its own plugin-root/data anchors. Its documented MCP subset includes stdio and Streamable HTTP, with restrictions on URLs/redirects; legacy SSE is not interchangeable. This compatibility is not a claim of full conformance to every component in the Agent Plugins specification.

Proposed first fixture:

composite-root/
  plugin.json
  skills/review/SKILL.md
  mcp.json                 # omitted for a skills-only package
  mcp/example.mjs

Generate identity and MCP documents using the existing portable serializer, then exercise Hermes' parser and actual component discovery. Only add native metadata when the verified host contract requires it.

B. Native plugin for host hooks/commands

Native directory plugins use plugin.yaml plus __init__.py with register(ctx). Registrations include tools, hook callbacks, commands and bundled skills. Python handlers have their own schema/result and keyword-context contracts; shell hooks and gateway HOOK.yaml handlers are separate interfaces, not interchangeable plugin formats.

Illustrative native skeleton:

hermes-native/
  plugin.yaml
  __init__.py
  skills/review/SKILL.md
  runtime/                 # declared compiled JS operation payload if needed
name: example-plugin
version: 1.0.0
description: Project review helpers
provides_hooks:
  - post_tool_call
def register(ctx):
    def observed_call(**kwargs):
        # Adapter-owned payload conversion belongs here, not application policy.
        pass
    ctx.register_hook("post_tool_call", observed_call)

This is an illustrative registration skeleton, not a working business hook. Pin actual callback signatures and supported return semantics before generation. Prefer MCP for existing JS tools rather than rewriting application logic in Python. If native hooks require a bridge to compiled JS, keep it thin, explicitly owned, cancellable and bounded; do not create a second agent loop or spawn a process for every token.

Operator configuration / lifecycle

Official workflow separates installation from activation:

hermes plugins install example/repository --no-enable
hermes plugins list
hermes plugins enable example-plugin
hermes plugins doctor /path/to/plugin --ci

User plugins reside under the selected Hermes profile/home. Project-local discovery requires an explicit trust-related opt-in; never enable it globally for the user. config.yaml contains native mcp_servers and plugin enable/disable/settings controls. A disabled plugin must stay disabled after an Agent Bundle rebuild or reinstall. Native grant/capability changes require host consent; code executes with the user's permissions, not in a sandbox.

Native MCP illustration, independent of portable mcp.json:

mcp_servers:
  example:
    command: node
    args: ["/absolute/installed-plugin/mcp/example.mjs"]

Use the documented profile configuration and environment-secret mechanisms. Do not embed API keys in either generated file. Native Python dependency declarations do not justify installing arbitrary packages into Hermes' shared environment during plugin activation.

Composite and ownership constraints

  • Determine native-versus-portable manifest precedence when both are present. Never double-register the same tool/skill or assume both formats load simultaneously.
  • Existing Claude/Codex/Cursor files must not cause Hermes to discover unrelated components. Preserve Composite conformance: test cross-host auto-discovery and precedence, not only file collisions #651 required/forbidden-discovery coverage.
  • Keep package code immutable, runtime data in the host/profile data location, and deletion limited to recorded owned artifacts.
  • Preserve canonical operation identity and explicit host namespace differences in inspection. Do not conflate a renamed native skill with a new application operation.

Acceptance

  • Pin Hermes version/source and list the exact portable subset versus native-only capabilities.
  • A static portable package loads without Python glue, MCP startup or Flight/state machinery.
  • A generated MCP tool succeeds through Hermes from a relocated source-free artifact; unsupported transport and malformed sibling behavior are explicit.
  • Native hook mapping proves observational versus blocking semantics using the actual event contract.
  • Install, disabled state, enable, update, remove and profile isolation are exercised without bypassing grants.
  • hermes plugins doctor --ci validates trusted fixture registration; importing a plugin is not treated as sandboxed inspection.
  • Composite precedence, namespaces, foreign discovery, packed files and uninstall/data retention are tested.
  • Capture real-host completion separately from parser/registration checks; preserve no-credentials and unavailable-host outcomes honestly.

Reuse existing adapters, portable schema/evidence, manifest and receipt machinery. No provider/model selection, gateway-channel implementation, memory engine, Python environment manager, or global relaxation of executable self-containment is required by this issue.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions