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

# Webhooks

# Webhooks & Event-Driven Automation

Savant can receive inbound webhooks from external services and automatically convert them into agent sessions. When a GitHub PR is opened, a JIRA ticket is created, a Zendesk ticket arrives, or a Datadog alert fires — Savant can react autonomously.

## How It Works

```mermaid theme={null}
flowchart LR
    E["External Service<br/>GitHub · Bitbucket · JIRA<br/>Zendesk · Slack · Datadog"] -->|POST| W["Svantic Webhook<br/>Verify signature<br/>Extract event<br/>Format prompt"]
    W -->|Trigger| S["Agent Session<br/>Plan → Execute → Results"]
```

1. An external service sends a POST to `/webhooks/:provider`.
2. The webhook route verifies the request signature (if configured).
3. The event type is extracted from provider-specific headers or body fields.
4. The `WebhookSessionBridge` formats the event into a natural-language prompt.
5. That prompt can trigger a new Savant session — the agent takes it from there.

## Supported Providers

| Provider      | Event Source            | Signature Verification                    |
| ------------- | ----------------------- | ----------------------------------------- |
| **github**    | `X-GitHub-Event` header | HMAC SHA-256 (`X-Hub-Signature-256`)      |
| **bitbucket** | `X-Event-Key` header    | HMAC SHA-256 (`X-Hub-Signature`)          |
| **jira**      | `webhookEvent` in body  | Shared secret (`X-Webhook-Secret` header) |
| **zendesk**   | `event` field in body   | Shared secret (`X-Webhook-Secret` header) |
| **slack**     | `event.type` in body    | HMAC SHA-256 (Slack signing secret)       |
| **datadog**   | Always `alert`          | Shared secret (`X-Webhook-Secret` header) |

Any unlisted provider can use the generic path — event type is read from `X-Event-Type` header and signature from `X-Webhook-Secret`.

## Configuration

### Registering a Webhook URL

Point your external service's webhook settings to:

```
https://your-savant-server.com/webhooks/{provider}
```

For example:

* **GitHub:** `https://savant.example.com/webhooks/github`
* **Bitbucket:** `https://savant.example.com/webhooks/bitbucket`
* **JIRA:** `https://savant.example.com/webhooks/jira`
* **Zendesk:** `https://savant.example.com/webhooks/zendesk`
* **Datadog:** `https://savant.example.com/webhooks/datadog`

### Configuring Secrets

Secrets are configured on the server side via the `WebhookRoute` API:

```typescript theme={null}
import { WebhookRoute } from './routes/webhooks.js';

const webhook_route = new WebhookRoute();

// Configure secrets per provider
webhook_route.configure_provider('github', { secret: process.env.GITHUB_WEBHOOK_SECRET });
webhook_route.configure_provider('bitbucket', { secret: process.env.BITBUCKET_WEBHOOK_SECRET });
webhook_route.configure_provider('jira', { secret: process.env.JIRA_WEBHOOK_SECRET });
webhook_route.configure_provider('zendesk', { secret: process.env.ZENDESK_WEBHOOK_SECRET });

// Disable a provider entirely
webhook_route.configure_provider('datadog', { enabled: false });
```

If no secret is configured for a provider, signature verification is skipped. If a provider is disabled, all webhooks from that provider are silently ignored.

### Slack URL Verification

Slack sends a `url_verification` challenge when you first register a webhook URL. The Savant webhook route handles this automatically — it responds with the challenge token so Slack confirms the endpoint.

## Event Handlers

Register handlers that fire when a webhook arrives:

```typescript theme={null}
webhook_route.on_event(async (event) => {
    console.log(`[${event.provider}] ${event.event_type}`);
    console.log('Payload:', event.payload);

    // Create a Savant session from the event
    const prompt = WebhookSessionBridge.format_prompt(event);
    // ... trigger a new session with this prompt
});
```

### WebhookEvent Shape

```typescript theme={null}
interface WebhookEvent {
    provider: string;          // "github", "bitbucket", "jira", etc.
    event_type: string;        // "push", "pullrequest:created", "ticket_created", etc.
    payload: Record<string, unknown>;  // Raw webhook body
    headers: Record<string, string>;   // Request headers
    received_at: string;       // ISO timestamp
}
```

## WebhookSessionBridge

The `WebhookSessionBridge` converts raw webhook events into natural-language prompts suitable for starting a Savant session:

| Provider  | Event                   | Generated Prompt Example                                                                                             |
| --------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------- |
| GitHub    | `pull_request` (opened) | "GitHub webhook: pull request opened — PR #42 'Add feature' on owner/repo. Review and take appropriate action."      |
| GitHub    | `push`                  | "GitHub webhook: push to refs/heads/main — 3 commit(s) on owner/repo. Check for any issues."                         |
| Bitbucket | `pullrequest:created`   | "Bitbucket webhook: pull request created — PR #5 'Fix login' on myteam/my-repo. Review and take appropriate action." |
| Bitbucket | `repo:push`             | "Bitbucket webhook: push to myteam/my-repo. Check for any issues."                                                   |
| JIRA      | `jira:issue_updated`    | "JIRA webhook: jira:issue\_updated — issue PROJ-123. Review and take appropriate action."                            |
| Zendesk   | `ticket_created`        | "Zendesk webhook: ticket\_created — ticket #101 'Cannot access account'. Review and respond if needed."              |
| Slack     | `message`               | "Slack webhook: message event — 'Hello bot, can you help?'. Respond appropriately."                                  |
| Datadog   | `alert`                 | "Datadog webhook: alert — 'High CPU on api-server'. Investigate and take action."                                    |

## Example: Auto-Review PRs on Push

Combine webhooks with builtin tools for fully autonomous workflows:

1. **GitHub/Bitbucket** sends a `pull_request.opened` webhook to Savant.
2. The `WebhookSessionBridge` creates a prompt: "Review PR #42..."
3. A new Savant session starts. The agent uses `github_get_pr_diff` (or `bitbucket_get_pr_diff`) to read the changes.
4. The agent reviews the code, checking for patterns in the Knowledge Store.
5. The agent posts a review comment via `github_post_review` (or `bitbucket_post_comment`).
6. The agent updates the linked JIRA ticket via `jira_transition_issue`.
7. The agent posts a summary to Slack via `slack_send_message`.

No human involved. The entire loop — from webhook to review to ticket update to notification — runs autonomously.

## Example: Auto-Triage Zendesk Tickets

1. **Zendesk** sends a `ticket_created` webhook.
2. Savant reads the ticket details via `zendesk_get_ticket`.
3. The agent searches the Knowledge Store for similar past tickets and resolutions.
4. The agent looks up the customer in internal systems (via custom client tools).
5. The agent drafts a response and posts it via `zendesk_add_comment`.
6. The agent updates the ticket priority and tags via `zendesk_update_ticket`.

## Safety

Webhook-triggered sessions run through the same safety system as user-initiated sessions:

* **ToolGuard** gates every tool invocation — destructive actions (merging PRs, closing tickets) require approval unless YOLO mode is enabled.
* **FlowGuard** prevents runaway execution — a single webhook cannot trigger an infinite chain of agent actions.
* Webhook handlers run asynchronously and failures in one handler do not block others.
