Hermes Agent Webhooks: Trigger Agent Runs from External Events

hermes-agentintermediate8 min readVerified Jul 26, 2026
Hermes Agent Webhooks: Trigger Agent Runs from External Events

This guide covers how to configure Hermes Agent webhooks to receive events from external systems like GitHub, GitLab, Jira, and Stripe, validate their signatures, transform payloads, and route agent responses. It is intended for operators who want to move beyond chat-based demos and build practical, event-driven agent workflows.

What You Need

Before setting up webhooks, ensure you have the following:

  • A running Hermes Agent instance (self-hosted or managed cloud). The webhook integration is part of the Hermes gateway, not a separate service.
  • Access to the command line to run hermes commands.
  • The ability to set environment variables or modify configuration files for the Hermes gateway.
  • For production use, a publicly accessible HTTPS endpoint (or a tunnel like ngrok for local testing).
  • An external system that can send HTTP POST requests (e.g., GitHub, GitLab, Jira, Stripe, or a custom script).
  • Basic familiarity with HMAC signatures and JSON payloads.

How Hermes Webhooks Work

Hermes webhooks provide an HTTP server that listens for POST events on a configurable route. When an event arrives, Hermes validates the payload using an HMAC signature, transforms the payload into an agent task or notification, and then routes the agent's response back to a chat platform, log, comment thread, or follow-up tool.

The core flow is:

  1. An external system sends an HTTP POST to https://your-host/webhooks/<route-name>.
  2. Hermes validates the request using a shared secret (HMAC-SHA256 by default).
  3. If valid, Hermes applies any event filters and prompt templates associated with that route.
  4. The agent processes the payload and generates a response.
  5. The response is delivered according to the route's configured delivery path (e.g., Slack message, GitHub comment, email).

This is fundamentally different from cron-based scheduling. Cron is for periodic checks. Webhooks are for immediate, event-driven reactions. Use webhooks when a pull request opens, a payment fails, a support ticket changes, or an internal tool emits an event that should produce a focused agent run.

Setup Path

Diagram: Setup Path

Step 1: Enable the Webhook Platform

The webhook server is part of the Hermes gateway. Enable it by running:

hermes gateway setup

Alternatively, set the environment variable:

export WEBHOOK_ENABLED=true

This starts the HTTP server on the default port 8644. You can change the port by setting WEBHOOK_PORT or using your configured gateway value if you changed it.

Step 2: Set a Strong Webhook Secret

Security is critical. Set a strong, random HMAC secret:

export WEBHOOK_SECRET=your-strong-random-secret-here

This secret is used to sign and verify all incoming webhook payloads. Without it, anyone who knows your webhook URL could send arbitrary events to your agent. The official documentation warns: "Avoid unauthenticated routes outside local testing."

You can also set per-route secrets for different trust levels. For example, a GitHub webhook might use one secret while a Stripe webhook uses another. This is configured in the route definition.

Step 3: Create a Named Route

Routes are the core of webhook configuration. Each route has a name, a prompt template, optional event filters, and a delivery path. Create a route using the CLI:

hermes webhook subscribe <route-name> --prompt "Your prompt template here"

For example, to create a route for GitHub pull requests:

hermes webhook subscribe github-prs --prompt "Summarize the risk of this pull request and assign review steps."

Routes can also be defined in a configuration file (e.g., YAML or JSON). The exact file format depends on your Hermes version, but the structure typically includes:

  • name: The route identifier.
  • prompt: The instruction template for the agent.
  • event_filter: Optional criteria to match specific event types or payload fields.
  • secret: Optional per-route HMAC secret.
  • delivery: Where to send the agent's response (e.g., Slack channel, GitHub issue comment, email).

Step 4: Verify the Server

Before pointing external services at your webhook, verify the server is running:

curl http://localhost:8644/health

A successful response indicates the gateway is up and the webhook server is listening. If you get a connection refused error, check that the gateway process is running and that the port is not blocked by a firewall.

Step 5: Point the External Service at Your Webhook

Configure your external system to send POST requests to:

https://your-host/webhooks/<route-name>

Replace your-host with your actual domain or IP address. For local testing, use a tool like ngrok to expose your local server:

ngrok http 8644

