Skip to main content

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 (hermes in a terminal): the dispatch is injected as the next message in your conversation via Hermes's inject_message primitive. 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.
  • Two LLM tools โ€” lyriel_send_ask and lyriel_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

  1. 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_id is already set, the plugin will fall back to that; you can skip the plugins.entries.lyriel block in that case.

  2. 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
    
  3. Restart the Hermes gateway so the plugin is loaded:

    # however you run Hermes โ€” systemd restart, supervisor restart, etc.
    
  4. 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_id and one LYRIEL_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lyriel_hermes-0.1.0.tar.gz (26.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lyriel_hermes-0.1.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

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

Hashes for lyriel_hermes-0.1.0.tar.gz
Algorithm Hash digest
SHA256 573ae0a91245a5a5ef7f27a6c017c8188cd3e2206b4dad8ee84ac7c97a123e2d
MD5 c6ea131cf8150ab45c362032679fa1ff
BLAKE2b-256 64f88c5ce9c046fa653eaec19c15c56ec84e3b5a187d14fbdd6d52e82e142625

See more details on using hashes here.

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

Hashes for lyriel_hermes-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b943cb95e268315c4da9e8203f67064b2435527358db03cb3faef9deea277d03
MD5 985914b44791df85de5aecb5dde9a979
BLAKE2b-256 57f58d68588c9900c4fd56f70b9a0620e8ab9602823bf14848fc8e651ceb1aac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page