What a firing carries
Every destination receives the same payload. The webhook version includes an HMAC-SHA256 signature in the X-Discatch-Signature header.
Webhook payload
{
"event": "catch.fired",
"catch_id": "cat_01J...",
"delivery_id": "dlv_01J...",
"fired_at": "2026-09-09T14:17:00Z",
"results": [
{
"source": "hackernews",
"url": "https://news.ycombinator.com/item?id=42345678",
"title": "Show HN: ...",
"prescore": 0.82,
"thread": { "replies": 47, "score": 312 },
"matched": { "terms": ["your product"] }
}
],
"suggested_action": "A user is comparing tools and asked for agent-native options. Consider a reply that answers the question.",
"quote": { "amount_usd": 0.003, "units": { "alert": 1, "result": 1 } }
}Every destination
| Type | What you configure | What wakes the agent |
|---|---|---|
| webhook | A URL and a secret | A signed POST with the results, the suggested action, and a cursor to replay from |
| claude_code | A slash command and a working directory | The coding agent picks up the mention as work |
| codex | A slash command and a working directory | Same as claude_code, for Codex |
| doozy | A list and optionally an agent | A Doozy todo with the results; the named agent runs it |
| github_dispatch | A repository | A repository_dispatch event; a workflow files the issue or runs triage |
| pane | A RunPane endpoint | Pane Chat picks up the mention as work |
| An address | A digest for a human | |
| slack | A webhook URL or OAuth token | A channel post for a human |
Retries and dead letter
Webhook delivery is at-least-once. The event stays in the log regardless, so a replay from the cursor recovers anything a failed delivery missed.
- 5 attempts over about 6 hours with exponential backoff.
- After the last attempt, the delivery moves to a dead letter visible at GET /v1/catches/{id}/deliveries with the last error.
- The catch keeps running. One email per dead-lettered catch per day tells you something is wrong.
- Every payload carries a delivery_id. Consumers deduplicate on it.
- POST /v1/catches/{id}/test sends a sample payload so the destination can be verified before a real mention fires it.
Why not just MCP
MCP is a request and a response. A server cannot start the conversation. Products that ship only MCP say so in their own docs and point you at webhooks. discatch ships the MCP server for reading and control, and ships push so a catch that fires at 3am starts the agent instead of waiting for it. The two surfaces complement each other: MCP to set up the catch, the destination to deliver it.
What discatch never does
- Post on your behalf. The suggested action is a note, not an action.
- Run your agent. The destination starts it; discatch calls out and stops.
- Charge for a catch that fires nothing.