Skip to content

Deployment

Deploying the integration is three steps: create a DonutChat bot, run a Hermes Agent, and run the bridge that connects them. You can run the bridge locally for testing or as a flag-gated ECS service in production.

  • A DonutChat bot and its donutbot_… token (created in the app or via the bot management API).
  • A reachable Hermes Agent instance with the OpenAI-compatible API server enabled.
  • The chat(s) the bot should answer in, with the bot added as a member.
  1. Create a bot in the DonutChat app (Bots → New) and copy its donutbot_… token — it is shown once.
  2. Add the bot to each chat it should respond in.
  3. Set the bot’s trigger mode per chat:
    • mention (default) — replies only when @mentioned.
    • all — replies to every message (use for 1:1 DMs).
    • manual — never auto-replies.

See Bot Receive for the full trigger-mode semantics.

Stand up Hermes per its own docs and enable the API server:

  • API_SERVER_ENABLED=true (listens on port 8642 by default).
  • Set API_SERVER_KEY — this becomes the bridge’s HERMES_API_KEY.

The bridge is a subcommand of the main binary. It is stateless (no database) and reads all settings from the environment — see the Configuration reference.

Terminal window
export DONUT_BOT_TOKEN="donutbot_…"
export DONUT_STREAM_URL="wss://api.donutchat.com/bots/v1/stream"
export DONUT_SEND_URL="https://api.donutchat.com/bots/v1/messages"
export DONUT_TYPING_URL="https://api.donutchat.com/bots/v1/typing" # optional; enables the thinking indicator
export HERMES_BASE_URL="http://hermes-host:8642"
export HERMES_API_KEY=""
export HERMES_MODEL="hermes"
go run main.go hermes-bridge

On start the bridge validates its configuration (missing required values fail fast with a clear error), connects to the bot stream, and begins forwarding triggered messages. Stop it with SIGINT/SIGTERM for a graceful shutdown.

The bridge ships as a flag-gated ECS Fargate service defined in infra/. It is disabled by default; enable it once a Hermes box is reachable. Secrets are pulled from AWS Secrets Manager, never baked into the task definition.

Set the Terraform variables and apply:

terraform.tfvars
hermes_bridge_enabled = true
hermes_bridge_bot_token = "donutbot_…" # sensitive → Secrets Manager
hermes_bridge_api_key = "" # sensitive → Secrets Manager
# Endpoints (sensible production defaults already set)
hermes_bridge_stream_url = "wss://api.donutchat.com/bots/v1/stream"
hermes_bridge_send_url = "https://api.donutchat.com/bots/v1/messages"
hermes_bridge_typing_url = "https://api.donutchat.com/bots/v1/typing"
hermes_bridge_hermes_base_url = "http://hermes.internal:8642" # private address
hermes_bridge_model = "hermes"
Terminal window
cd infra
terraform apply

Terraform creates the ECS service, task definition, and the hermes_bridge secret holding bot_token and hermes_api_key. The non-secret URLs and model are passed as plain environment variables on the task.

  1. In a chat the bot belongs to (trigger mode mention), post @yourbot hello.
  2. You should see the bot’s typing indicator, then a markdown reply attributed to the bot with a BOT badge.
  3. Stop the Hermes box and @mention again — you should get the graceful fallback message, not silence and not a raw error.

If something is off, see Operations & troubleshooting.