A Hermes Agent platform plugin for Blooio — a hosted iMessage API. Send and receive real iMessages (with automatic SMS/RCS fallback) over a REST API and inbound webhooks, without running a Mac yourself. This is the standalone twin of the built-in BlueBubbles and Photon iMessage channels.
Connect it in one click with the official "Blooio for Hermes" OAuth app
(hermes blooio login) — talks to the Blooio v4 API. An API key is
supported as a headless/CI fallback.
This plugin is distributed standalone (not bundled into NousResearch/hermes-agent).
Install it one of two ways, then enable it — plugins are opt-in.
pip install "git+https://github.com/blooio/hermes-blooio"
hermes plugins enable blooioHermes discovers the plugin through its hermes_agent.plugins entry point on the
next startup. hermes plugins list should show blooio once installed.
git clone https://github.com/blooio/hermes-blooio
cp -r hermes-blooio/src/hermes_blooio ~/.hermes/plugins/blooio
pip install aiohttp httpx # runtime deps
hermes plugins enable blooioHermes scans ~/.hermes/plugins/<name>/ at startup and reads the bundled
plugin.yaml + adapter.py.
- Auth = OAuth (default).
hermes blooio loginruns Authorization Code + PKCE (S256) on a loopback redirect with the official Blooio app, storing rotating tokens in~/.hermes/auth.jsonand auto-refreshing them. SetBLOOIO_API_KEYto skip the browser login (headless/CI). Multi-org tokens are scoped withX-Organization-Id(BLOOIO_ORG_ID). - Inbound = webhooks. Runs a small
aiohttpwebhook server and receives Blooio events at/blooio/webhook. Each event is HMAC-SHA256 signature-verified (Stripe-styleX-Blooio-Signature: t=<ts>,v1=<hex>over"{ts}.{rawBody}"), deduped onmessage_id, parsed from the v4 typed envelope, and dispatched to the agent. - Outbound = REST (v4). Replies POST to
/chats/{chat_id}/messageson the Blooio v4 API (https://api.blooio.com/v4); cron / addressed sends usePOST /messageswithto(+ optionalfrom). - Reactions, typing, read receipts each map to a dedicated v4 chat endpoint.
- Attachments are HTTPS URLs — remote URLs pass straight through; local files
are served from the same webhook server behind
BLOOIO_PUBLIC_URL.
Blooio delivers inbound messages via webhooks and fetches local-file attachments
from a public URL, so Hermes must be reachable at a public HTTPS hostname.
Expose it with Cloudflare Tunnel, Tailscale Funnel, or ngrok and set
BLOOIO_PUBLIC_URL.
hermes blooio login # one-click OAuth (opens the browser)hermes blooio status / hermes blooio logout manage the stored credentials.
Then point Blooio at your public URL:
export BLOOIO_PUBLIC_URL="https://my-tunnel.example.com"
export BLOOIO_AUTO_REGISTER_WEBHOOK=true # auto-create webhook + capture its secret
export BLOOIO_ALLOWED_USERS="+15551234567" # allowlist sendersHeadless/CI without a browser? Skip login and use an API key instead:
export BLOOIO_API_KEY="api_..."
export BLOOIO_WEBHOOK_SECRET="whsec_..." # from the webhook you create
export BLOOIO_PUBLIC_URL="https://my-tunnel.example.com"Then, in the Blooio dashboard, add a webhook pointing at
<BLOOIO_PUBLIC_URL>/blooio/webhook (type: all) and copy its signing secret into
BLOOIO_WEBHOOK_SECRET. (Or set BLOOIO_AUTO_REGISTER_WEBHOOK=true to have the
plugin register the webhook and capture the secret on connect.)
See src/hermes_blooio/plugin.yaml for the
complete environment-variable reference.
Three levels, fastest first. The first two exercise the real adapter (webhook server, signature verification, event parsing, outbound REST) without needing the Hermes core or an LLM.
Boots the adapter's webhook server, signs a synthetic Blooio message.received
event, POSTs it in, and shows the adapter verify → parse → dispatch it — plus
tampered-signature rejection and dedup.
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
python demo/echo_demo.py loopbackA real iMessage echo bot built on just this plugin: every message you text the
number is echoed back through the Blooio API. Needs BLOOIO_API_KEY,
cloudflared (brew install cloudflared), and the number attached to your key.
export BLOOIO_API_KEY=api_...
./demo/run_live.sh # starts a cloudflared tunnel, registers the webhook, echoesrun_live.sh provisions the public HTTPS URL for you; then text the number and
watch it reply. (Under the hood you can also run python demo/echo_demo.py live
if you already have BLOOIO_PUBLIC_URL.)
The actual product experience: an LLM-backed agent answering over iMessage.
pip install "git+https://github.com/blooio/hermes-blooio"
hermes plugins enable blooio
export BLOOIO_API_KEY=api_...
# expose Hermes publicly (Cloudflare Tunnel / ngrok) and point BLOOIO_PUBLIC_URL at it:
export BLOOIO_PUBLIC_URL=https://your-tunnel.example.com
export BLOOIO_AUTO_REGISTER_WEBHOOK=true
hermes gateway setup # configure platforms / LLM if not already done
hermes gateway # run in foreground — now text the numberpip install -e ".[dev]"
ruff check src tests
pytest -qMIT — see LICENSE.