Skip to main content
A webhook trigger turns an agent into an endpoint: something posts to a URL, and a task starts. This guide creates one, secures it, and shows how to tell a rejected delivery from a filtered one. A delivery is recorded first and answered immediately; the task it produces, if any, starts moments later when the dispatcher next reaches that event — not inline with the HTTP response. See Event streams for what happens in between.

Prerequisites

  • An agent with a working model. See create and configure an agent.
  • A publicly reachable API, or a tunnel to your local one — the sending system has to be able to reach the webhook URL.
  • An access token as AGENTAREA_TOKEN and the API base URL as AGENTAREA_URL.

Steps

1

Create the trigger

Omit webhook_id and the platform generates one with secrets.token_urlsafe(16). Let it — a generated id is unguessable, and for an unverified webhook the URL is the only thing standing between the agent and the internet.
The response carries both webhook_id and webhook_url — the full address, ready to give the sending system:
A request there is recorded in the trigger’s own event stream before anything else happens.
2

Turn on signature verification

Verification is opt-in for every type, including github and stripe. Without a signing secret, verify_webhook_signature returns “not enabled” and the request proceeds unverified. Naming a webhook_type alone secures nothing.
Configure the secret the provider signs with, then point the trigger at it:
For generic webhooks the HMAC details are configurable, because the sender is whatever you wrote:
Those three values are the defaults. signature_algorithm is one of sha1, sha256, sha384 or sha512; any other value is refused with 422 when the trigger is saved. slack, github, discord (Ed25519), linear and stripe ignore them and use their provider’s scheme. Telegram is validated by bot token at a different layer.
3

Point the sending system at the URL

Register the URL wherever the events come from — a GitHub repository webhook, a Stripe endpoint, your own service.
Only Telegram registers its inbound webhook with the provider automatically. Every other channel is a manual step, and nothing in the platform reports that you skipped it.
4

Send a test delivery

Use the provider’s own “redeliver” or “send test” button where one exists — it exercises the real signature path, which a hand-rolled curl does not.For a generic webhook with no secret configured yet:
A request that passes method, signature, and size checks gets 202 back immediately:
The same request repeated with the same provider delivery id (GitHub’s X-GitHub-Delivery, Stripe’s id, a webhook-id or Idempotency-Key header, and a few others) gets 202 again with "status": "duplicate" and the same sequence, instead of a second row and a second task. A provider with none of those is never deduplicated — every delivery gets a fresh sequence. A burst over AGENTAREA_EVENT_WRITE_QUOTA gets 429; a body over 256 KiB gets 413.

Verify

The trigger’s execution history records every delivery that actually reached condition evaluation, including ones that produced no task:
status: "success" with a task_id means the delivery started a task. status: "success" with task_id: null means validation passed and the conditions declined — the trigger is working and deliberately filtering.
A delivery rejected at the method, signature, or validation stage never becomes an execution record with a task — check the API logs for the rejection reason, which is deliberately not returned to the caller in detail. Three other things also never become an execution record, because the dispatcher stops them before TriggerService ever evaluates conditions: an event filtered out by event_types, a trigger that is paused or disabled, and a configurer who lost access to the agent. All three still show up as the stream’s own record — read stream_id off the trigger (GET .../triggers/$TRIGGER_ID returns it), then:
outcomes is empty when no subscription’s filter matched the event at all; otherwise it carries a verdict (reacted, skipped, error) and reason per subscription, independent of whether a task execution record exists. The same list, with the trigger’s name and a link to any task it created, is on the workspace’s Events page.

Troubleshooting

A signing secret is configured and the signature did not match. The most common cause is the body: the signature is computed over the exact raw bytes, so any proxy that re-serializes JSON between the provider and the API invalidates it. The same response is returned when a secret is configured but the raw body was unavailable to verify.
allowed_methods defaults to ["POST"] and is checked before signature and validation. A provider that sends PUT, or a browser preflight, is rejected here.
Check the stream’s events (see Verify) before assuming a bug — three different things look like this and each has a different cause:
  • The conditions declined. Conditions with no explicit type are evaluated by a model against the payload once the dispatcher reaches the event, so the verdict is a judgement, not a rule mismatch. The execution record exists; read trigger_data on it, or reason on the stream’s outcome, to see exactly what the model was shown.
  • event_types filtered it out. The subscription only sees the kinds it names; an event of any other kind gets no outcome at all for this trigger, and no execution record — “nobody listened,” not a failure.
  • The trigger is paused or disabled. The event is still recorded and the dispatcher still reaches it, but a trigger whose is_active is false is skipped before conditions are ever evaluated — no execution record, only a skipped outcome on the stream.
Crossing failure_threshold consecutive failures disables the trigger — but it does not touch the webhook source. Deliveries are still recorded and still answered 202; only the firing is skipped. Nothing re-enables the trigger automatically:
Re-enabling does not replay what was skipped while it was off — only events the dispatcher reaches from then on fire.
The workspace crossed AGENTAREA_EVENT_WRITE_QUOTA events in the trailing minute — counted across every stream the workspace owns, not just this one, so a quiet second stream does not help. A provider’s own retry handles an occasional 429; a sustained one means the deployment’s AGENTAREA_EVENT_WRITE_QUOTA needs raising. See Configuration.
The request body is over 256 KiB after headers and query parameters that look like credentials are stripped. Send a reference to a workspace file instead of the content itself.
It is not. The type selects which verifier runs, not whether one runs. Verification begins only once a signing secret resolves from webhook_config or validation_rules.

Triggers and channels

The model behind this, and what it does not cover.

Event streams

The journal a delivery lands in, and who else can read it.

Schedule an agent

The other way a task starts without a person.

Debug a failed task

When the delivery worked and the task did not.

Errors

What the API returns, and what is safe to retry.
Last modified on October 9, 2026