Hermes Agent
Installing more than one agent framework? The one-line curl covers Claude Code, OpenCode, OpenClaw and Pi in a single pass, and can select several at once. Hermes is installed manually, below.
The Telem plugin gives Hermes Agent two native tools:
telem_search— web search across Telem’s provider set, with several queries batched into one call.telem_fetch— read whole pages, a small batch of URLs per call.
It ships inside the telem-sdk Python package and Hermes discovers it through
a standard Python entry point — no separate plugin package, no npm.
Install
Section titled “Install”Install telem-sdk into the same Python environment Hermes runs in, then enable
the plugin:
pip install telem-sdkhermes plugins enable telemConfirm Hermes found it — telem should be listed, as enabled, with source
entrypoint:
hermes plugins listHermes requires Python 3.11, 3.12 or 3.13 (requires-python = ">=3.11,<3.14");
telem-sdk supports 3.10 and up, so any Hermes-compatible environment works. On
3.14, see troubleshooting.
Make the tools visible
Section titled “Make the tools visible”Registering a plugin is not the same as the model being able to call it:
- The toolset. Both tools live in a toolset named
telem, enabled by default. If you have narrowed your enabled toolsets, addtelemback. tool_search. Hermes defers non-core tools behind its catalog by default, so the model discovers them by searching rather than finding them in its initial tool list.
Credentials
Section titled “Credentials”The plugin uses the SDK’s own credential resolution: TELEM_API_KEY in the
environment, then ~/.telem/credentials.json (what --login writes). Because the
second exists, the tools register either way rather than being gated on the
environment variable. TELEM_BASE_URL overrides the hosted service endpoint.
Configuration
Section titled “Configuration”Hermes reads the same unified .telem/telem.json as every other file-reading Telem
tool — one project file, one user file, then TELEM_*, resolved per tool call and
per key. There are no Hermes-specific config files.
{ "tier": "extended", "providersInclude": ["exa", "brave"]}The two keys most people reach for:
| File key | Env fallback | Meaning |
|---|---|---|
tier |
TELEM_TIER |
Named result-field tier: minimalist, default, extended, or max |
providersInclude |
TELEM_PROVIDERS_INCLUDE (comma-separated) |
Replace the deployment’s provider set |
Full parameter reference → — every key, its env fallback and how the levels compose.
“The project” is Hermes’s own TERMINAL_CWD, falling back to the process working
directory when that is unset or gone. Anything ignored is reported to the Hermes
log, never into the text the model reads.
Using the tools
Section titled “Using the tools”Batch related queries into one call. They run concurrently as a single search and come back grouped per query — faster and cheaper than repeated calls:
{"queries": ["hermes agent plugin api", "hermes agent toolsets"], "goal": "plugin docs"}goal is an optional short label for what the search is trying to establish.
Reach for telem_fetch when a snippet is not enough. Search returns titles,
URLs, summaries and short excerpts; fetch returns the readable page:
{"urls": ["https://example.com/docs/plugins"]}Results are capped so one page cannot crowd out a batch, and the whole result stays under 90,000 characters so Hermes returns it inline rather than spilling it to a file.
Fetched URLs are screened
Section titled “Fetched URLs are screened”Hermes’s URL screening is keyed to its built-in web_extract by name, so a plugin
tool inherits none of it; telem_fetch runs the same checks itself, calling
Hermes’s own helpers. A URL is refused, before any request, when it:
- carries something shaped like an API key or token — checked in the raw URL, in the normalized form a redirect resolves to, and in the percent-decoded version of either;
- carries a credential-bearing query parameter (
api_key,token, …); - embeds a username or password;
- resolves to a private, loopback, or cloud-metadata address.
These checks are fail-closed: if they cannot run, the fetch is refused rather than performed unscreened.
Remote content is untrusted
Section titled “Remote content is untrusted”Hermes wraps its built-in web tools’ output in untrusted-content delimiters by tool
name, so telem_* output would otherwise arrive unmarked. Both tools apply the
same wrapper themselves and defang any delimiter the fetched content contains —
without which a page carrying a closing tag could end the trust boundary early.
It is a mitigation, not a guarantee: web content reaching a model is attacker-influenced input.
Troubleshooting
Section titled “Troubleshooting”“Plugin enabled but the tools are not visible.” Almost always tool_search
rather than a broken install. Confirm the plugin is loaded with
hermes plugins list, and check that the telem toolset is enabled.
Delegating to a subagent fails with 'DaemonThreadPoolExecutor' object has no attribute '_initializer'. Hermes is running on Python 3.14, which it does not
support: CPython 3.14 stopped setting _initializer on ThreadPoolExecutor and
Hermes’s thread pool still reads it, so every delegation dies at spawn — with or
without this plugin. pip install hermes-agent refuses 3.14; a source-tarball
install (a Homebrew formula, say) skips that check and lands here. Run Hermes on
3.11–3.13: python3.13 -m venv ~/.hermes-venv && ~/.hermes-venv/bin/pip install hermes-agent telem-sdk.
Every fetch is refused. The URL-safety checks are fail-closed and call into
Hermes’s internals; if a Hermes upgrade moved them, telem_fetch refuses
everything by design rather than fetching unscreened. The refusal message names
the cause; telem_search is unaffected.
Searches fail with a version error. The plugin requires the router’s normalized response and rejects an older one rather than rendering something misleading.
What is not included
Section titled “What is not included”- The built-in
web_searchandweb_extracttools are left registered. This plugin adds tools; it does not replace Hermes’s own. - Telem is not registered as a Hermes
WebSearchProvider. That interface takes one query at a time with no goal and no provider attribution, which would drop most of what these tools return.