Then use the ngrok URL (e.g., https://abc123.ngrok.io/webhooks/github-prs) in your external service's webhook settings.

Step 6: Send a Test Payload

Send a test payload to confirm the integration works. For a route named test-route:

curl -X POST https://your-host/webhooks/test-route \
  -H "Content-Type: application/json" \
  -H "X-Hub-Signature-256: sha256=<computed-signature>" \
  -d '{"event": "test", "data": {"key": "value"}}'

You need to compute the HMAC signature using your secret. For example, in Python:

import hmac
import hashlib

secret = b"your-strong-random-secret-here"
payload = b'{"event": "test", "data": {"key": "value"}}'
signature = hmac.new(secret, payload, hashlib.sha256).hexdigest()
print(f"sha256={signature}")

Once sent, check the Hermes logs to confirm the payload was received, validated, and transformed into an agent task.

Route Design Best Practices

The official documentation emphasizes: "Do not send every event to one giant prompt." Instead, create small, named routes with specific event filters and specific instructions. This keeps the agent grounded and makes failures easier to debug.

Separate Routes for Different Event Types

Create distinct routes for different event sources:

  • github-prs: For pull request events.
  • billing-events: For Stripe disputes or payment failures.
  • customer-forms: For internal form submissions.
  • alerts: For monitoring alerts from tools like PagerDuty.

Each route should have a focused prompt that tells the agent exactly what to do with that specific type of event.

Per-Route Secrets

When different systems have different trust levels, use per-route secrets. This limits the blast radius if one secret is compromised. Configure the secret in the route definition:

routes:
  - name: github-prs
    secret: github-specific-secret
    prompt: "Summarize the risk of this pull request and assign review steps."
  - name: stripe-disputes
    secret: stripe-specific-secret
    prompt: "Notify the team and draft a dispute response checklist."

Log Payload Shape During Testing

During initial setup, log the full payload shape to understand what data the agent will receive. Once the route is stable, remove noisy debugging to keep logs clean. You can do this by setting a debug: true flag on the route during testing, then removing it.

Advanced Configuration

Diagram: Advanced Configuration

Event Filters

Event filters allow you to process only certain events from a source. For example, from GitHub you might only want to handle pull_request events with action: opened. Filters are defined as JSONPath or simple key-value matches in the route configuration.

Delivery Paths

The agent's response can be delivered to multiple destinations. The official documentation mentions: "Responses can be routed back to chat platforms, comments, logs, or follow-up tools." Common delivery paths include:

  • Slack or Discord channels.
  • GitHub or GitLab issue/PR comments.
  • Email via SMTP.
  • A log file or database.
  • Another webhook endpoint.

Configure the delivery path in the route definition. For example:

routes:
  - name: github-prs
    delivery:
      type: slack
      channel: "#pr-reviews"

HMAC Signature Validation

Hermes validates incoming webhooks using HMAC-SHA256 by default. The signature is expected in the X-Hub-Signature-256 header (for GitHub compatibility) or a custom header. If the signature does not match, Hermes rejects the request with a 401 status.

For services that don't support HMAC signing (e.g., custom scripts), you can use the INSECURE_NO_AUTH option, but only for temporary local testing. The official documentation states: "Only for temporary local testing. Public webhook routes should validate signatures."

Common Setup Issues

The Integration Appears Enabled but Nothing Happens

If you've enabled the webhook platform and created a route, but events are not triggering agent runs, restart the Hermes gateway or start a fresh Hermes session after config changes. The gateway may be caching an old configuration.

hermes gateway restart

Credentials Work in One Shell but Not in the Gateway

This is a common issue. Check the active Hermes profile and where the gateway process reads its environment. The gateway may be running under a different user or systemd service that doesn't inherit your shell's environment variables. Ensure the WEBHOOK_SECRET and other variables are set in the gateway's environment (e.g., in a .env file or systemd unit file).

The Workflow Is Too Broad

If the agent is producing irrelevant or overly generic responses, your route prompt is too broad. Split it into smaller routes, skills, or prompts with one expected outcome each. For example, instead of one route for all GitHub events, create separate routes for issues, pull requests, and pushes.

Troubleshooting

Health Check Fails

If curl http://localhost:8644/health fails, check:

  • The gateway process is running: ps aux | grep hermes.
  • The port is not in use by another service: netstat -tulpn | grep 8644.
  • Firewall rules are not blocking the port.

Signature Validation Errors

If you see 401 responses in the logs, the HMAC signature is incorrect. Verify:

  • The secret matches on both sides.
  • The payload body is exactly as sent (no extra whitespace or encoding differences).
  • The signature header name matches what Hermes expects (X-Hub-Signature-256 by default).

Payload Not Transformed Correctly

If the agent receives unexpected data, check the route's event filter and prompt template. Log the raw payload during testing to understand its structure, then adjust the prompt accordingly.

Going Further

Once webhooks are working, explore these related topics:

  • Add tools to Hermes: Understand how tools and MCP servers become available to the agent, enabling it to take actions beyond generating text.
  • GitHub integration: Connect automation outcomes to code, pull requests, and repository reports.
  • Background monitoring: Use Hermes for continuous monitoring tasks that don't require a user to be present.
  • Schedule tasks with Hermes: Combine webhooks with cron-based scheduling for hybrid workflows.
  • Pricing and FlyHermes: Compare self-hosting with the managed cloud option when uptime and maintenance matter.

The official documentation also lists integrations with Telegram, Discord, Slack, WhatsApp, and Signal, which can serve as delivery paths for webhook-triggered agent responses.

Newsletter

The #1 AI Newsletter

The most important ai updates, guides, and fixes — one weekly email.

No spam, unsubscribe anytime. Privacy policy

Related Guides