Documentation Index
Fetch the complete documentation index at: https://docs.dari.dev/llms.txt
Use this file to discover all available pages before exploring further.
Webhooks let your application receive push notifications from Dari. When the model calls an external tool, Dari records a tool.call_requested event, sends that event to your agent’s webhook URL, and waits for your application to submit a tool.result_submitted event back to the session. The same webhook URL also receives session and batch lifecycle events such as session.completed and batch.completed.
A webhook is optional. Without one, you can still watch the session event stream for tool.call_requested events, poll session or batch status, and submit tool results yourself. Configure a webhook when you want Dari to push work and lifecycle updates directly to your server.
First, declare an external tool with kind: external in dari.yml. External tools include schemas, but no handler code, because your infrastructure runs the tool.
# dari.yml
custom_tools:
- name: repo_search
path: tools/repo_search
kind: external
timeout_seconds: 60
# tools/repo_search/tool.yml
name: repo_search
description: Search the checked-out repository for matching content.
input_schema: input.schema.json
output_schema: output.schema.json
Use the CLI after deploying the agent:
dari agent webhook set agt_123 https://example.com/dari/webhook
# opt into lifecycle events by repeating --event
# dari agent webhook set agt_123 https://example.com/dari/webhook --event tool.call_requested --event session.completed
The first set response includes a signing_secret. Store it immediately; Dari does not return it again. If you do not pass any event options, Dari subscribes the webhook only to tool.call_requested.
{
"webhook_url": "https://example.com/dari/webhook",
"signing_enabled": true,
"event_types": ["tool.call_requested"],
"signing_secret": "whsec_..."
}
You can inspect, rotate, or clear the configuration later:
dari agent webhook get agt_123
dari agent webhook rotate-secret agt_123
dari agent webhook clear agt_123
You can also manage webhooks over the API. Start with Set Agent Webhook, then use Get Agent Webhook, Rotate Agent Webhook Secret, or Delete Agent Webhook as needed.
curl -X PUT https://api.dari.dev/v1/agents/agt_123/webhook \
-H "Authorization: Bearer $DARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://example.com/dari/webhook",
"event_types": ["tool.call_requested", "session.completed", "session.failed"]
}'
In production, webhook URLs must use HTTPS, must not contain username/password information, and must resolve to public IP addresses.
Webhook requests
Dari sends a JSON POST when an external tool is requested:
{
"id": "sess_123:msg_456:call_abc",
"type": "tool.call_requested",
"session_id": "sess_123",
"message_id": "msg_456",
"tool_call_id": "call_abc",
"tool_name": "repo_search",
"arguments": { "query": "billing retry logic" },
"input_schema": { "type": "object" },
"output_schema": { "type": "object" },
"expires_at": "2026-05-07T18:30:00Z",
"submit_url": "https://api.dari.dev/v1/sessions/sess_123/events"
}
The request includes these headers:
User-Agent: Dari-Webhook/1.0
Dari-Webhook-Id: sess_123:msg_456:call_abc
Dari-Webhook-Timestamp: 1778178600
Dari-Webhook-Signature: v1=<hex-hmac-sha256>
Dari also sends lifecycle events using a nested data object. Session lifecycle events include the session metadata you provided at creation time, which makes it easy to correlate tester runs, task indexes, and LLM choices.
{
"id": "evt_abc123",
"type": "session.completed",
"created_at": "2026-05-15T18:30:00Z",
"data": {
"session_id": "sess_123",
"batch_id": "batch_123",
"agent_id": "agt_123",
"version_id": "ver_9",
"llm_id": "medium-claude",
"status": "completed",
"last_message_status": "completed",
"metadata": {
"managed_run_id": "run_123",
"kind": "tester",
"task_index": "1",
"llm_id": "medium-claude"
}
}
}
Subscribe to lifecycle events by including them in event_types when you configure the webhook. Supported event types are tool.call_requested, session.completed, session.failed, batch.completed, batch.failed, and batch.partial_failed. Because webhook configuration is agent-scoped, session batches are single-agent; batch lifecycle events are sent to that agent’s configured webhook URL.
Dari retries failed deliveries with the same webhook ID. Treat the id as an idempotency key on your side. Events may be delivered more than once and out of order. Store the session_id or batch_id from the payload and call the corresponding GET endpoint when you need the current source of truth.
Verify the signature
Compute an HMAC-SHA256 over the exact raw request body:
signed_payload = Dari-Webhook-Timestamp + "." + raw_body
signature = HMAC_SHA256(signing_secret, signed_payload)
Compare that value to the v1= value in Dari-Webhook-Signature. Reject requests with an invalid signature or an old timestamp.
import crypto from "node:crypto";
function verifyDariWebhook(rawBody: Buffer, headers: Record<string, string>, secret: string) {
const timestamp = headers["dari-webhook-timestamp"];
const signature = headers["dari-webhook-signature"];
if (!timestamp || !signature?.startsWith("v1=")) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(timestamp)
.update(".")
.update(rawBody)
.digest("hex");
const received = Buffer.from(signature.slice(3), "hex");
const computed = Buffer.from(expected, "hex");
return received.length === computed.length && crypto.timingSafeEqual(received, computed);
}
After your server runs the tool, submit the result to submit_url with your Dari API key:
curl -X POST https://api.dari.dev/v1/sessions/sess_123/events \
-H "Authorization: Bearer $DARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "tool.result_submitted",
"message_id": "msg_456",
"tool_call_id": "call_abc",
"is_error": false,
"result": {
"matches": ["docs/manifest.mdx"]
}
}'
result is raw JSON. If the external tool defines an output_schema, Dari validates successful results before resuming the agent. To return an error to the model, set is_error to true; error results skip output-schema validation.