Lyriel plugin for Hermes โ native integration with the Lyriel substrate.
Project description
Lyriel plugin for Hermes
Native Hermes integration for the Lyriel substrate. One bot, one chat, full agent context. Replaces the standalone Telegram bridge with a plugin that runs inside the Hermes process and pipes Lyriel asks into the user's existing Hermes Telegram chat via the gateway's own send pipeline.
What you get
- ๐ชถ Lyriel asks arrive in your active Hermes surface the instant
they're dispatched (long-poll loop on a daemon thread inside Hermes).
The plugin auto-detects which surface you're on:
- CLI mode (
hermesin a terminal): the dispatch is injected as the next message in your conversation via Hermes'sinject_messageprimitive. If the agent is mid-turn, it interrupts; if idle, the surface message becomes the next "user" input that triggers the agent. - Gateway mode (Hermes connected to Telegram / Discord / Slack): the plugin pushes through the gateway's existing platform adapter. No second bot to configure.
- CLI mode (
- Two LLM tools โ
lyriel_send_askandlyriel_replyโ so the user drives Lyriel in natural language. "Hermes, ping @noor about dinner." "Reply yes thursday works." - Full agent context: Hermes's memory, preferences, calendar tools, etc. are all available when drafting replies to Lyriel asks.
Install
Published (recommended)
pip install lyriel-hermes
lyriel-hermes install
The install subcommand symlinks the installed package into
~/.hermes/plugins/lyriel/ so Hermes discovers it on next boot. Pass
--copy if your environment doesn't allow symlinks; --target PATH
to override the destination.
Subsequent pip install --upgrade lyriel-hermes updates the plugin
through the symlink โ no need to re-run lyriel-hermes install.
Development (from this checkout)
# Editable install โ pip points at lyriel_hermes/ in this repo.
pip install -e clients/hermes-plugin
lyriel-hermes install # symlinks the editable install into ~/.hermes/plugins/lyriel
Or symlink directly without pip:
ln -sfn "$(pwd)/clients/hermes-plugin/lyriel_hermes" ~/.hermes/plugins/lyriel
Configure
-
Enable the plugin in
~/.hermes/config.yaml:plugins: enabled: - lyriel entries: lyriel: telegram_chat_id: "123456789" # your DM chat with the Hermes bot
If
gateway.telegram.home_chat_idis already set, the plugin will fall back to that; you can skip theplugins.entries.lyrielblock in that case. -
Set the Lyriel API key in
~/.hermes/.env(or your shell):LYRIEL_API_KEY=lyk_xxxxxxxxxxxxxxxx # from /me/agent setup LYRIEL_BASE_URL=https://lyriel.ai # or http://localhost:5173 for dev, # or your cloudflared tunnel URL
-
Restart the Hermes gateway so the plugin is loaded:
# however you run Hermes โ systemd restart, supervisor restart, etc. -
Verify by sending an ask to yourself or asking Hermes to ping
@lyriel. You should see a ๐ชถ message land in your Hermes Telegram chat within a second.
Configuration
| Setting | Where | Required | Default |
|---|---|---|---|
LYRIEL_API_KEY |
env / .env |
yes | โ |
LYRIEL_BASE_URL |
env / .env |
no | https://lyriel.ai |
plugins.entries.lyriel.telegram_chat_id |
~/.hermes/config.yaml |
yes (or fallback) | โ |
gateway.telegram.home_chat_id |
~/.hermes/config.yaml |
fallback for above | โ |
If neither chat id is set, the plugin still claims dispatches from Lyriel (so they don't pile up server-side) but won't surface them to Telegram. The LLM tools still work, so the user can list pending asks and reply via direct prompting if needed.
How it works
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Hermes process (always-on) โ
โ โ
register() โ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโถ โ โ Inbox poll loop โ โ LLM tool handlers โ โ
โ โ (daemon thread) โ โ lyriel_send_ask โ โ
โ โโโโโโโโโโฌโโโโโโโโโโ โ lyriel_reply โ โ
โ โ โโโโโโโโโโโโฌโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โผ โ
โ pending.py (ask_id โ callback URL/token map) โ
โ โ
โ Telegram surfacing via โ
โ tools.send_message_tool._send_to_platform โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ User's Hermes Telegram chat โ
โ โ
โ ๐ชถ Lyriel ask from @noor: โ
โ "dinner thursday?" โ
โ To reply, say: reply to Lyriel โ
โ ask <id> with <your response> โ
โ โ
โ > yes thursday works โ
โ โ
โ (LLM calls lyriel_reply โ โ
โ plugin POSTs callback) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Comparison with the standalone Telegram bridge
The standalone bridge (clients/telegram-bridge/lyriel_bridge.py) is a
runtime-agnostic reference client. It works for users who don't run
Hermes at all but produces a worse UX:
| Bridge | This plugin | |
|---|---|---|
| Bots in user's Telegram | 2 (Hermes + bridge) | 1 (Hermes) |
| LLM context on incoming asks | none โ bridge has no LLM | full Hermes context, memory, tools |
| Reply path | type verbatim into bridge chat | natural-language drafting via Hermes |
| Outbound asks via natural language | no โ manual curl | yes โ LLM calls lyriel_send_ask |
| Setup | run a separate Python process + new bot | drop into ~/.hermes/plugins/ + config entry |
The plugin is the production answer. The bridge stays useful for users on other runtimes (Claude Desktop, ChatGPT, etc.) until per-runtime skills exist for those.
Troubleshooting
"LYRIEL_API_KEY is not set" in Hermes logs. The env var isn't in the
gateway's process environment. Add it to ~/.hermes/.env and restart, or
run hermes setup to re-prompt.
Plugin loads but nothing arrives in Telegram. Check the gateway logs
for "no Telegram chat id configured". Set
plugins.entries.lyriel.telegram_chat_id (numeric) in
~/.hermes/config.yaml. To find your chat id, message @userinfobot in
Telegram โ its Id field is your chat id for any DM with any bot.
"could not extract callback URL/token for ask ..." in logs. The
inbound dispatch envelope didn't match the expected pattern. Likely a
Lyriel server version mismatch. Re-pair your agent at /me/agent for a
fresh setup.
LLM keeps trying to reply via lyriel_send_ask instead of
lyriel_reply. Adjust the surface message wording in surfacing.py
to be more directive, or add a system-prompt note in your Hermes config
that distinguishes initiation from reply.
Hot reload. Hermes doesn't hot-reload plugins. After any edit to
files in ~/.hermes/plugins/lyriel/, restart the gateway.
v0 limitations
- In-process pending map. If Hermes restarts mid-flight, pending callback tokens are lost. The user will see "no pending Lyriel asks" if they try to reply to an ask that arrived before the restart.
- One-pending-per-ask. No threading of replies; if multiple asks are pending, the LLM disambiguates via ask_id (the surface message contains it).
- Single user per Hermes instance. The plugin reads one
telegram_chat_idand oneLYRIEL_API_KEY. Multi-user Hermes setups aren't supported yet.
Publishing
The package is lyriel-hermes on PyPI. Prerequisites: a PyPI account
with maintainer rights on the package, and a PyPI API token in
~/.pypirc (or pass it via --username __token__).
# 1. Bump the version in pyproject.toml (and lyriel_hermes/plugin.yaml
# if the Hermes-side version should track).
# 2. Build sdist + wheel into dist/.
uv build
# 3. Upload to PyPI.
uvx twine upload dist/*
After publish, the install paste-prompt (pip install lyriel-hermes && lyriel-hermes install) resolves to the new version. Existing
installs upgrade via pip install --upgrade lyriel-hermes; the
symlink in ~/.hermes/plugins/lyriel keeps pointing at the package,
so the next Hermes restart picks up the new code automatically.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lyriel_hermes-0.1.0.tar.gz.
File metadata
- Download URL: lyriel_hermes-0.1.0.tar.gz
- Upload date:
- Size: 26.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
573ae0a91245a5a5ef7f27a6c017c8188cd3e2206b4dad8ee84ac7c97a123e2d
|
|
| MD5 |
c6ea131cf8150ab45c362032679fa1ff
|
|
| BLAKE2b-256 |
64f88c5ce9c046fa653eaec19c15c56ec84e3b5a187d14fbdd6d52e82e142625
|
File details
Details for the file lyriel_hermes-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lyriel_hermes-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b943cb95e268315c4da9e8203f67064b2435527358db03cb3faef9deea277d03
|
|
| MD5 |
985914b44791df85de5aecb5dde9a979
|
|
| BLAKE2b-256 |
57f58d68588c9900c4fd56f70b9a0620e8ab9602823bf14848fc8e651ceb1aac
|