Skip to main content

WebhookSignalProvider

Added in: @mastra/core@1.39.0

beta

Breaking changes may occur without a major version bump until the API is stable.

Concrete signal provider for push-based event delivery. Routes incoming webhook payloads to subscribed agent threads by matching the payload against a configurable resource ID extractor.

Extends SignalProvider with public subscription management and a built-in handleWebhook() implementation.

Usage example
Direct link to Usage example

Route GitHub webhook events to subscribed threads:

src/signals/webhook.ts
import { WebhookSignalProvider } from '@mastra/core/signals'

const webhookProvider = new WebhookSignalProvider({
extractResourceId: payload => `${payload.repository?.full_name}`,
buildNotification: (payload, subscription) => ({
source: 'github-webhook',
kind: payload.action ?? 'event',
summary: `${payload.action} on ${subscription.externalResourceId}`,
payload,
}),
})

Register with an agent and subscribe a thread:

src/mastra/index.ts
import { Agent } from '@mastra/core/agent'

const agent = new Agent({
id: 'agent',
signals: [webhookProvider],
})

// subscribe a thread to a specific repo
webhookProvider.subscribeThread({ threadId: 'thread-1', resourceId: 'user-1' }, 'mastra-ai/mastra')

// handle an incoming webhook
const result = await webhookProvider.handleWebhook({
body: { repository: { full_name: 'mastra-ai/mastra' }, action: 'push' },
headers: {},
})
// result.matched === 1

Constructor parameters
Direct link to Constructor parameters

id?:

string
= 'webhook-signals'
Unique identifier for the provider instance.

name?:

string
= 'Webhook Signals'
Human-readable name.

extractResourceId?:

(payload: unknown) => string | string[] | undefined
= Returns `payload.resource` or `payload.externalResourceId` if present
Extract the external resource ID from a webhook payload. Return undefined to skip the event. Can return an array to match multiple resources.

buildNotification?:

(payload: unknown, subscription: SignalSubscription) => SendNotificationSignalInput
= Returns `{ source: id, kind: 'webhook-event', summary, payload }`
Build the notification object from a webhook payload and the matched subscription.

Methods
Direct link to Methods

Subscription management
Direct link to Subscription management

subscribeThread(target, externalResourceId, metadata?)
Direct link to subscribethreadtarget-externalresourceid-metadata

Subscribe a thread to receive webhook events for a specific external resource.

webhookProvider.subscribeThread(
{ threadId: 'thread-1', resourceId: 'user-1' },
'mastra-ai/mastra',
{ watchType: 'push' },
)

Returns: SignalSubscription

target:

SignalProviderTarget
The thread to subscribe. Must include threadId and resourceId.

externalResourceId:

string
The external resource to monitor (for example, a repository full name).

metadata?:

Record<string, unknown>
Additional data to store with the subscription.

unsubscribeThread(target, externalResourceId)
Direct link to unsubscribethreadtarget-externalresourceid

Unsubscribe a thread from a specific external resource.

const removed = webhookProvider.unsubscribeThread(
{ threadId: 'thread-1', resourceId: 'user-1' },
'mastra-ai/mastra',
)

Returns: boolean

Webhook handling
Direct link to Webhook handling

handleWebhook(request)
Direct link to handlewebhookrequest

Process an incoming webhook request. Extracts the resource ID from the payload and finds matching subscriptions. It builds a notification for each subscription and calls notify().

const result = await webhookProvider.handleWebhook({
body: { repository: { full_name: 'mastra-ai/mastra' }, action: 'push' },
headers: { 'x-github-event': 'push' },
})

Returns: Promise<{ status: number; body: { matched: number } }>

Returns { status: 200, body: { matched: N } } where N is the number of subscriptions that received notifications. Returns matched: 0 when no resource ID could be extracted or no subscriptions match.

request:

object
The incoming webhook request.
object

body:

unknown
The parsed webhook payload.

headers:

Record<string, string>
HTTP headers from the webhook request.

Static signal factories
Direct link to Static signal factories

WebhookSignalProvider.signals.subscribe(externalResourceId)
Direct link to webhooksignalprovidersignalssubscribeexternalresourceid

Create a reactive signal input that subscribes the current thread to an external resource.

const signal = WebhookSignalProvider.signals.subscribe('mastra-ai/mastra')

Returns: { type: 'reactive'; tagName: string; contents: string; attributes: { resource: string } }

WebhookSignalProvider.signals.unsubscribe(externalResourceId)
Direct link to webhooksignalprovidersignalsunsubscribeexternalresourceid

Create a reactive signal input that unsubscribes the current thread from an external resource.

const signal = WebhookSignalProvider.signals.unsubscribe('mastra-ai/mastra')

Returns: { type: 'reactive'; tagName: string; contents: string; attributes: { resource: string } }