Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since #11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (#17417 #16997 #16193 #14315 #13151 #11794 #10610 #10283 #10246 #11564 #13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (#16052 #16539 #16566 #15841 #14798 #10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (#17305 #17026 #17000 #15077 #14557 #14227 #14166 #14730 #17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (#17130 #17113 #17175 #17150 #16707 #12312 #12305 #12934 #14810 #14045 #17286 #17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (#16506 #15027 #13428 #12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (#12929 #12972 #10763 #16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (#16576 #16572 #16383 #15878 #15608 #15606 #14809 #14767 #14231 #14232 #14307 #13683 #12373 #11891 #11291 #10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (#15045 #14473 #15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
10 KiB
sidebar_position, sidebar_label, title, description
| sidebar_position | sidebar_label | title | description |
|---|---|---|---|
| 12 | Built-in Plugins | Built-in Plugins | Plugins shipped with Hermes Agent that run automatically via lifecycle hooks — disk-cleanup and friends |
Built-in Plugins
Hermes ships a small set of plugins bundled with the repository. They live under <repo>/plugins/<name>/ and load automatically alongside user-installed plugins in ~/.hermes/plugins/. They use the same plugin surface as third-party plugins — hooks, tools, slash commands — just maintained in-tree.
See the Plugins page for the general plugin system, and Build a Hermes Plugin to write your own.
How discovery works
The PluginManager scans four sources, in order:
- Bundled —
<repo>/plugins/<name>/(what this page documents) - User —
~/.hermes/plugins/<name>/ - Project —
./.hermes/plugins/<name>/(requiresHERMES_ENABLE_PROJECT_PLUGINS=1) - Pip entry points —
hermes_agent.plugins
On name collision, later sources win — a user plugin named disk-cleanup would replace the bundled one.
plugins/memory/ and plugins/context_engine/ are deliberately excluded from bundled scanning. Those directories use their own discovery paths because memory providers and context engines are single-select providers configured through hermes memory setup / context.engine in config.
Bundled plugins are opt-in
Bundled plugins ship disabled. Discovery finds them (they appear in hermes plugins list and the interactive hermes plugins UI), but none load until you explicitly enable them:
hermes plugins enable disk-cleanup
Or via ~/.hermes/config.yaml:
plugins:
enabled:
- disk-cleanup
This is the same mechanism user-installed plugins use. Bundled plugins are never auto-enabled — not on fresh install, not for existing users upgrading to a newer Hermes. You always opt in explicitly.
To turn a bundled plugin off again:
hermes plugins disable disk-cleanup
# or: remove it from plugins.enabled in config.yaml
Currently shipped
disk-cleanup
Auto-tracks and removes ephemeral files created during sessions — test scripts, temp outputs, cron logs, stale chrome profiles — without requiring the agent to remember to call a tool.
How it works:
| Hook | Behaviour |
|---|---|
post_tool_call |
When write_file / terminal / patch creates a file matching test_*, tmp_*, or *.test.* inside HERMES_HOME or /tmp/hermes-*, track it silently as test / temp / cron-output. |
on_session_end |
If any test files were auto-tracked during the turn, run the safe quick cleanup and log a one-line summary. Stays silent otherwise. |
Deletion rules:
| Category | Threshold | Confirmation |
|---|---|---|
test |
every session end | Never |
temp |
>7 days since tracked | Never |
cron-output |
>14 days since tracked | Never |
| empty dirs under HERMES_HOME | always | Never |
research |
>30 days, beyond 10 newest | Always (deep only) |
chrome-profile |
>14 days since tracked | Always (deep only) |
| files >500 MB | never auto | Always (deep only) |
Slash command — /disk-cleanup available in both CLI and gateway sessions:
/disk-cleanup status # breakdown + top-10 largest
/disk-cleanup dry-run # preview without deleting
/disk-cleanup quick # run safe cleanup now
/disk-cleanup deep # quick + list items needing confirmation
/disk-cleanup track <path> <category> # manual tracking
/disk-cleanup forget <path> # stop tracking (does not delete)
State — everything lives at $HERMES_HOME/disk-cleanup/:
| File | Contents |
|---|---|
tracked.json |
Tracked paths with category, size, and timestamp |
tracked.json.bak |
Atomic-write backup of the above |
cleanup.log |
Append-only audit trail of every track / skip / reject / delete |
Safety — cleanup only ever touches paths under HERMES_HOME or /tmp/hermes-*. Windows mounts (/mnt/c/...) are rejected. Well-known top-level state dirs (logs/, memories/, sessions/, cron/, cache/, skills/, plugins/, disk-cleanup/ itself) are never removed even when empty — a fresh install does not get gutted on first session end.
Enabling: hermes plugins enable disk-cleanup (or check the box in hermes plugins).
Disabling again: hermes plugins disable disk-cleanup.
observability/langfuse
Traces Hermes turns, LLM calls, and tool invocations to Langfuse — an open-source LLM observability platform. One span per turn, one generation per API call, one tool observation per tool call. Usage totals, per-type token counts, and cost estimates come out of Hermes' canonical agent.usage_pricing numbers, so the Langfuse dashboard sees the same breakdown (input / output / cache_read_input_tokens / cache_creation_input_tokens / reasoning_tokens) that appears in hermes logs.
The plugin is fail-open: no SDK installed, no credentials, or a transient Langfuse error — all turn into a silent no-op in the hook. The agent loop is never impacted.
Setup (interactive — recommended):
hermes tools # → Langfuse Observability → Cloud or Self-Hosted
The wizard collects your keys, pip installs the langfuse SDK, and adds observability/langfuse to plugins.enabled for you. Restart Hermes and the next turn ships a trace.
Setup (manual):
pip install langfuse
hermes plugins enable observability/langfuse
Then put the credentials in ~/.hermes/.env:
HERMES_LANGFUSE_PUBLIC_KEY=pk-lf-...
HERMES_LANGFUSE_SECRET_KEY=sk-lf-...
HERMES_LANGFUSE_BASE_URL=https://cloud.langfuse.com # or your self-hosted URL
How it works:
| Hook | Behaviour |
|---|---|
pre_api_request / pre_llm_call |
Open (or reuse) a per-turn root span "Hermes turn". Start a generation child observation for this API call with serialized recent messages as input. |
post_api_request / post_llm_call |
Close the generation, attach usage_details, cost_details, finish_reason, assistant output + tool calls. If no tool calls and non-empty content, close the turn. |
pre_tool_call |
Start a tool child observation with sanitized args. |
post_tool_call |
Close the tool observation with sanitized result. read_file payloads get summarized (head + tail + omitted-line count) so a huge file read stays under HERMES_LANGFUSE_MAX_CHARS. |
Session grouping keys off the Hermes session ID (or task ID for sub-agents) via langfuse.propagate_attributes, so everything in a single hermes chat session lives under one Langfuse session.
Verify:
hermes plugins list # observability/langfuse should show "enabled"
hermes chat -q "hello" # check the Langfuse UI for a "Hermes turn" trace
Optional tuning (in .env):
| Variable | Default | Purpose |
|---|---|---|
HERMES_LANGFUSE_ENV |
— | Environment tag on traces (production, staging, …) |
HERMES_LANGFUSE_RELEASE |
— | Release/version tag |
HERMES_LANGFUSE_SAMPLE_RATE |
1.0 |
Sampling rate passed to the SDK (0.0–1.0) |
HERMES_LANGFUSE_MAX_CHARS |
12000 |
Per-field truncation for message content / tool args / tool results |
HERMES_LANGFUSE_DEBUG |
false |
Verbose plugin logging to agent.log |
Hermes-prefixed and standard SDK env vars (LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_BASE_URL) are both accepted — Hermes-prefixed wins when both are set.
Performance: the Langfuse client is cached after the first hook call. If credentials or SDK are missing, that decision is also cached — subsequent hooks fast-return without re-checking env vars or reloading config.
Disabling: hermes plugins disable observability/langfuse. The plugin module is still discovered, but no module code runs until you re-enable.
google_meet
Lets the agent join, transcribe, and participate in Google Meet calls — take notes on a meeting, summarize the back-and-forth after, follow up on specific points, and (optionally) speak replies back into the call via TTS.
What it adds:
- A headless virtual participant that joins a Meet URL using browser automation
- Live transcription of the meeting audio via the configured STT provider
- A
meet_summarize/meet_speak/meet_followuptoolset the agent invokes to act on what it heard - Post-meeting artifacts (transcript, speaker-attributed notes, action items) saved under
~/.hermes/cache/google_meet/<meeting_id>/
Setup:
hermes plugins enable google_meet
# Prompts you to sign in via the plugin's OAuth flow on first use —
# needs a Google account with Meet access. Host approval may be required
# if the meeting enforces "only invited participants can join".
Usage from chat:
"Join meet.google.com/abc-defg-hij and take notes. After the call, send me a summary with action items."
The agent kicks off the meeting join, streams the transcription back into its context as the call proceeds, and produces a structured summary when the meeting ends (or when you tell it to stop).
When to use it: recurring standups where you want a bot to transcribe + summarize for async attendees; deposition-style interviews where you want structured notes; any case where you'd otherwise need Fireflies / Otter / Grain. When you'd rather not have an AI listening in — don't enable it.
Disabling: hermes plugins disable google_meet. Any cached transcripts and recordings stay in ~/.hermes/cache/google_meet/ until you remove them.
Adding a bundled plugin
Bundled plugins are written exactly like any other Hermes plugin — see Build a Hermes Plugin. The only differences are:
- Directory lives at
<repo>/plugins/<name>/instead of~/.hermes/plugins/<name>/ - Manifest source is reported as
bundledinhermes plugins list - User plugins with the same name override the bundled version
A plugin is a good candidate for bundling when:
- It has no optional dependencies (or they're already
pip install .[all]deps) - The behaviour benefits most users and is opt-out rather than opt-in
- The logic ties into lifecycle hooks that the agent would otherwise have to remember to invoke
- It complements a core capability without expanding the model-visible tool surface
Counter-examples — things that should stay as user-installable plugins, not bundled: third-party integrations with API keys, niche workflows, large dependency trees, anything that would meaningfully change agent behaviour by default.