Tireless Crew Tireless Crew
Docs
Sign in Get started free

Destinations

Destinations send agent output to an external system after every successful run — email, a webhook endpoint, or a Slack channel.

You can attach one or more destinations to any agent. Go to Agents → [agent name], scroll to the Destinations section, and click Add destination.

Email

Send the agent's output to one or more email addresses as soon as the run completes.

SettingDescription
To One or more recipient email addresses, comma-separated. For example: [email protected], [email protected]
Subject prefix Optional prefix prepended to every subject line. Defaults to the agent name.

Emails are sent via the platform's configured mail provider. The body contains the full agent output formatted as plain text.

Webhook

POST the agent's output as JSON to any URL you control. This is the most flexible destination — it lets you pipe results into your own systems, databases, or automation tools.

SettingDescription
URL The HTTPS endpoint that receives the POST request. Must be publicly reachable.
Secret A shared secret used to generate an HMAC-SHA256 signature. Leave blank to skip signature verification.

Request format

The platform sends a POST request with Content-Type: application/json and this body:

{
  "agent_id":   "uuid-of-the-agent",
  "agent_name": "Abandoned Cart Recovery",
  "run_id":     "uuid-of-the-run",
  "status":     "completed",
  "output":     "Subject: Your cart is still waiting...\n\nHi Sarah...",
  "ran_at":     "2026-06-09T14:32:00Z"
}

Verifying the signature

When you set a secret, every webhook request includes an X-Signature header containing an HMAC-SHA256 digest of the raw request body, prefixed with sha256=.

X-Signature: sha256=3b4c2d1e9f...

Verify it in your receiver before trusting the payload:

PHP

<?php

function verifyWebhookSignature(string $body, string $header, string $secret): bool
{
    $expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
    return hash_equals($expected, $header);
}

$body      = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SIGNATURE'] ?? '';

if (! verifyWebhookSignature($body, $signature, 'YOUR_SECRET')) {
    http_response_code(401);
    exit('Invalid signature');
}

$payload = json_decode($body, true);
// handle $payload...

Node.js

const crypto = require('crypto');

function verifyWebhookSignature(body, header, secret) {
    const expected = 'sha256=' + crypto
        .createHmac('sha256', secret)
        .update(body)
        .digest('hex');
    return crypto.timingSafeEqual(
        Buffer.from(expected),
        Buffer.from(header)
    );
}

// Express example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
    const signature = req.headers['x-signature'] || '';
    if (!verifyWebhookSignature(req.body, signature, 'YOUR_SECRET')) {
        return res.status(401).send('Invalid signature');
    }
    const payload = JSON.parse(req.body.toString());
    // handle payload...
    res.sendStatus(200);
});

Always use hash_equals (PHP) or timingSafeEqual (Node.js) for the comparison — a naive === check is vulnerable to timing attacks.

Respond with any 2xx HTTP status to acknowledge receipt. The platform logs the response status for each delivery attempt.

Slack

Post the agent's output as a message to a Slack channel using an Incoming Webhook URL.

SettingDescription
Webhook URL The Slack Incoming Webhook URL for your workspace and channel. Create one at api.slack.com/apps → Incoming Webhooks.
Username Optional display name shown in Slack. Defaults to the agent name.

The message body is the agent's plain-text output. For long outputs (over 3,000 characters), the platform truncates the message and appends a note with a link to the full run in the dashboard.