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

# Webhooks & Event Destinations

> Push agent events to external systems like HTTP endpoints, Slack, and email

# Webhooks & Event Destinations

Push agent events to external systems automatically. The webhook system listens to the agent's `EventBus` and forwards events to configured destinations with retry and batching.

## Quick Start

```typescript theme={null}
import { Agent, openai, httpWebhook, slackWebhook } from "@agentium/core";

const agent = new Agent({
  name: "assistant",
  model: openai("gpt-4o"),
  webhooks: {
    destinations: [
      httpWebhook({
        url: "https://your-api.com/webhooks",
        secret: "my-hmac-secret",
      }),
      slackWebhook({
        webhookUrl: "https://hooks.slack.com/services/T.../B.../...",
      }),
    ],
    events: ["run.complete", "run.error"],
    retries: 3,
  },
});
```

## Destinations

### HTTP

```typescript theme={null}
httpWebhook({
  url: "https://api.example.com/events",
  headers: { "X-API-Key": "..." },
  method: "POST",        // or "PUT"
  secret: "hmac-secret", // Signs payload with HMAC-SHA256
});
```

The payload is JSON: `{ event, payload, timestamp }`. With a `secret`, the `X-Webhook-Signature` header contains `sha256=<hex>`.

### Slack

```typescript theme={null}
slackWebhook({
  webhookUrl: "https://hooks.slack.com/services/...",
  channel: "#alerts",
  formatMessage: (event, payload) => `Custom: ${event}`,
});
```

Default format:

```
[Agentium] run.complete
Agent: assistant
Run: abc12345
Tokens: 450 prompt + 128 completion
Duration: 1.2s
```

### Email (SendGrid)

```typescript theme={null}
emailWebhook({
  transport: "sendgrid",
  apiKey: process.env.SENDGRID_API_KEY!,
  to: ["team@example.com"],
  from: "alerts@example.com",
  subject: (event) => `[Agentium] ${event}`,
});
```

### Custom Destination

Build your own destination by implementing the `WebhookDestination` interface:

```typescript theme={null}
import type { WebhookDestination } from "@agentium/core";

const datadogDestination: WebhookDestination = {
  name: "datadog",
  async send(event: string, payload: Record<string, unknown>) {
    await fetch("https://http-intake.logs.datadoghq.com/api/v2/logs", {
      method: "POST",
      headers: {
        "DD-API-KEY": process.env.DD_API_KEY!,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        ddsource: "agentium",
        ddtags: `event:${event},agent:${payload.agentName}`,
        message: JSON.stringify(payload),
      }),
    });
  },
};

const agent = new Agent({
  name: "assistant",
  model: openai("gpt-4o"),
  webhooks: {
    destinations: [datadogDestination],
    events: ["run.complete", "run.error", "cost.tracked"],
  },
});
```

## Configuration

```typescript theme={null}
interface WebhookConfig {
  destinations: WebhookDestination[];
  events?: string[];         // Filter events (default: all)
  batchInterval?: number;    // Batch events before sending (ms)
  retries?: number;          // Retry on failure (default: 2)
  onError?: "log" | "throw"; // Error handling (default: "log")
}
```

## Supported Events

All events from the `AgentEventMap` are supported, including:

`run.start`, `run.complete`, `run.error`, `tool.call`, `tool.result`, `team.delegate`, `handoff.transfer`, `handoff.complete`, `cost.tracked`, `cache.hit`, `cache.miss`, `memory.stored`, `skill.loaded`, and more.

***

## Event Filtering

Only forward specific events to specific destinations:

```typescript theme={null}
const agent = new Agent({
  name: "assistant",
  model: openai("gpt-4o"),
  webhooks: {
    destinations: [
      httpWebhook({ url: "https://api.example.com/all-events" }),
      slackWebhook({
        webhookUrl: "https://hooks.slack.com/...",
        channel: "#alerts",
      }),
    ],
    events: [
      "run.complete",
      "run.error",
      "cost.budget.exceeded",
      "handoff.transfer",
    ],
    retries: 3,
    onError: "log",
  },
});
```

Only the listed events are forwarded. Omit `events` to forward everything.

***

## Batching

For high-throughput agents, batch events before sending to reduce HTTP calls:

```typescript theme={null}
webhooks: {
  destinations: [httpWebhook({ url: "https://api.example.com/events" })],
  batchInterval: 5000, // Batch events for 5 seconds before sending
}
```

Batched events are sent as an array in a single HTTP request. The batch flushes either when `batchInterval` elapses or when 100 events accumulate (whichever comes first).

***

## HMAC Signature Verification

When using `httpWebhook` with a `secret`, every request includes a `X-Webhook-Signature` header. Verify it on your server:

```typescript theme={null}
import crypto from "node:crypto";

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string,
): boolean {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(payload).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

// In your Express handler:
app.post("/webhooks", (req, res) => {
  const sig = req.headers["x-webhook-signature"] as string;
  if (!verifyWebhookSignature(JSON.stringify(req.body), sig, "my-hmac-secret")) {
    return res.status(401).send("Invalid signature");
  }
  // Process the event
  console.log(req.body.event, req.body.payload);
  res.sendStatus(200);
});
```
