Introducing Webhook Signals for Mastra Agents

Your agents can now react to webhook events from GitHub, Slack, Stripe, or your own API.

Paul ScanlonPaul Scanlon·

Jul 1, 2026

·

3 min read

You can now connect your agents to events from external systems using a WebhookSignalProvider. Each event arrives as a notification signal, injected into the agent's thread without restarting the conversation or invalidating the prompt cache.

WebhookSignalProvider is part of the broader Signal providers system.

Before webhook providers, notifications could be sent to running agents using .sendNotificationSignal() but additional wiring was required to ensure payloads were sent to the right thread.

Now you can forward a payload using handleWebhook(), which matches an event with a subscription to deliver a notification to the right thread.

To the agent, an incoming webhook payload becomes another signal in the thread. A single conversation can hold user input alongside events from multiple external sources.

Get started

Configure a WebhookSignalProvider with two functions:

  1. extractResourceId: Can be used to find a unique identifier from the webhook payload.
  2. buildNotification: Defines the shape and data of the notification.
note

Requires @mastra/core@1.39.0 or later, added in PR #17577.

In this example, the repository.name is used as the externalResourceId and can be used later when subscribing to a thread. Setting a delivery policy to priority : "urgent" wakes the agent so it can respond to events.

TypeScriptsrc/mastra/signals/github-signals.ts
import { WebhookSignalProvider } from "@mastra/core/signals";
 
export const githubSignals = new WebhookSignalProvider({
  extractResourceId: (payload) => {
    const {
      repository: { full_name }
    } = payload;
    return full_name;
  },
  buildNotification: (payload) => {
    const {
      action,
      issue: { number, title, body }
    } = payload;
    return {
      source: "github",
      kind: action,
      priority: "urgent",
      summary: `#${number} ${title}`,
      payload
    };
  }
});

Pass the provider to your agent's signals:

TypeScriptsrc/mastra/agents/repo-agent.ts
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { githubSignals } from "../signals/github-signals";
 
export const repoAgent = new Agent({
  id: "repoAgent",
  name: "Repo Agent",
  model: "anthropic/claude-opus-4-8",
  instructions: "You're a GitHub repository assistant.",
  signals: [githubSignals],
  memory: new Memory()
});

Register the agent and mount a webhook route with registerApiRoute() — the handler forwards each request to handleWebhook():

TypeScriptsrc/mastra/index.ts
import { Mastra } from "@mastra/core/mastra";
import { registerApiRoute } from "@mastra/core/server";
import { repoAgent } from "./agents/repo-agent";
import { githubSignals } from "./signals/github-signals";
 
export const mastra = new Mastra({
  // ...
  agents: { repoAgent },
  server: {
    apiRoutes: [
      registerApiRoute("/webhooks/github", {
        method: "POST",
        handler: async (c) => {
          const body = await c.req.json();
          const headers = Object.fromEntries(c.req.raw.headers);
          const result = await githubSignals.handleWebhook({ body, headers });
          return c.json({ ok: true }, 200);
        }
      })
    ]
  }
});

The API route becomes a webhook URL:

Use .subscribeThread to subscribe your webhook provider to a thread, passing in a threadId, resourceId, and externalResourceId.

import { mastra } from "./mastra";
import { githubSignals } from "./mastra/signals/github-signals";
 
const threadId = "thread-123";
const resourceId = "repoAgent";
const externalResourceId = "<repository.name>"; // The  identifier extractResourceId returns
 
const repoAgent = mastra.getAgent("repoAgent");
 
await repoAgent.stream("Hello RepoAgent", {
  memory: { thread: threadId, resource: resourceId }
});
 
githubSignals.subscribeThread({ threadId, resourceId }, externalResourceId);

For more information and full configuration options, see:

Share:
Paul Scanlon
Paul ScanlonTechnical Product Marketing Manager

Paul Scanlon sits between Developer Education and Product Marketing at Mastra. Previously, he was a Technical Product Marketing Manager at Neon and worked in Developer Relations at Gatsby, where he created educational content and developer experiences.

All articles by Paul Scanlon