IntegrationsInbound webhooks

Inbound webhooks

Let an external system POST a signed event to a per-webhook URL and have a Naumu agent act on it inside your space.

Updated August 3, 20263 min read

An inbound webhook turns an outside event - a GitHub issue, a Stripe charge, a form submission, anything that can send an HTTP request - into agent action inside one of your spaces. You give the external system a private URL to POST to; each delivery runs an agent against the payload using instructions you wrote in advance.

This page is for developers wiring an external service into Naumu. For the mirror direction - Naumu driving your own agent runtime with signed outbound webhooks - see external agents.

Webhooks belong to a space, not to your account. Open the space's settings and choose Webhooks.

Create a webhook

  1. In the space's settings, open Webhooks and select New webhook.
  2. Write a prompt template - the instructions the agent follows when a delivery arrives, such as "When a GitHub issue arrives, summarise it and create a task node." The incoming payload is handed to the agent as data to examine, never as commands, so a hostile payload can't rewrite what the agent does.
  3. Pick a target:
    • One-off run (ephemeral) - a fresh agent runs for that single delivery and then goes away.
    • An existing space agent - route deliveries to one of your space's agents so they land under its identity.
  4. Optionally pick one or more topics to file deliveries into. Search and select them in the topic picker; the chosen topics show as chips you can remove. Only topics you can file into are offered, and the choice is checked when you save - not when a delivery arrives - because the delivery request itself is unauthenticated.
  5. Select Create webhook.

Either way, each delivery lands as a thread in the space. With no topics picked, the thread lands in misc and stays conversational: post a follow-up question there and @Naumu answers. When you file deliveries into topics, the thread goes to those topics' members instead, and @Naumu does not reply automatically - @-mention it when you want it to weigh in.

On creation Naumu shows the webhook's URL and signing secret once. Copy both immediately - the signing secret is shown only this once and cannot be retrieved later.

Sign each delivery

Naumu only acts on deliveries it can verify came from you, so every POST must be signed with the webhook's signing secret. Send these headers alongside the JSON body:

HeaderValue
X-Naumu-Webhook-IdA unique id for this delivery
X-Naumu-TimestampThe current time in Unix seconds
X-Naumu-Signaturesha256= followed by the hex HMAC (below)

The signature is an HMAC-SHA256 over the string id.timestamp.body, keyed with the signing secret:

Code
message   = `${webhookId}.${timestamp}.${rawBody}`
signature = hex(HMAC-SHA256(signingSecret, message))

Send the result as X-Naumu-Signature: sha256=<hex>.

The timestamp must be within five minutes of Naumu's clock - this defeats anyone replaying a delivery they captured earlier. The signature is checked against the raw bytes you sent, so don't re-serialize the body between signing and sending.

Manage a webhook

Each webhook in the list can be:

  • Toggled on or off - a disabled webhook stops acting on deliveries without losing its URL or secret.
  • Edited - adjust its prompt template or the topics it files into; the new settings apply to the next delivery.
  • Rotated - generate a fresh signing secret, shown once. The old secret stops verifying immediately, so update your caller right after.
  • Deleted - the URL stops accepting deliveries at once. Anything still POSTing to it gets an error. This cannot be undone.
  • Agents - the agents an inbound webhook can route deliveries to.
  • External agents - the reverse direction: Naumu signs outbound webhooks to your own agent runtime.
Anything missing?
Tell us what would make these docs better.