Skip to content
donutchat.com

Connect a Hermes agent

Run your own Hermes Agent as a DonutChat bot. People message the bot in a chat, and the agent answers in the thread under their message. The hermes-donut plugin connects DonutChat to the Hermes gateway the same way Hermes connects to Slack or Discord.

Because the gateway delivers the replies, the agent can also post after its turn has ended. When it starts a long job in the background and says it will report back, the result appears in the same thread when the job finishes. Cron jobs and Hermes’ send_message tool post to DonutChat the same way.

  • A computer that stays on, with Hermes Agent installed and set up with a model. Use a recent Hermes version: older ones can’t load platform plugins.
  • A DonutChat account, to create the bot.

The plugin makes only outgoing connections, so you don’t need a public address, an open port or a web server.

  1. Create an API bot: Add a bot > Developer options > Build an API bot (web app: Create bot). Leave Trigger mode on When mentioned while you test.
  2. Copy the API token when it appears. It starts with donutbot_ and is shown only once.
  3. Add the bot to the group chats where it should answer.

To talk with your agent one to one, start a private conversation with the bot. It receives every message you send there, without an @mention.

On the computer that runs Hermes:

Terminal window
hermes plugins install DonutChat/hermes-donut --enable

The plugin needs no extra packages. To update it later, run hermes plugins update.

  1. Add the token to ~/.hermes/.env:

    ~/.hermes/.env
    DONUT_BOT_TOKEN=donutbot_YOUR_TOKEN_HERE
    DONUT_ALLOWED_USERS=

    hermes gateway setup asks for the same values, if you prefer.

  2. Restart the gateway, and keep it running:

    Terminal window
    hermes gateway restart
  3. In a chat with the bot, send a message that @mentions it. The gateway log shows message from, your name and your user ID. Hermes doesn’t answer yet, because nobody is allowed.

  4. Put your user ID in DONUT_ALLOWED_USERS and restart the gateway again. To allow several people, separate their IDs with commas.

Hermes answers only the people in DONUT_ALLOWED_USERS. To answer everyone whose messages reach the bot, set DONUT_ALLOW_ALL_USERS=true instead. Read Keep your agent safe first.

VariableDefaultDescription
DONUT_BOT_TOKENThe bot’s API token. Required.
DONUT_ALLOWED_USERSDonutChat user IDs that Hermes answers, separated by commas.
DONUT_ALLOW_ALL_USERSfalseAnswer everyone whose messages reach the bot.
DONUT_HOME_CHANNELChat ID where cron results and notices go. You can also send /sethome in a chat.

While Hermes works, one reply in the thread shows its steps, such as 💻 Running …, and updates as it goes. To hide it, add this to ~/.hermes/config.yaml and restart the gateway:

~/.hermes/config.yaml
display:
platforms:
donut:
tool_progress: "off"

The other values are new, all (the default) and verbose. To switch from a chat instead, also set display.tool_progress_command: true. Then /verbose cycles through the modes.

Hermes asks before it runs a command it considers risky. It posts the command in the thread. Answer /approve or /deny in that thread, with When mentioned, as @yourbot /approve. To let Hermes decide by itself, change the approval mode in ~/.hermes/config.yaml:

~/.hermes/config.yaml
approvals:
mode: smart
ModeWhat Hermes does
manualAsks in the thread before every risky command. This is the default.
smartA model approves commands that look safe and refuses the rest, without asking.
offRuns every command without a check.

With off, anyone Hermes answers can run any command on that computer.

Run hermes gateway as a service, so it starts with the computer and restarts if it stops:

Terminal window
hermes gateway install
  • One connection. The plugin keeps the event stream open and reconnects with a growing delay. After a reconnect it asks for the events it missed and skips any it already handled. Replay covers at most the bot’s last 100 events from the past 5 minutes.
  • One conversation per thread. A message starts a thread under itself, and each thread is its own Hermes session. A follow-up in a thread continues that conversation, and a new message starts a fresh one.
  • Thread and linked messages. The first time Hermes sees a thread, the plugin also gives it the thread’s first message, even when someone else wrote it. When a message links to another message in the same chat, it gives Hermes that message too.
  • Files. The plugin downloads attachments with the bot token and hands images and documents to Hermes. Bots can’t upload files yet, so files Hermes sends back arrive as text.
  • Replies. Answers are thread replies that update while Hermes writes. Messages without a thread, such as cron results in the home chat, are posted as ordinary bot messages. A reply holds at most 80,000 UTF-8 bytes, so longer answers continue in further replies.

The bot’s trigger mode decides which messages reach Hermes, and chat owners and managers can change it for their chat. With When mentioned, every follow-up in a thread must @mention the bot too. Event stream has the exact rules.

For an agent other than Hermes, donut_hermes.py shows a small script that sends each message to an OpenAI-compatible /v1/chat/completions endpoint and streams the answer into the thread. It answers only during that request, so the agent can’t post results later.

  • Treat message text as untrusted input. Anyone who can @mention the bot in its chats can send text to your agent, and anyone who can open the bot’s profile can start a private conversation with it. Keep DONUT_ALLOWED_USERS to people you trust.
  • Hermes can run commands and use its other tools for anyone it answers. Give the agent only the tools it needs.
  • The agent also reads a thread’s first message and linked messages as context, and other members may have written them.
  • Never put the bot token or agent credentials in prompts, replies or logs. If the token leaks, regenerate it and update ~/.hermes/.env.
  1. In a chat with the bot, send a message that @mentions it. The answer appears in the thread under your message.
  2. Reply in that thread, @mentioning the bot again. The answer takes the earlier turns into account.
  3. Ask for something that takes a while, such as “run sleep 60; date in the background and tell me when it’s done”. Hermes answers right away, and posts the result in the same thread about a minute later without another message from you.
  4. Send a screenshot and ask the bot to describe it.
  5. Restart the gateway. It reconnects and doesn’t answer an earlier message again.
ProblemWhat to check
No message from line in the gateway logThe bot is in the chat and its trigger mode isn’t Manual only. With When mentioned, the message must @mention the bot’s username; @everyone and @here don’t count. Check hermes gateway status for the DonutChat platform.
message from appears, but Hermes doesn’t answerYour user ID isn’t in DONUT_ALLOWED_USERS. Add it and restart the gateway.
DonutChat rejected the bot tokenThe token is wrong or was regenerated, or the bot is paused. Copy the token exactly as the app showed it, including donutbot_.
The connection drops every few secondsAnother integration with the same token is running. Stop it.
Follow-ups in a thread are ignoredWith When mentioned, every follow-up must @mention the bot. In any mode, a reply that mentions only someone else doesn’t reach the bot.
/approve does nothingWith When mentioned, write @yourbot /approve in the thread.
A message sent while the gateway was stopped isn’t answeredReplay covers only the last 5 minutes. Send the message again.

For every error code, see Errors.