Hermes Agent Plugin Development and Production Practices

This chapter is for advanced users: how to extend Hermes through the plugin system, how to migrate from OpenClaw, and best practices for security and cost when deploying Hermes to production.


Getting Started with Plugin Development

Hermes supports three types of plugins: general-purpose plugins (tools + hooks), memory providers, and context engines.

Example

# Interactively Manage Installed Plugins
hermes plugins

# Command-line management
hermes plugins list
hermes plugins install <path>
hermes plugins enable <name>
hermes plugins disable <name>

You can manage plugins in the dashboard. Use the following command to start the Dashboard:

hermes dashboard

Open the dashboard in your browser, open the plugin list on the left, and you can see the installed plugins:

Hook system

The most commonly used plugin capability is the Hook — injecting custom logic at key points in the Agent lifecycle:

Example

# File path: plugin directory/logging_plugin.py
# Simple plugin example: record all LLM calls
from hermes.plugins import Plugin, hook

class LoggingPlugin(Plugin):
    name = "logging-plugin"

    @hook("pre_llm_call")
    async def before_call(self, ctx):
        # Trigger before each LLM call
        print(f"[LOG] About to call LLM, current context length: {len(ctx.messages)}")

    @hook("post_llm_call")
    async def after_call(self, ctx, response):
        # Trigger after each LLM call
        print(f"[LOG] LLM call completed, response length: {len(response.content)}")

Available Hook Points

HookTrigger timingTypical use
pre_llm_callBefore LLM CallsRecord context, modify prompts
post_llm_callAfter LLM CallsRecord responses, statistical analysis
pre_tool_callBefore tool invocation (can intercept/modify)Permission verification, parameter filtering
post_tool_callAfter the tool callResult Auditing, Logging
on_message_receivedWhen Receiving User MessagesMessage preprocessing, sensitive word filtering
on_session_startAt the start of the sessionInitialize resources, inject context
on_session_endAt the end of the sessionClean up resources, generate summary

Registering Custom Tools

Add brand-new tool capabilities to the Agent through plugins:

Example

# File path: plugin directory/my_tools.py
# Register custom tools — the Agent can use them just like built-in tools
from hermes.plugins import Plugin

class MyPlugin(Plugin):
    name = "my-tools"

    def register_tools(self, ctx):
        # Register custom tools, visible in the agent's system prompt
        ctx.register_tool(
            name="my_custom_tool",
            description="This tool does something, use when the user needs X",
            parameters={
                "type": "object",
                "properties": {
                    "input": {
                        "type": "string",
                        "description": "Input Parameter Description"
                    }
                },
                "required": ["input"]
            },
            handler=self.my_tool_handler
        )

    async def my_tool_handler(self, **kwargs):
        # Actual Execution Logic of the Tool
        input_text = kwargs.get("input", "")
        # ... processing logic ...
        return {"result": "done"}

Migrating from OpenClaw

If you are using OpenClaw, the official zero-downtime migration solution is provided:

Example

# Export OpenClaw configuration
openclaw export --format hermes > openclaw-config.json

# Import to Hermes
hermes import --from openclaw openclaw-config.json

# Verify Migration Results
hermes doctor

Main Concept Comparison

ConceptsOpenClawHermes
Agent DefinitionJSON Agent configurationSOUL.md + config.yaml
WorkflowManually write YAML flowsSkill (SKILL.md)
Memory BackendExternal databaseBuilt-in SQLite + Pluggable
Skills/ToolsCode PluginMarkdown skill files
multiple instancesMulti-process configurationProfile system

Production environment best practices

Security Checklist

Recommended Security Configuration for Production Deployment:

Example

# File path: ~/.hermes/config.yaml
# Recommended Security Configuration for Production Environment
terminal
:
  backend
: docker          # Required: isolate Agent command execution environment

approvals
:
  mode
: smart              # Dangerous commands require approval (or manual is stricter).
  cron_mode
: deny          # Scheduled tasks reject dangerous commands by default

security
:
  redact_secrets
: true     # Automatically redact sensitive information in logs (enabled by default)

Access control in environment variables:

Example

# File path: ~/.hermes/.env
# Access Control Configuration for Production Environment
GATEWAY_ALLOW_ALL_USERS=false           # Never allow all users
TELEGRAM_ALLOWED_USERS=your user ID# Explicit whitelist

Token cost control

Auxiliary tasks use cheaper models, significantly reducing operating costs:

Example

# File path: ~/.hermes/config.yaml
# Use a separate model for auxiliary tasks to reduce Token costs
auxiliary
:
  background_review
:
    provider
: openrouter
    model
: google/gemini-3-flash-preview    # No Need to Use the Main Model

  vision
:
    provider
: openrouter
    model
: google/gemini-2.5-flash-preview

  session_search
:
    provider
: openrouter
    model
: google/gemini-3-flash-preview

Multi-Profile gateway monitoring

Example

# View gateway status for all Profiles simultaneously
hermes profile list

# Batch restart all gateways
for profile in coder assistant researcher; do
  $profile gateway restart
done

Update Strategy

Update code and built-in skills of all Profiles with one command:

Example

# One-time code update + sync new built-in skills for all Profiles
hermes update
# → Code update (12 commits)
# → Skill sync:
# default (already latest)
# coder (+2 new skills)
# assistant (+2 new skills)

User-modified skills will never be overwritten. Updates only sync the new and changed parts of built-in skills.

other extensions