← Home

Guide

Connect Webhooks to Your AI Agent

Webhooks are the other direction. Instead of a person messaging the agent, a system does — a deploy finishes, a payment fails, an alert fires, and the agent picks it up and acts.

What This Is Good For

An event in another system can start a conversation with your agent instead of a person having to. On a bot hosted here it is one switch on the instance card; running Hermes yourself, it is a config block and an open port. A few things people actually build:

  • A monitoring alert arrives and the agent triages it and messages you on Telegram with a summary.
  • A pull request opens and the agent reviews the diff and posts back.
  • A payment fails and the agent drafts the customer email for you to check.
  • A form submission arrives and the agent files it where it belongs.

Turn On the Webhook Server

On a bot hosted here, skip this section — turning on Receive Webhooks does it for you, config and restart included. Read on if you run Hermes yourself.

Add the webhook platform to your agent's config file, then restart the bot once so the gateway brings the listener up:

platforms:
  webhook:
    enabled: true
    extra:
      port: 8644
      secret: "your-strong-secret"

Put it in the config file rather than in a .env. Setting WEBHOOK_ENABLED in a .env does start the listener, but the hermes webhook commands read the config file only — so they refuse to run, and you are left editing routes by hand for no reason.

Set the secret. An open webhook endpoint is an open door to your agent's time and your model credits, and anything that can reach the port can make it do work.

Define Routes

A route maps an incoming request to what the agent should do with it. You can define them in the config file, or create them on the fly:

hermes webhook subscribe <route-name> --secret <route-secret>

A new route goes live immediately, with no restart, and answers at /webhooks/<route-name> — not at /<route-name>, which is an easy one to lose an afternoon to. Give every route a real secret: the INSECURE_NO_AUTH placeholder is refused for anything but loopback traffic, so a route left on it will not serve a real sender.

Think of the route as the instruction attached to the payload. The sending service knows nothing about your agent; the route is where you say what an incoming GitHub event or alert actually means and what should happen next.

Make It Reachable

A hosted bot's own ports are deliberately unreachable from the internet, so the webhook listener alone is not enough — something has to stand in front of it. On a bot hosted here, that is one switch: open the Use in Another App panel on your instance card and turn on Receive Webhooks. You get an HTTPS address, and each route answers at that address plus its name. Turning it on restarts your bot once.

Nothing is exposed by doing it. The address is served by us, not by your bot — we pass each delivery straight through to the webhook server inside your instance, signature headers untouched, and your bot checks the signature against that route's secret exactly as it would if the sender had reached it directly. A request without a valid signature never reaches your agent, so it costs you nothing.

Running Hermes yourself, you control the network instead: expose the webhook port over HTTPS, or put a tunnel such as Cloudflare Tunnel in front of it, and the sending service reaches your agent directly.

Do not expose the port without the secret set. Bots scan for open endpoints constantly, and an unauthenticated webhook that triggers an AI agent is an expensive thing to leave lying around.

Test It

Send a request yourself before wiring up the real service — a signed POST with a small JSON body tells you whether the server is up, whether the signature matches and whether the route fires, in one go. A correctly signed request comes back as accepted; an unsigned one is rejected; and a request to the wrong path returns a not found, which is the quickest way to catch a missing /webhooks/ prefix. Once that works, point the real service at the same URL — on a self-hosted install, or through whatever you have made it reachable with.

Troubleshooting

  • The service reports a delivery failure. The endpoint is not reachable from the internet, or the tunnel dropped.
  • Requests are rejected. The secret does not match what the sender is sending.
  • Delivered but nothing happens. No route matches the incoming path, so the payload lands nowhere.
  • The agent misreads the payload. Say explicitly in the route what the data is and what to do with it — a raw JSON blob with no instruction gets guesswork.
  • Unexpected usage. Something is calling your endpoint. Rotate the secret.

Need a Hand?

Contact support from your dashboard and we will help you work out which route fits what you are building — the Endpoint on a hosted bot, or the webhook server if you are running Hermes yourself.