Webhooks
Pass a callback_url when creating a task, and Agent delivers the result to your URL as soon as the task finishes. No polling needed.
Enabling webhooks
Add callback_url (and optionally callback_secret) to the POST /api/tasks body:
{
"assistant_id": 1,
"callback_url": "https://yourapp.com/hook",
"callback_secret": "your-secret",
"input": [{ "type": "text", "text": "What is Laravel?" }]
}
What you receive
Agent delivers a webhook on any terminal status (completed,
failed, canceled), and also on interrupted — in that case the body
additionally carries pending_tool_calls. The body is the same object that
GET /api/tasks/{uuid} returns.
POST https://yourapp.com/hook X-Task-Uuid: 550e8400-… X-Signature: <hmac> # only if callback_secret is set { "uuid": "550e8400-…", "status": "completed", "turn": { "output": […], "messages": […], "metadata": { … } }, "error": null, "created_at": "…", "completed_at": "…" }
Verifying the signature
If callback_secret is set, the request carries an X-Signature header — an
HMAC-SHA256 of the raw request body. Verify it on your side:
$body = file_get_contents('php://input'); $expected = hash_hmac('sha256', $body, $secret); if (! hash_equals($expected, $_SERVER['HTTP_X_SIGNATURE'] ?? '')) { http_response_code(401); // signature mismatch — reject exit; }
If no callback_secret is set, the X-Signature header isn't sent and there's nothing to verify.
Retries
Delivery goes through a queue (fire-and-forget), with up to 5 attempts and exponential
backoff: 10 s, 30 s, 60 s, 120 s. Your endpoint must respond with
2xx, otherwise the attempt counts as failed.
callback_url, the result is always
available via GET /api/tasks/{uuid}.