> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blaxel.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Asynchronous triggers

> Run Blaxel agent requests asynchronously with optional callbacks, allowing background tasks up to 15 minutes without keeping HTTP connections open.

Asynchronous triggers allow you to run an agent request asynchronously. The agent responds immediately while it continues processing the task in the background. You can optionally receive the result through a callback. This lets tasks run for up to 15 minutes without keeping an HTTP connection open.

## Create an asynchronous request

To create an asynchronous request, call your agent URL as shown below:

```http theme={null}
POST https://run.blaxel.ai/{your-workspace}/agents/{your-agent}?async=true
```

Your agent should immediately return:

```json theme={null}
{ "success": true }
```

Meanwhile, the full request is processed asynchronously in the background.

## Set a callback URL

<Note>
  Callback URLs are only supported on Mark 3 infrastructure.
</Note>

You can provide an optional callback URL to receive the result when the background job completes. The callback URL must be specified when the agent is deployed, either via the [Blaxel Console](#blaxel-console) or the [`blaxel.toml` configuration file](#blaxel-configuration-file).

When a callback URL is set, a POST request is automatically sent to that URL when the background job completes. The POST request contains a JSON payload with the agent response. Here is an example:

```json theme={null}
{
  "status_code": 200,
  "response_body": "{\"result\":\"ok\"}",
  "response_length": 123,
  "timestamp": 1735891200
}
```

<Tip>
  You can inspect and verify callbacks by using [https://webhook.site](https://webhook.site).
</Tip>

## Verify a callback using its signature

If you set a callback URL, Blaxel automatically generates a callback secret and uses it to sign the request. This is included in the response payload headers:

```http theme={null}
X-Blaxel-Signature: sha256=<hex>
X-Blaxel-Timestamp: <unix timestamp>
```

The signature can be verified using the Blaxel SDK.

<Note>
  If no callback URL is set, no secret is generated.
</Note>

Here is an example of a webhook running at the `/callback` URL endpoint to validate and process signed responses from an agent running an asynchronous request:

<CodeGroup>
  ```ts TypeScript theme={null}
  import express from "express";
  import { verifyWebhookFromRequest } from "@blaxel/core";

  const app = express();
  const CALLBACK_SECRET = process.env.CALLBACK_SECRET!;

  app.use(express.text({ type: "application/json" }));

  app.post("/callback", (req, res) => {
    if (!verifyWebhookFromRequest(req, CALLBACK_SECRET)) {
      return res.status(401).json({ error: "Invalid signature" });
    }

    const data = JSON.parse(req.body);
    console.log("Job completed:", data);

    res.json({ received: true });
  });
  ```

  ```python Python theme={null}
  from flask import Flask, request, jsonify
  from blaxel.core import verify_webhook_from_request
  import os, json

  app = Flask(__name__)
  CALLBACK_SECRET = os.environ["CALLBACK_SECRET"]

  class ReqWrapper:
      def __init__(self, req):
          self.body = req.get_data()
          self.headers = {k.lower(): v for k, v in req.headers.items()}

  @app.post("/callback")
  def callback():
      if not verify_webhook_from_request(ReqWrapper(request), CALLBACK_SECRET):
          return jsonify({"error": "Invalid signature"}), 401

      data = request.json
      print("Job completed:", data)
      return jsonify({"received": True})
  ```
</CodeGroup>

To create the asynchronous request, use the following example command:

```shell theme={null}
curl -X POST "https://run.blaxel.ai/$(bl workspace --current)/agents/{your-agent}?async=true" \
  -H "Content-Type: application/json" \
  -d '{"input": "Hello"}'
```

## Configure asynchronous triggers

Asynchronous triggers are configured in two ways: via the Blaxel Console or in the `blaxel.toml` configuration file.

### Blaxel Console

In the Blaxel Console, you can configure asynchronous triggers by clicking the **Triggers** tab on the agent detail page. This page lets you list, add, edit, or delete triggers for your agent.

<img src="https://mintcdn.com/blaxel/opPwRTewCbLy-pVp/images/agents/triggers.webp?fit=max&auto=format&n=opPwRTewCbLy-pVp&q=85&s=70f78f94e12b7c10d3e96ac5d2423951" alt="Triggers List" width="1778" height="704" data-path="images/agents/triggers.webp" />

To add a new asynchronous trigger, click **Add Trigger**. You can also optionally configure a callback URL for the trigger.

<img src="https://mintcdn.com/blaxel/opPwRTewCbLy-pVp/images/agents/configuration.webp?fit=max&auto=format&n=opPwRTewCbLy-pVp&q=85&s=14d581fc29e8f48822b90d2f223d8334" alt="Trigger Configuration" width="1314" height="1172" data-path="images/agents/configuration.webp" />

<Note>
  If no callback URL is set, the request will still be processed asynchronously but the callback URL will not be triggered.
</Note>

When you create a trigger with a callback URL, Blaxel automatically generates a callback secret. You can use this secret to verify incoming requests to the callback URL using the Blaxel SDK.

<img src="https://mintcdn.com/blaxel/opPwRTewCbLy-pVp/images/agents/secret.webp?fit=max&auto=format&n=opPwRTewCbLy-pVp&q=85&s=b537e6f25b8921956a18a37f897472c5" alt="Callback Secret" width="1086" height="684" data-path="images/agents/secret.webp" />

<Warning>
  The callback secret is only shown once, so you should save it securely.
</Warning>

### Blaxel configuration file

You can configure asynchronous triggers directly in your `blaxel.toml` file, as in the example below:

```toml theme={null}
type = "agent"
name = "async-agent"

[[triggers]]
  # unique trigger ID
  id = "async"
  # marks trigger as asynchronous
  type = "http-async"

[triggers.configuration]
  # callback URL - optional
  callbackUrl = "https://webhook.site/3955e30a-e4b6-4fa5-8a28-598ce0f53386"
```

This approach allows you to version-control triggers and manage them as part of your agent codebase.
