Integrating the Pebble Index 01 with my Hermes Agent A developer integrated the Pebble Index 01 voice ring with the Hermes Agent framework by using webhooks instead of MCP servers, because Hermes' MCP server is stdio-only and cannot create new conversations. The setup uses a Cloudflare Tunnel to expose a proxy script on a Mac mini, which forwards transcriptions to Hermes for full agent processing and delivers responses to Telegram. I recently got the Pebble Index 01 https://repebble.com/index . It’s a slim aluminum ring with a single button and a mic, no screen, and no notifications. You press and hold, speak, it transcribes what you said, and sends it to the Pebble app for processing. I’ve hooked it up using the app to Apple Reminders todos including time triggers, and shopping lists , Apple Calendar to add entries , and Obsidian speak note content, it lands in my vault . It works and is low-friction. The number of times I’ve forgotten something in seconds because I didn’t have my phone on me is now zero. But sometimes a thought is too complex for a pre-built action. Sometimes it needs actual reasoning, or tool access, or the ability to dig into something I’ve built, a script, an API, a research thread. For those moments I run Hermes Agent https://hermes-agent.nousresearch.com/ , an open-source autonomous agent framework on my Mac mini. It has access to my tools, my memory, my skills. It can read my knowledge base, write code, send context-aware messages, and more. And when I’m out and about, sometimes I have a clarifying thought on how to move something forward. So the natural question: why not have the ring talk to Hermes using the secondary gesture of a double click and hold? Hermes’ MCP server, and why it doesn’t work hermes-mcp-server-and-why-it-doesnt-work Hermes can expose an MCP server, with messaging tools like conversations list , messages send and events poll . On paper that sounds like the right interface, with Pebble supports MCP servers in its cloud agent, and the idea of connecting the two felt obvious. It doesn’t work for two reasons: Hermes MCP is stdio-only. Pebble needs an HTTP or SSE endpoint. Bridging stdio to HTTP adds latency and complexity I don’t want for something that should feel instant. The available tools don’t create new conversations. The MCP server lets you read and write messages on existing platform connections. It doesn’t start a new Hermes thread with full agent access. So I went a different direction. Webhooks instead of MCP. The architecture the-architecture The ring sends a voice note. The Pebble app transcribes it locally and POSTs it to my tunnel URL. A proxy script on my Mac receives the multipart POST, extracts the transcription, signs an HMAC, and forwards JSON to Hermes. Hermes runs the full agent with all its tools and delivers the response to a Telegram forum topic. I reply in that topic. The conversation continues. Simple, low latency, full agent access. Here’s how I set it up Setting it up setting-it-up Cloudflare Tunnel cloudflare-tunnel My Mac mini runs at home and is exposed via a Tailnet https://tailscale.com/docs/concepts/tailnet to my other personal devices. The ring’s app can’t reach it directly. Enter Cloudflare Tunnel https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/ . It’s a lightweight daemon that creates an outbound WebSocket connection to Cloudflare’s edge. No port forwarding, no exposed services, no firewall holes. Cloudflare handles the HTTPS termination, the routing, and the certificate management. Create a config file at ~/.cloudflared/pebble-index.yaml : But there’s a gotcha I hit: Cloudflare Tunnel’s ingress rules need explicit hostname matching for domain-based routing. The bare service: directive won’t route to your backend when you’re using a custom domain. I had to use: And I needed to write that to ~/.cloudflared/config.yaml , not the named config file. Cloudflared reads config.yaml for ingress rules, not the tunnel-specific YAML. That one confused me for a while. DNS route: That CNAME record creates https://your-custom.domain.com , which now routes to my proxy on port 8788. DNS propagation takes 1-3 minutes. Converting and forwarding the payload to Hermes converting-and-forwarding-the-payload-to-hermes Pebble sends webhooks as multipart/form-data , a format designed for file uploads rather than API payloads. The fields are: - transcription — the transcribed text - audio — the raw M4A audio file optional - recordedAt — Unix timestamp in milliseconds - client — always “ring” Hermes expects JSON. The proxy bridges the gap. The proxy reads the HMAC secret from the config file or an environment variable, starts listening on port 8788, and when it receives a multipart POST it extracts the transcription, signs the payload, and forwards JSON to Hermes. No dependencies, pure stdlib. The Hermes route the-hermes-route Hermes webhooks work by defining routes in config.yaml . Each route matches an incoming POST, runs the agent, and delivers the response. A few notes on the configuration: - prompt uses dot-notation to access the JSON payload. {transcription} pulls the transcription field from the incoming JSON. - deliver: telegram sends the response to Telegram. - deliver extra with chat id and message thread id routes to a specific forum topic in the group I use to interact with my agents. Replace both values with your own. - secret is an HMAC key for request authentication. You might wonder why I didn’t use hermes webhook subscribe pebble-input --deliver telegram , the CLI way to create a webhook subscription. The CLI has a routing bug: --deliver telegram on a webhook subscription sends the agent’s response back to the caller, not to the target Telegram chat. Routes defined directly in config.yaml don’t have this problem. Pebble app configuration pebble-app-configuration In the Pebble app: 1. Go to Index → Settings 2. Set Double-click & hold to “Webhook only” 3. Set the Webhook URL to https://your-custom.domain.com your domain, no path appended 4. Set What to send to “Transcription” Double press the ring button, hold, speak. Within 3-5 seconds your thought arrives in Telegram’s Index 01 forum topic. Hermes runs the agent with full tool access and responds. You reply in the same topic to continue the conversation. The auto-start services the-auto-start-services Both the proxy and the tunnel run as macOS launchd services. They survive reboots automatically. Proxy plist: ~/Library/LaunchAgents/com.pebble.proxy.plist Tunnel wrapper: ~/.hermes/scripts/pebble-tunnel-start.sh Tunnel plist: ~/Library/LaunchAgents/com.pebble.tunnel.plist Load them: Both will start automatically on boot. The proxy catches Pebble webhooks, routes them to Hermes, and the agent runs with full access to everything: browsing, code execution, file manipulation, calendar, reminders, API calls. Why tihs matters why-tihs-matters The Pebble ring captures thoughts with almost zero friction. Simple thoughts route to Apple Reminders for tracking, medium ones to Obsidian for reference, and complex thoughts to Hermes where they actually get processed. Thoughts like “research the best way to batch-process the PDFs in my Google Drive” or “write a script to monitor my Apify accounts sending” need more than a todo item. They need reasoning and tool access, and that’s what closing the loop to Hermes gives you. By connecting the ring to Hermes, I’ve closed the loop. Simple thoughts go to Apple Reminders. Medium thoughts go to Obsidian. Complex thoughts go to Hermes. The ring stays the input method, the processing is context-aware. The pipeline is: