Skip to main content

Overview

A webhook trigger gives your agent a unique URL it listens on. When an external service POSTs (or otherwise hits) that URL, the agent receives the request body and can act on it — reply, store data, trigger a workflow, and so on. The URL is generated for you when you create the trigger and shown in the card. Click the copy icon next to it to copy. Each agent’s URLs are distinct, and each trigger has its own URL; create as many as you need. To add a trigger, click Add Webhook on the page, give it a name, and click Save. Each card has an ON / OFF toggle, drag-to-reorder, and a delete button. Authentication uses any API key from your API Keys page. Pass it in the request:
or

What to send

POST with a JSON body is the shape to build against — that body is what the agent reads.
GET, PUT, PATCH and DELETE are accepted too — some services verify an endpoint before they start delivering to it — but a request without a body reaches the agent as (empty body), so there is nothing for it to work with. Any content type is accepted. JSON is parsed, which is what lets interpreters match on fields, pre-processors read event.payload as an object, and the chat id be picked up from the body. Limits: 1 MiB per request and 60 requests per minute per trigger. Over either, the request is rejected (413 / 429) and logged.

Conversations: the chat id

A webhook can be either a conversation or a series of independent one-shot requests. You choose per request, by sending a chat id or not. With a chat id — every request carrying that id continues the same chat. The agent sees the full history and replies in context, exactly like consecutive messages in a web chat or on a messaging channel. Without a chat id — the request is a one-shot. The agent is handed that request and nothing else: no earlier messages, no memory of the previous delivery, and nothing carried into the next one. Each one-shot gets its own entry in the Inbox. Pass it any of three ways (first one found wins): An id may be up to 128 characters of letters, digits and . _ : @ + -. Anything else is ignored — and an id that is ignored means the request is treated as a one-shot, so check the format if follow-ups aren’t landing in the conversation you expect. Send a new id when a new conversation starts (a new customer, ticket, or order) and reuse it for every follow-up that belongs to it. Each conversation appears as its own thread in the Inbox, labelled with the trigger name and the chat id.
Use a chat id when later requests only make sense in light of earlier ones — a support thread, a multi-step form, a back-and-forth with a customer. Leave it off for independent events like order notifications or alerts: a one-shot is cheaper (no history is sent to the model) and can’t be confused by unrelated earlier traffic. A conversation grows with every request, so end one by simply not reusing its id.

Processing pipeline

Each webhook card exposes the shared incoming-event pipeline. Every request flows through these stages in order before (and around) the agent. By default every request reaches the agent — it becomes the next message in the conversation and the agent answers it. The stages below exist to change that: a pre-processor can transform, answer, store or drop a request before any of it happens, and a classifier can screen out what isn’t worth an agent run.

Event pre-processor

Optional owner-supplied code that runs in a sandbox before the classifier and the agent see the request. Define handle(event, ctx) and return a verdict — pass_to_agent, drop, store, run_tool, or respond (a synchronous HTTP reply). A drop here happens before, and skips, the classifier — the cheapest place to filter health-check pings or noise. See the Event pre-processor guide for the full contract, the event/ctx objects, and worked examples.

Interpreters

When one webhook receives several different kinds of payload, Interpreters recognise each kind and inject a plain-language hint into the agent’s context so it knows what it’s looking at before it reads the body. Each interpreter matches by JSON field presence (dot-paths) or regex (any body format), tested in order — first match wins. See the Interpreters guide for the full matching rules and worked examples (Shopify, Stripe, form-encoded, XML, CSV, GitHub, and more). Leave interpreters empty when every payload on this webhook is the same kind of thing — use Context instead.

Event classifier

Optional. When enabled, an LLM reads each request before the agent runs and picks an action from the allow-list — React (hand it to the agent), Store (keep it in the inbox without running the agent), or Drop (ignore it, still logged). Off → every request goes straight to the agent. Give it a prompt describing what counts as relevant, e.g. “Only react to payment.succeeded and refund events; drop everything else.” Turn it on when a webhook receives more traffic than is worth an agent run — screening noise here is cheaper than answering it. With no React action allowed it becomes a free log-only gate: requests are recorded and stored, and no LLM is called at all.

Context and Notes

Two free-text fields at the bottom of each card:
  • Context — instructions for the agent that apply to every call on this webhook (e.g. “These are GitHub push events. Extract the repository name and commit message.”). Prepended to the agent’s context for every incoming payload.
  • Notes — private operator notes, never seen by the agent.
Use Context when every payload on this webhook is the same kind of thing. Use Interpreters when one webhook receives different event types.

Spend budget

Owner-only advanced control.
Each trigger can carry its own AI spend cap so a runaway or abused webhook can’t drain your credits. Set a Spend cap (credits) and a Budget periodDaily, Weekly (Mon–Sun), or Monthly (calendar month). Once the cap is reached for the current period, further deliveries are still acknowledged (so the caller sees a 200) but not processed by the agent, until the period resets at UTC boundaries. Leave the cap at 0 for no limit.

Testing your webhook

Each webhook card has a Test section at the bottom. Fill in a method, content type, an optional chat id and a request body, then click Run Test. The request goes through the real pipeline — interpreters, pre-processor and classifier all run — and the panel shows:
  • which interpreter matched, what the pre-processor and classifier decided, and the resulting outcome;
  • which conversation the request lands in, and how many messages are already in it;
  • the exact prompt and data the agent receives — the <webhook_context> block added to its system prompt, the message text, and the full message array including prior history.
The agent itself is not run and nothing is written to the conversation. Two things do happen for real, so the result is a rehearsal rather than a guess: your pre-processor executes (any side effects it has will occur) and the classifier is a real LLM call (it costs credits). You can also test from the command line with curl:
Recent deliveries appear in Recent Webhook Events on the Webhook Triggers page — a table of time, method, source IP, auth verdict, outcome (→ agent / dropped / stored / responded / ran tool), event name, and detail — and in the Inbox, as the conversation the request belonged to or, for a one-shot, as its own entry.

Manage via the Management MCP

This area is managed through the Management MCP at https://manage.agentheya.com/mcp. All tools take owner_id + agent_id as required arguments. See the Management MCP guide for authentication and the full tool catalogue.