Learn Hermes AI Agent - Agent Customization & Extensions
Episode 16 of 23

Learn Hermes AI Agent - Agent Customization & Extensions

This episode turns a generic agent into a specialized one: writing custom actions and plugins with hooks, building domain-specific tools that are easy for the model to understand, and packaging it all into modules that can be installed and reused across projects.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 15 you made the agent cheap and fast: token budgets, semantic cache for repeated responses, TTL tool caches, and latency profiling to find bottlenecks. Your agent is now efficient. But efficiency does not add capability — for specific business problems, Hermes's built-in tools are often not enough.

Here is the roadmap for this episode: understanding the anatomy of a Hermes plugin, writing custom actions and hooks, building domain-specific tools that the model understands, and then packaging everything into reusable modules. This is the episode where your agent starts to be "shaped" for your own domain.

Anatomy of a Hermes Plugin

A Hermes plugin is one small package containing two things: a manifest that describes the plugin, and an entry module that registers actions, tools, and hooks. This separation matters: the manifest is used for resolution and installation, the code is used at runtime.

plugin.yml - plugin manifest
name: support-autopilot
version: 1.2.0
entry: index.ts
hooks:
  - on_turn_start
  - on_tool_invoked
capabilities:
  - action:order_status
  - tool:get_stock

The capabilities field is a kind of "label" that an orchestrator agent or a permission system (remember episode 11) can read to decide when this plugin may be used. Manifest versioning is also the basis for upgrades — a changed version means plugin behavior could change, and teams installing it must be aware of that.

Writing a Custom Action

An action is the simplest unit of work: a named function with an input schema that the model calls based on the description. The key is in the description — the model decides whether to use this action or not from that sentence, not from its code name.

actions/order-status.ts - custom action
import { action } from "@hermes/plugin";
 
export default action({
  name: "order_status",
  description: "Cek status order berdasarkan nomor order. Pakai saat user menanyakan posisi pesanannya.",
  input: {
    orderId: { type: "string", required: true },
  },
  async run({ orderId }) {
    return queryOrder(orderId);
  },
});

Notice three things. First, input comes with a type and required, so arguments are validated before run is called. Second, run returns structured data that the model will cite in its answer. Third, the description is written as a sentence explaining when the action is used, not how it works — the model is far better at choosing an action from a functional description like this.

Building Domain-Specific Tools

A simple action handles one question. For deeper integration — for example, checking warehouse stock, calculating shipping cost, or pulling data from an internal system — build a tool with complete input and output schemas. The output schema matters so the model knows how to read the result.

import { tool } from "@hermes/plugin";
 
export const stockTool = tool({
  name: "get_stock",
  description: "Ambil jumlah stok untuk SKU tertentu. Pakai saat user menanyakan ketersediaan barang.",
  input: {
    sku: { type: "string", required: true },
  },
  async run({ sku }) {
    return warehouse.queryStock(sku);
  },
});

Tools are registered through the config so they can be combined with built-in tools (builtin), plugin tools (plugin), or local files (local). The order in the list affects the model's preference — the tools most relevant to your domain should be placed higher.

Hooks: Injecting Behavior into the Lifecycle

Besides adding capabilities, a plugin can also inject behavior into the agent lifecycle through hooks. This is the same mechanism that observability teams used in episode 7 to record events, or that will be used for the guard layer in episode 18.

hooks/audit-hook.ts - record tool invocations
import { hook } from "@hermes/plugin";
 
export const auditHook = hook({
  on: "on_tool_invoked",
  async run(event) {
    await auditLog(event.toolName, event.args, event.sessionId);
  },
});

A hook like on_turn_start runs before the agent assembles its answer — suitable for injecting context from internal systems. on_tool_invoked runs right before a tool is executed — suitable for auditing, rate limiting, or blocking. One practical rule: hooks must be fast and must not throw unhandled errors, because they sit on the critical path of the conversation.

Packaging & Installing Agent Modules

After actions, tools, and hooks are assembled, you have a valuable agent module. Do not let it be trapped in one project — package it as a tarball, store it in a registry, and install it in other projects. Hermes provides packaging and installation commands:

hermes plugin pack --output dist/support-autopilot-1.2.0.tgz

Once packaged, the plugin can be published to an internal npm registry or distributed as a tarball. hermes plugins list shows installed plugins with their versions, and versions are pinned so teams do not silently use changed behavior. If your project already uses semantic-release (like this repository), bumping the manifest plugin version can follow the same commit conventions: feat: bumps the minor, fix: bumps the patch, and a breaking change bumps the major.

Conclusion

Episode 16 turned a generic agent into a tool shaped for your domain. You understood the plugin anatomy through the manifest and entry module, wrote custom actions with descriptions that let the model know when to use them, built domain-specific tools with complete schemas, injected behavior through hooks, and packaged everything into a cleanly installed and versioned module.

Key takeaways:

  • The manifest describes the plugin; the entry code registers actions, tools, and hooks.
  • The action description is the model's "eyes" — write when it is used, not how it works.
  • Domain-specific tools need complete input and output schemas so the model can use them.
  • Hooks inject behavior into the lifecycle without changing the core agent code.
  • Package the plugin as a tarball, install with hermes plugins install, and pin its version.

In the next episode 17 we assemble all the agents you have shaped into a team: Multi-agent Coordination — communication patterns between agents, an orchestrator that delegates subtasks to workers, and arbitration and consistency strategies when many agents work simultaneously. See you there!

Learn Hermes AI Agent - Agent Customization & Extensions | Learn Hermes AI Agent