Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ece4e72
feat(pkg/tools/builtin/webhook/webhook.go): adding up amazing webhook…
dwin-gharibi Jul 14, 2026
fc16f0a
test(pkg/tools/builtin/webhook/webhook_test.go): adding proper tests …
dwin-gharibi Jul 14, 2026
373ce83
feat(pkg/teamloader/toolsets/toolsets.go): adding the webhook tool in…
dwin-gharibi Jul 14, 2026
3f40244
feat(pkg/teamloader/toolsets/catalog.go): adding the webhook tool int…
dwin-gharibi Jul 14, 2026
8b8b977
docs(docs/tools/webhook/index.md): feating the webhook tool docs for …
dwin-gharibi Jul 14, 2026
3df4bf5
docs(docs/configuration/tools/index.md): adding the webhook tool into…
dwin-gharibi Jul 14, 2026
15c633b
docs(docs/tools/webhook/index.md): updating up the doc markdown file …
dwin-gharibi Jul 15, 2026
cf41fad
docs(docs/tools/webhook/index.md): updating the docs again solving li…
dwin-gharibi Jul 15, 2026
a951bd9
docs(docs/tools/webhook/index.md): fixing problem of MD047/single-tra…
dwin-gharibi Jul 15, 2026
ebce6b7
fix(agent-schema.json): fixing up the agent-schema.json
dwin-gharibi Jul 15, 2026
1df880e
fix(pkg/tools/builtin/webhook/webhook.go): fixing up the review probl…
dwin-gharibi Jul 15, 2026
f7bb775
fix(pkg/tools/builtin/webhook/webhook_test.go): fixing the webhook te…
dwin-gharibi Jul 15, 2026
7169c6a
feat(docs/tools/webhook/index.md): updating up the webhook document a…
dwin-gharibi Jul 15, 2026
7cabb1a
feat(pkg/config/latest/types.go): adding up the webhook configs into …
dwin-gharibi Jul 16, 2026
6baad0d
fix(pkg/teamloader/toolsets/toolsets.go): fixing up the tool registra…
dwin-gharibi Jul 16, 2026
902ecab
fix(pkg/tools/builtin/webhook/webhook.go): feating up some amazing fe…
dwin-gharibi Jul 16, 2026
25e8755
feat(pkg/tools/builtin/webhook/webhook_test.go): adding the new tests…
dwin-gharibi Jul 16, 2026
7e8ee22
docs(docs/configuration/tools/index.md): adding the webhook tool conf…
dwin-gharibi Jul 16, 2026
836b48e
docs(docs/tools/webhook/index.md): updating up the docs for webhook t…
dwin-gharibi Jul 16, 2026
f035f3b
feat(agent-schema.json): adding the webhook tool and configs details …
dwin-gharibi Jul 16, 2026
1a17469
fix(pkg/tools/builtin/webhook/webhook.go): fixing the go linting prob…
dwin-gharibi Jul 17, 2026
5e6e5da
fix(pkg/tools/builtin/webhook/webhook.go): fixing up the linting prob…
dwin-gharibi Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion agent-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2021,7 +2021,8 @@
"background_agents",
"scheduler",
"rag",
"git"
"git",
"webhook"
]
},
"instruction": {
Expand Down Expand Up @@ -2105,6 +2106,10 @@
"$ref": "#/definitions/ApiConfig",
"description": "API tool configuration"
},
"webhook_config": {
"$ref": "#/definitions/WebhookConfig",
"description": "Webhook tool configuration"
},
"rag_config": {
"$ref": "#/definitions/RAGConfig",
"description": "RAG configuration for type: rag toolsets"
Expand Down Expand Up @@ -2395,6 +2400,22 @@
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "webhook"
}
}
},
{
"required": [
"webhook_config"
]
}
]
},
{
"allOf": [
{
Expand Down Expand Up @@ -2562,6 +2583,42 @@
],
"additionalProperties": false
},
"WebhookConfig": {
"type": "object",
"description": "Webhook tool configuration: delivery destination and credentials",
"properties": {
"provider": {
"type": "string",
"description": "Payload shape for the target service",
"enum": [
"slack",
"discord",
"ifttt",
"telegram",
"mattermost",
"rocketchat",
"googlechat",
"teams",
"generic"
]
},
"url": {
"type": "string",
"description": "Webhook endpoint URL. Usually embeds a secret, so prefer ${env.VAR}"
},
"headers": {
"type": "object",
"description": "HTTP headers sent with the request; use ${env.VAR} for tokens",
"additionalProperties": {
"type": "string"
}
},
"chat_id": {
"type": "string",
"description": "Destination chat id (provider: telegram)"
}
}
},
"ApiConfig": {
"type": "object",
"description": "API tool configuration for making HTTP requests to external APIs",
Expand Down
1 change: 1 addition & 0 deletions docs/configuration/tools/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Built-in tools are included with Docker Agent and require no external dependenci
| `open_url` | Open a fixed URL in the user's default browser | [Open URL](../../tools/open-url/index.md) |
| `transfer_task` | Delegate to sub-agents (auto-enabled) | [Transfer Task](../../tools/transfer-task/index.md) |
| `background_agents` | Parallel sub-agent dispatch | [Background Agents](../../tools/background-agents/index.md) |
| `webhook` | Reliable notifications to a configured destination, with retries (Slack, Discord, Telegram, IFTTT, Teams, …) | [Webhook](../../tools/webhook/index.md) |
| `handoff` | Local conversation handoff to another agent in the same config (auto-enabled by `handoffs:`) | [Handoff](../../tools/handoff/index.md) |
| `a2a` | A2A remote agent connection | [A2A](../../tools/a2a/index.md) |
| `mcp_catalog` | Discover and activate remote MCP servers from the Docker MCP Catalog on demand | [MCP Catalog](../../tools/mcp-catalog/index.md) |
Expand Down
143 changes: 143 additions & 0 deletions docs/tools/webhook/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: "Webhook Tool"
description: "Reliable outbound notifications to Slack, Discord, Telegram, IFTTT, and more."
keywords: docker agent, ai agents, tools, toolsets, webhook, slack, discord, telegram, ifttt, notifications
linkTitle: "Webhook"
weight: 145
canonical: https://docs.docker.com/ai/docker-agent/tools/webhook/
---

_Reliable outbound notifications to Slack, Discord, Telegram, IFTTT, and more._

## Overview

The webhook toolset delivers a notification to a destination **you configure**. The
agent supplies only the message text: it never sees or chooses the URL, because a
webhook URL is itself a credential (Slack and Mattermost embed a secret path,
Discord a token, IFTTT a key, Telegram a bot token).

This is not a general HTTP client — that is the [`api`](../api/index.md) toolset.
The webhook toolset owns *delivery*:

- **At-least-once delivery.** Transient failures (`429`, `5xx`, network errors) are
retried with exponential backoff, honouring the server's `Retry-After`. A `4xx`
is permanent and fails immediately without wasting retries.
- **Non-blocking.** The call returns as soon as the notification is queued, so a
slow or retrying endpoint never stalls the agent's turn. The agent is messaged
back **only if delivery ultimately fails**.
- **Storm protection.** An identical message to the same destination inside a short
window is suppressed, and notifications are rate limited, so a looping agent
cannot flood a channel.
- **Provider-shaped payloads.** Each service's wire format is applied for you.

## Configuration

The destination lives in `webhook_config`. Use `${env.VAR}` for anything secret —
values are expanded at call time and never stored in the config file.

```yaml
toolsets:
- type: webhook
webhook_config:
provider: slack
url: ${env.SLACK_WEBHOOK_URL}
```

| Field | Required | Description |
| --- | --- | --- |
| `url` | Yes | Webhook endpoint. Usually embeds a secret — prefer `${env.VAR}`. |
| `provider` | No | Payload shape (default `generic`). |
| `headers` | No | Extra headers, for endpoints authenticating with a token. |
| `chat_id` | No | Destination chat — required for `provider: telegram`. |

`timeout` on the toolset (seconds) overrides the per-request HTTP timeout.

## Providers

| Provider | Payload sent | Where the secret lives |
| --- | --- | --- |
| `slack`, `mattermost`, `rocketchat`, `googlechat`, `teams`, `generic` | `{"text": message}` | secret webhook URL |
| `discord` | `{"content": message}` | token in the webhook URL |
| `ifttt` | `{"value1": message, "value2": …, "value3": …}` | key in the webhook URL |
| `telegram` | `{"chat_id": …, "text": message}` | bot token in the URL, plus `chat_id` |

Aliases are accepted: `msteams`/`microsoft_teams` → `teams`, `google_chat`/`gchat`
→ `googlechat`, `rocket.chat` → `rocketchat`.

### Per-service examples

```yaml
# Slack / Mattermost / Rocket.Chat — the URL is the credential
toolsets:
- type: webhook
webhook_config:
provider: slack
url: ${env.SLACK_WEBHOOK_URL}
```

```yaml
# Discord — the token is part of the webhook URL
toolsets:
- type: webhook
webhook_config:
provider: discord
url: ${env.DISCORD_WEBHOOK_URL}
```

```yaml
# Telegram — bot token in the URL, chat_id selects the destination chat
toolsets:
- type: webhook
webhook_config:
provider: telegram
url: https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/sendMessage
chat_id: "123456789"
```

```yaml
# IFTTT — the key is part of the trigger URL
toolsets:
- type: webhook
webhook_config:
provider: ifttt
url: https://maker.ifttt.com/trigger/build_failed/with/key/${env.IFTTT_KEY}
```

```yaml
# Generic endpoint authenticating with a bearer token
toolsets:
- type: webhook
webhook_config:
provider: generic
url: https://alerts.example.com/notify
headers:
Authorization: Bearer ${env.ALERTS_TOKEN}
```

## `send_webhook`

| Parameter | Required | Description |
| --- | --- | --- |
| `message` | Yes | The message text to deliver. |
| `value2`, `value3` | No | Extra IFTTT data fields (`provider: ifttt`). |

Returns immediately once queued. On success nothing further happens; if delivery
ultimately fails, the agent receives a message saying so.

## Example

```yaml
agents:
root:
model: openai/gpt-5-mini
instruction: If a check fails, notify the team with send_webhook.
toolsets:
- type: webhook
webhook_config:
provider: slack
url: ${env.SLACK_WEBHOOK_URL}
```

> [!NOTE]
> Requests to non-public addresses are refused (the SSRF-safe HTTP client), and the
> configured URL is never echoed back to the model or into error messages.
28 changes: 28 additions & 0 deletions pkg/config/latest/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,31 @@ type APIToolConfig struct {
OutputSchema map[string]any `json:"output_schema,omitempty"`
}

// WebhookToolConfig configures the `webhook` toolset: where a notification is
// delivered and how it authenticates.
//
// The destination is deployment configuration, not something the model chooses:
// every provider's webhook URL is itself a credential (Slack and Mattermost
// embed a secret path, Discord a token, IFTTT a key, Telegram a bot token), so
// the agent only supplies the message. URL and Headers are expanded at call
// time, so secrets are referenced as ${env.VAR} and never stored in the config.
type WebhookToolConfig struct {
// Provider selects the payload shape: slack, discord, ifttt, telegram,
// mattermost, rocketchat, googlechat, teams, or generic (default).
Provider string `json:"provider,omitempty"`

// URL is the webhook endpoint. It usually embeds a secret, so prefer
// ${env.VAR} over a literal.
URL string `json:"url,omitempty"`

// Headers are sent with the request, for endpoints that authenticate with a
// token instead of a secret URL (e.g. Authorization: Bearer ${env.TOKEN}).
Headers map[string]string `json:"headers,omitempty"`

// ChatID is the destination chat for provider: telegram.
ChatID string `json:"chat_id,omitempty"`
}

// PostEditConfig represents a post-edit command configuration
type PostEditConfig struct {
Path string `json:"path"`
Expand Down Expand Up @@ -1395,6 +1420,9 @@ type Toolset struct {

APIConfig APIToolConfig `json:"api_config"`

// For the `webhook` tool - destination and credentials.
WebhookConfig WebhookToolConfig `json:"webhook_config"`

// For the `filesystem` tool - VCS integration
IgnoreVCS *bool `json:"ignore_vcs,omitempty"`

Expand Down
1 change: 1 addition & 0 deletions pkg/teamloader/toolsets/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var BuiltinToolsets = []BuiltinToolsetInfo{
builtinToolset("think", "think", "Step-by-step reasoning scratchpad for planning"),
builtinToolset("todo", "todo", "Manage a task list for complex multi-step workflows"),
builtinToolset("user_prompt", "user-prompt", "Ask the user questions and collect interactive input"),
builtinToolset("webhook", "webhook", "Send outbound notifications (Slack, Discord, Telegram, IFTTT, Teams, and more)"),
}

func builtinToolset(toolsetType, docsSlug, summary string) BuiltinToolsetInfo {
Expand Down
4 changes: 4 additions & 0 deletions pkg/teamloader/toolsets/toolsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/docker/docker-agent/pkg/tools/builtin/think"
"github.com/docker/docker-agent/pkg/tools/builtin/todo"
"github.com/docker/docker-agent/pkg/tools/builtin/userprompt"
"github.com/docker/docker-agent/pkg/tools/builtin/webhook"
"github.com/docker/docker-agent/pkg/tools/mcp"
)

Expand Down Expand Up @@ -121,5 +122,8 @@ func DefaultToolsetCreators() map[string]teamloader.ToolsetCreator {
"rag": func(ctx context.Context, toolset latest.Toolset, parentDir string, runConfig *config.RuntimeConfig, _ string) (tools.ToolSet, error) {
return rag.CreateToolSet(ctx, toolset, parentDir, runConfig)
},
"webhook": func(_ context.Context, toolset latest.Toolset, _ string, runConfig *config.RuntimeConfig, _ string) (tools.ToolSet, error) {
return webhook.CreateToolSet(toolset, runConfig)
},
}
}
Loading
Loading