How Ponytail Activates on Session Start: Hermes Plugin Lifecycle Explained

Ponytail automatically activates when the register() function binds a pre-LLM hook to the Hermes context, injecting instructional context into the first model request of every session.

Ponytail is a Hermes plugin that enhances LLM-agent interactions by automatically prepending contextual instructions at the start of each conversation. Understanding how Ponytail activates on session start requires examining its registration mechanism and hook architecture in the DietrichGebert/ponytail repository. When properly initialized, the plugin intercepts the first LLM call to insert mode-specific guidance without requiring manual intervention.

The Activation Process on Session Start

The activation sequence begins when ponytail.register(ctx) is invoked with a valid Hermes context object. According to the source code in __init__.py (lines 95-106), this function registers three critical components with the Hermes framework:

  • A pre-LLM-call hook (_pre_llm_call) via ctx.register_hook("pre_llm_call", _pre_llm_call)
  • A gateway-dispatch rewrite hook (rewrite_gateway_command) via ctx.register_hook("pre_gateway_dispatch", rewrite_gateway_command)
  • Slash commands including /ponytail, /ponytail-review, and others for runtime configuration

Hook Execution and Context Injection

As soon as a session issues its first LLM request, Hermes invokes every registered pre_llm_call hook. Ponytail’s _pre_llm_call handler executes build_injected_context (implemented in __init__.py, lines 25-33 and 105-112) to construct the mode-filtered instructional text.

The hook returns a dictionary in the format { "context": <text> }, which Hermes automatically injects as a prefix to the model’s prompt. This injection happens transparently before the LLM processes the user's actual query.

Mode Resolution Hierarchy

The content injected on session start depends on the active mode, resolved in the following priority order:

  1. Explicit argument passed directly to build_injected_context
  2. Environment variable PONYTAIL_DEFAULT_MODE (normalized via _normalize_config_mode)
  3. Configuration file at ~/.config/ponytail/config.json (if present)
  4. Hard-coded fallback DEFAULT_MODE = "full"

When no other configuration exists, the first LLM call receives a prefix such as:


PONYTAIL MODE ACTIVE — level: full

<filtered skill description …>

Subsequent calls in the same session reuse this context unless the user changes modes via slash commands.

Practical Implementation Examples

Registering Ponytail with a Hermes Instance

from hermes import Hermes
import ponytail

# Create a Hermes context (or obtain one from your app)

ctx = Hermes()

# Wire Ponytail into the session

ponytail.register(ctx)

# From now on every new session will receive Ponytail’s injected context

# on the very first LLM call.

Changing the Mode During a Session


# User enters the slash command in the chat UI

#   /ponytail lite

# Hermes routes the command to Ponytail’s `_handle_mode_command`,

# which updates the global `_current_mode`.

# The next LLM turn will see:

#   PONYTAIL MODE ACTIVE — level: lite

Examining the Injected Context

from ponytail import build_injected_context

# Assuming default mode (full)

print(build_injected_context())

# => 

# PONYTAIL MODE ACTIVE — level: full

#

# <skill body filtered for “full” mode>

Key Source Files

Understanding Ponytail's activation mechanism requires familiarity with these components:

  • __init__.py: Core plugin implementation containing mode handling, context building, and hook registration logic
  • skills/ponytail/SKILL.md: Full-mode skill description injected during activation
  • skills/ponytail-review/SKILL.md: Alternative skill content for "review" mode (activated via PONYTAIL_DEFAULT_MODE=review)
  • README.md: Repository overview and initialization instructions

Summary

  • Ponytail activates on session start by registering a pre_llm_call hook through ponytail.register(ctx) that intercepts the first LLM request
  • The hook builds mode-filtered context via build_injected_context (lines 25-33 and 105-112 in __init__.py) and returns it in a dictionary format for Hermes injection
  • Mode selection follows a strict hierarchy: explicit argument, environment variable PONYTAIL_DEFAULT_MODE, config file at ~/.config/ponytail/config.json, then falls back to DEFAULT_MODE = "full"
  • Slash commands like /ponytail allow runtime mode changes that affect subsequent LLM turns by updating the global _current_mode variable
  • The registration logic resides in __init__.py (lines 95-106), which binds the plugin to the Hermes lifecycle

Frequently Asked Questions

What triggers Ponytail to start working in a new session?

Ponytail activates when Hermes invokes the registered _pre_llm_call hook during the first LLM request of a session. This hook, registered via ctx.register_hook("pre_llm_call", _pre_llm_call) in __init__.py (lines 95-106), executes automatically without requiring manual activation commands, ensuring the context is injected before the model processes any user input.

How do I configure Ponytail to use a specific mode on startup?

Set the environment variable PONYTAIL_DEFAULT_MODE to your preferred mode (e.g., full or review) before starting the session, or create a JSON config file at ~/.config/ponytail/config.json specifying the default mode. If neither exists, Ponytail defaults to DEFAULT_MODE = "full" as defined in the source code and processed by the _normalize_config_mode function.

Can I change Ponytail's behavior after a session has started?

Yes. Users can issue slash commands such as /ponytail lite or /ponytail review during an active session. Hermes routes these commands to _handle_mode_command, which updates the global _current_mode variable, causing subsequent LLM calls to receive the newly configured context prefix.

Where does the injected context text come from?

The injected content originates from skill definition files located in the skills/ directory. For full mode, Ponytail loads skills/ponytail/SKILL.md. For review mode, it loads skills/ponytail-review/SKILL.md. The build_injected_context function filters these files based on the current mode before injection into the LLM prompt.

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 →