> For the complete documentation index, see [llms.txt](https://docs.ibexa.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ibexa.ai/manual/agents/triggers.md).

# Triggers

Triggers define when and how an agent runs. Every agent needs at least one trigger - without one, there is no way to start it. Use triggers to decide whether the agent runs on demand, on a schedule, or whenever an external event arrives.

A good trigger setup depends on the agent's purpose. If your agent is for ad-hoc review or testing, a manual **Run Now** trigger is enough. If it responds to business events, a **Webhook** trigger is usually the best fit. If it performs recurring work like reporting or maintenance, choose a **Schedule** trigger that matches the cadence you need.

This guide covers the trigger types available on the platform and explains the configuration details you need for reliable automation, especially for **Webhook** triggers.

## Before You Begin

Any member of your organisation can add, edit, or remove triggers on an agent they have access to.

## Choosing the Right Trigger

Use this quick checklist when deciding which trigger to add:

* **Manual execution**: choose **Run Now** for testing, one-off actions, or internal workflows where a person starts the run.
* **Regular cadence**: use a **Daily**, **Weekly**, **Bi-weekly**, **Monthly**, **Quarterly**, or **Yearly** schedule when the agent should repeat on a fixed timetable.
* **Event-driven automation**: choose **Webhook** when another system should trigger the agent as soon as a specific event occurs.
* **Operational safety**: add message filters and rate limits to prevent noisy or high-volume webhooks from starting unnecessary runs.

## Available Trigger Types

| Category      | Trigger type           | What it does                                                                                                                                                       |
| ------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **General**   | **Run Now**            | Manually execute the agent on demand, without any scheduling. This is the trigger used by **Run test** and any manual chat with the agent.                         |
| **Scheduler** | **Daily Schedule**     | Executes the agent every day at a specific time (UTC).                                                                                                             |
| **Scheduler** | **Weekly Schedule**    | Executes the agent on one or more specific days of the week.                                                                                                       |
| **Scheduler** | **Bi-weekly Schedule** | Executes the agent every two weeks on a specific day.                                                                                                              |
| **Scheduler** | **Monthly Schedule**   | Executes the agent on a specific day of the month. If a month is shorter than the configured day (e.g. day 31 in April), it runs on that month's last day instead. |
| **Scheduler** | **Quarterly Schedule** | Executes the agent once per quarter.                                                                                                                               |
| **Scheduler** | **Yearly Schedule**    | Executes the agent once per year.                                                                                                                                  |
| **Webhook**   | **Webhook**            | Executes the agent when an external system sends an HTTPS request to a unique URL. See [below](#webhook-triggers) for details.                                     |

## Adding a Trigger

1. From an agent's **Add Agent**/**Edit Agent** wizard (Step 3: Triggers) or its **Behaviour** tab, select **Add trigger**.
2. Pick one or more trigger types from the list - types are grouped by category (**General**, **Scheduler**, **Webhook**). Select **Add**.
3. A settings form appears for each trigger you added. Fill in the required fields (these vary by trigger type - see below for Webhook).
4. The trigger appears in the agent's trigger list. To remove one, select the delete icon on its row.

## Webhook Triggers

A **Webhook** trigger lets an external system (a CRM, a form service, another internal tool, etc.) start an agent execution by sending an HTTPS `POST` request to a unique URL. No platform login is required to call it - security is handled through a token, an optional signature, and an optional IP allowlist instead.

### The Webhook URL

Every webhook trigger is identified by a **token** you choose (30-50 characters, letters/numbers/`_`/`-` only). The full URL external systems should call is:

```
https://<your-platform-domain>/api/v1/webhooks/<token>
```

> **Keep your token secret.** Anyone with the URL can attempt to trigger the agent, subject to the security settings below.

### Configuration Fields

| Field                                            | Required | Description                                                                                                                                                        |
| ------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Token**                                        | Yes      | The unique, URL-safe value that becomes part of the webhook URL. Choose a long, random string - it acts as a shared secret.                                        |
| **Signature required**                           | No       | Enabled by default. When on, every request must include a valid HMAC-SHA256 signature (see below). Turn it off only if the sending system cannot sign requests.    |
| **Secret**                                       | Depends  | Required whenever **Signature required** is on. A base64-encoded value of at least 32 bytes, shared with the sending system to compute the signature.              |
| **IP allowlist**                                 | No       | One or more IPv4/IPv6 addresses or CIDR blocks. When set, requests from any other source IP are rejected. Leave empty to allow any source IP.                      |
| **Rate limit per minute**                        | No       | Maximum requests accepted per minute, from 1 to 1000 (default: 60). Requests beyond the limit receive a `429 Too Many Requests` response.                          |
| **Signature/Timestamp/Idempotency header names** | No       | Override the header names the trigger reads from, if the sending system cannot use the defaults (`X-Webhook-Signature`, `X-Webhook-Timestamp`, `Idempotency-Key`). |
| **Message filter**                               | No       | Rules evaluated against the JSON payload to decide whether it should start an execution. See [Filtering Inbound Messages](#filtering-inbound-messages).            |

### Signing Requests

When **Signature required** is on (the default), the sending system must include two headers with every request:

* `X-Webhook-Timestamp` (or your custom name) - the current Unix timestamp, in seconds.
* `X-Webhook-Signature` (or your custom name) - `sha256=<hex-digest>`, an HMAC-SHA256 digest of the string `{timestamp}.{raw request body}`, computed using the shared **secret**.

Requests are rejected if the signature does not match, or if the timestamp is more than 5 minutes old (or in the future) - this protects against replay attacks.

### Filtering Inbound Messages

The optional **message filter** lets you accept a webhook call at the security level, but skip starting an execution unless the payload matches specific rules. This is useful when a single webhook URL receives many event types but the agent should only run for some of them.

* Rules are field/operator/value checks against the JSON payload, e.g. `event.type equals "order.created"`.
* Supported operators: `equals`, `not_equals`, `in`, `contains`, `regex`, `exists`.
* `field` is a dot-delimited path into the payload (e.g. `event.type`).
* Combine multiple rules with **match: all** (AND, default) or **match: any** (OR).
* A payload that does not match the filter is still accepted by the endpoint (so the sender sees a successful response) but does **not** start an execution.

### What the Sending System Receives

The webhook endpoint always responds `202 Accepted` (except for security failures, which return `401`/`403`, and rate limiting, which returns `429`). The response body includes a `status` field the sender should check rather than relying on the HTTP status code alone:

| Status               | Meaning                                                                                                                                                   |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ACCEPTED`           | The payload matched the message filter (or none is set) and an execution was created.                                                                     |
| `FILTERED`           | The request was valid, but the payload didn't match the message filter - no execution ran.                                                                |
| `BLOCKED_NO_CREDITS` | The request was valid, but your organisation is out of credits - no execution ran. Retrying the same request after topping up credits will run the agent. |

Sending the same request twice with the same **Idempotency-Key** header value will not create a duplicate execution - the second call returns a `409 Conflict` referencing the original result.

## Troubleshooting

| Issue                                            | What to do                                                                                                                                                                                     |
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Webhook calls return `401 Unauthorized`          | Check that the signature is computed over `{timestamp}.{body}` using the correct secret, and that the timestamp header is within 5 minutes of the current time.                                |
| Webhook calls return `403 Forbidden`             | The source IP is not in the configured IP allowlist.                                                                                                                                           |
| Webhook calls return `429 Too Many Requests`     | The configured rate limit was exceeded. Increase **Rate limit per minute** or reduce the sending frequency.                                                                                    |
| A webhook call succeeds but the agent never runs | Check the **message filter** rules - the payload may not be matching them (response `status` will be `FILTERED`). Also confirm your organisation has available credits (`BLOCKED_NO_CREDITS`). |
