How Ponytail Integrates with Hermes Agent: Plugin Architecture Explained

Ponytail integrates with Hermes Agent as a plugin that registers skills, hooks, and slash commands through a manifest-based architecture, automatically injecting context before each LLM call and intercepting gateway dispatches to rewrite commands.

The DietrichGebert/ponytail repository provides a lightweight development guidance system that operates within the Hermes Agent ecosystem. Understanding how Ponytail integrates with Hermes Agent reveals a sophisticated plugin pattern that leverages declarative manifests and runtime hooks to modify LLM behavior without altering core agent code.

The Plugin Manifest: Declaring Capabilities to Hermes

Hermes discovers Ponytail through the plugin.yaml manifest located in the repository root. This file declares the hooks, commands, and skills that Ponytail exposes to the Hermes runtime.

When Hermes loads the plugin, it reads this manifest to understand what capabilities Ponytail provides, including pre-LLM call hooks, pre-gateway dispatch interceptors, and a suite of /ponytail-* slash commands. This declarative approach allows Hermes to initialize the plugin without hardcoding Ponytail-specific logic into the agent core.

Registering Skills and Hooks in the Hermes Context

The integration centers on the register(ctx) function defined in __init__.py. When Hermes initializes the plugin, it invokes this function with a Hermes context object, triggering a three-phase registration process.

Automatic Skill Discovery from the skills/ Directory

During registration, Ponytail iterates over the skills/ directory and automatically registers every markdown-based skill with the Hermes context. According to the source code in __init__.py (lines 95-101), the plugin calls ctx.register_skill for each discovered skill file:


# From __init__.py lines 95-101

for skill_file in skills_dir.glob("*.md"):
    skill_name = skill_file.stem
    with open(skill_file, "r") as f:
        skill_content = f.read()
    ctx.register_skill(skill_name, skill_content)

This pattern allows developers to add new capabilities simply by dropping markdown files into the skills/ directory, without modifying the core plugin logic.

The pre_llm_call Hook: Injecting Context

Ponytail registers the pre_llm_call hook to modify prompts before they reach the LLM. As implemented in __init__.py (lines 125-130), this hook injects a mode-filtered context string that informs the LLM about the current Ponytail mode:


# Hook implementation from __init__.py lines 125-130

def pre_llm_call(session_id: str) -> dict:
    mode = _get_current_mode(session_id)
    context = f"PONYTAIL MODE ACTIVE — level: {mode}\n\n"
    return {"context": context}

The returned context string is prepended to the prompt sent to the LLM, ensuring that the "lazy senior developer" guidance is always active during the conversation.

The pre_gateway_dispatch Hook: Rewriting Commands

The second core hook, pre_gateway_dispatch, intercepts slash-command text from gateways before processing. Located at lines 152-165 in __init__.py, this function rewrites authorized /ponytail-* commands into normal agent prompts:


# From __init__.py lines 152-165

def pre_gateway_dispatch(text: str, session_id: str) -> str:
    if text.startswith("/ponytail"):
        # Rewrite command into structured prompt

        return _rewrite_ponytail_command(text, session_id)
    return text

This interception allows users to trigger Ponytail functionality through intuitive slash commands while the Hermes core processes them as standard prompts.

Runtime Mode Management and Slash Commands

Ponytail exposes several slash commands—including /ponytail, /ponytail-review, and /ponytail-audit—that allow users to change runtime modes or invoke specific skills directly.

The mode management system supports both configuration-time defaults and runtime toggling. The _default_mode variable sets the initial state, while the _handle_mode_command function (lines 166-176 in __init__.py) processes mode changes during conversations:


# Mode command handling from __init__.py lines 166-176

def _handle_mode_command(args: list, session_id: str) -> str:
    new_mode = args[0] if args else "full"
    _current_mode[session_id] = new_mode
    return f"Ponytail mode set to {new_mode}."

Users can trigger this functionality directly in chat:

/user> /ponytail lite

The system responds immediately, updating the internal _current_mode dictionary for that session and confirming the change.

Summary

  • Manifest-based discovery: Hermes loads Ponytail by reading plugin.yaml, which declares available hooks, commands, and skills without requiring code changes to the agent core.
  • Automatic skill registration: The plugin scans the skills/ directory and registers markdown-based capabilities via ctx.register_skill during initialization (lines 95-101).
  • Dual-hook architecture: pre_llm_call injects mode-specific context before each LLM turn (lines 125-130), while pre_gateway_dispatch intercepts and rewrites slash commands (lines 152-165).
  • Runtime flexibility: Users control Ponytail behavior through slash commands like /ponytail, with mode persistence handled via _handle_mode_command (lines 166-176).

Frequently Asked Questions

How does Hermes discover the Ponytail plugin?

Hermes discovers Ponytail through the plugin.yaml manifest file in the repository root. This YAML file declares the plugin's hooks, commands, and entry points, allowing Hermes to load and initialize the integration automatically without manual configuration in the agent core.

What happens when a user types a slash command like /ponytail lite?

When a user sends /ponytail lite, the pre_gateway_dispatch hook (lines 152-165 in __init__.py) intercepts the text before it reaches the LLM. The hook recognizes the /ponytail prefix, routes it to _handle_mode_command (lines 166-176), which updates the internal _current_mode for that session, and returns a confirmation message rather than processing it as a standard LLM prompt.

Can I add custom skills to Ponytail without modifying the Python code?

Yes. Ponytail automatically discovers skills by scanning the skills/ directory for markdown files during registration (lines 95-101). Adding a new SKILL.md file to this directory automatically registers it with Hermes via ctx.register_skill, making the new capability available immediately without touching __init__.py.

What is the difference between the pre_llm_call and pre_gateway_dispatch hooks?

The pre_llm_call hook (lines 125-130) executes immediately before sending a prompt to the LLM, injecting Ponytail's mode-specific context strings to guide the model's behavior. In contrast, pre_gateway_dispatch (lines 152-165) runs earlier in the pipeline, intercepting raw user input from chat gateways to rewrite slash commands into standard prompts before they enter the conversation flow.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →