@mastra/core
Version:
269 lines • 10.1 kB
TypeScript
import type { Agent } from '../agent/agent.js';
import type { AgentSignalIfIdleOptions } from '../agent/types.js';
import type { Mastra } from '../mastra/index.js';
import type { SendNotificationSignalInput } from '../notifications/types.js';
import type { InputProcessorOrWorkflow, OutputProcessorOrWorkflow } from '../processors/index.js';
/**
* Identifies a specific agent thread that a signal provider targets.
*
* @experimental Agent signals are experimental and may change in a future release.
*/
export type SignalProviderTarget = {
threadId: string;
resourceId: string;
agentId?: string;
/** Options for signal delivery when the target thread is idle — forwarded to sendNotificationSignal */
ifIdle?: AgentSignalIfIdleOptions<unknown>;
};
/**
* A subscription that links an agent thread to an external resource
* monitored by a signal provider.
*
* @experimental Agent signals are experimental and may change in a future release.
*/
export type SignalSubscription = {
/** Unique identifier for the subscription */
id: string;
/** The provider that owns this subscription */
providerId: string;
/** The thread receiving signals */
threadId: string;
/** The resource owning the thread */
resourceId: string;
/** Provider-specific identifier for the external resource (e.g., "github:owner/repo#123") */
externalResourceId: string;
/** When the subscription was created */
subscribedAt: Date;
/** Provider-specific metadata for the subscription */
metadata: Record<string, unknown>;
};
/**
* Options for the handleWebhook method.
*
* @experimental Agent signals are experimental and may change in a future release.
*/
export type SignalProviderWebhookRequest = {
body: unknown;
headers: Record<string, string>;
params?: Record<string, string>;
};
/**
* Abstract base for signal providers.
*
* A SignalProvider monitors external sources and pushes notification signals
* into agent threads. It combines three capabilities:
*
* 1. **Subscription tracking** — built-in registry of which threads are subscribed to which external resources
* 2. **External monitoring** — polling or webhook-driven event ingestion
* 3. **Optional processor/tool integration** — providers can expose input/output processors and tools
*
* Not all signal providers are processors. A provider that only polls an API
* and pushes notifications needs no processor hooks at all. Providers that
* need to intercept agent execution (e.g., injecting subscription hints) can
* return processors via `getInputProcessors()` / `getOutputProcessors()`.
* Providers that expose agent tools (e.g., subscribe/unsubscribe commands)
* can return them via `getTools()`.
*
* ## Usage
*
* ```ts
* const agent = new Agent({
* signals: [new MySignalProvider()],
* });
* ```
*
* The Agent automatically:
* - Calls `connect(this)` to establish the bidirectional link
* - Registers any processors returned by `getInputProcessors()` / `getOutputProcessors()`
* - Merges any tools returned by `getTools()`
* - Starts polling if `pollInterval` is defined
*
* ## Building a Provider
*
* Extend this class, implement the abstract `id` field, and override
* whichever hooks your provider needs:
*
* ```ts
* class SlackSignals extends SignalProvider<'slack-signals'> {
* readonly id = 'slack-signals';
* readonly pollInterval = 30_000; // poll every 30s
*
* async poll(subscriptions: SignalSubscription[]) {
* for (const sub of subscriptions) {
* // check Slack, emit notifications for changes
* }
* }
* }
* ```
*
* @experimental Agent signals are experimental and may change in a future release.
*/
export declare abstract class SignalProvider<TId extends string = string> {
#private;
abstract readonly id: TId;
readonly name?: string;
/**
* The Mastra instance this provider is registered with.
* Set by the framework when the agent is registered with Mastra.
*/
protected mastra?: Mastra<any, any, any, any, any, any, any, any, any, any>;
/**
* @internal Called when the provider's agent is registered with a Mastra instance.
*/
__registerMastra(mastra: Mastra<any, any, any, any, any, any, any, any, any, any>): void;
/**
* Called by the Agent constructor to establish the bidirectional link.
* Override to perform additional setup (always call `super.connect(agent)`).
*/
connect(agent: Agent<any, any, any, any>): void;
/**
* Whether this provider is already connected to an agent.
* Used to skip re-wiring when an Agent is forked via `__fork()`.
*/
get isConnected(): boolean;
/**
* The connected agent. Available after `connect()` has been called.
* Use this to send signals and notification signals back into agent threads.
*/
protected get agent(): Agent<any, any, any, any> | undefined;
/**
* Return input processors this provider needs registered with the agent.
* Override when your provider intercepts agent input steps (e.g., injecting
* subscription hints, detecting PR-related shell commands).
*
* @example
* ```ts
* getInputProcessors() {
* return [this]; // when the provider itself implements processInputStep
* }
* ```
*/
getInputProcessors?(): InputProcessorOrWorkflow[];
/**
* Return output processors this provider needs registered with the agent.
* Override when your provider intercepts agent output steps.
*/
getOutputProcessors?(): OutputProcessorOrWorkflow[];
/**
* Return tools this provider exposes to the agent.
* Override when your provider adds agent-callable tools (e.g.,
* subscribe/unsubscribe commands).
*
* @example
* ```ts
* getTools() {
* return {
* subscribe_pr: createTool({ ... }),
* unsubscribe_pr: createTool({ ... }),
* };
* }
* ```
*/
getTools?(): Record<string, unknown>;
/**
* Subscribe a thread to an external resource.
*
* @param target - The thread to receive signals
* @param externalResourceId - Provider-specific resource identifier
* (e.g., `"github:mastra-ai/mastra#123"`, `"slack:C0B01RW7A4T"`)
* @param metadata - Optional provider-specific metadata for the subscription
*/
protected subscribe(target: SignalProviderTarget, externalResourceId: string, metadata?: Record<string, unknown>): SignalSubscription;
/**
* Unsubscribe a thread from an external resource.
*
* @returns `true` if a subscription was removed, `false` if none existed
*/
protected unsubscribe(target: SignalProviderTarget, externalResourceId: string): boolean;
/**
* Get all active subscriptions for this provider.
*/
protected getSubscriptions(): SignalSubscription[];
/**
* Get all subscriptions for a specific external resource.
*
* @example
* ```ts
* const subs = this.getSubscriptionsForResource('github:mastra-ai/mastra#123');
* for (const sub of subs) {
* await this.notify({ ... }, { resourceId: sub.resourceId, threadId: sub.threadId });
* }
* ```
*/
protected getSubscriptionsForResource(externalResourceId: string): SignalSubscription[];
/**
* Get all subscriptions for a specific thread.
*/
protected getSubscriptionsForThread(target: SignalProviderTarget): SignalSubscription[];
/**
* Check if a thread is subscribed to a specific external resource.
*/
protected hasSubscription(target: SignalProviderTarget, externalResourceId: string): boolean;
/**
* Remove all subscriptions for a thread.
*/
protected unsubscribeAll(target: SignalProviderTarget): number;
/**
* Total number of active subscriptions.
*/
protected get subscriptionCount(): number;
/**
* Optional poll interval in milliseconds.
* When defined, the framework calls `poll()` on this interval
* with all active subscriptions.
*
* Set to `undefined` or `0` for webhook-only providers that don't poll.
*/
readonly pollInterval?: number;
/**
* Called on each poll cycle with all active subscriptions.
* Override to check external sources and emit notifications.
*
* @param subscriptions - All active subscriptions for this provider
*/
poll?(subscriptions: SignalSubscription[]): Promise<void>;
/**
* Start the polling timer. Called automatically by the Agent after `connect()`.
* Can also be called manually to restart polling after `stopPolling()`.
*/
startPolling(): void;
/**
* Stop the polling timer.
*/
stopPolling(): void;
/**
* Handle an incoming webhook request.
* Override to parse the payload, match it to subscriptions,
* and emit notification signals.
*
* The framework routes `POST /api/signals/:providerId` to this method.
*/
handleWebhook?(request: SignalProviderWebhookRequest): Promise<{
status?: number;
body?: unknown;
}>;
/**
* Called after `connect()` to perform async initialization.
* Override for setup that requires the agent or Mastra to be available.
*/
start?(): Promise<void> | void;
/**
* Called on shutdown. Override to clean up resources.
* Default implementation stops polling and clears all subscriptions.
*/
stop(): void;
/**
* Send a notification signal to the connected agent.
* Convenience wrapper around `this.agent.sendNotificationSignal()`.
*
* @throws If no agent is connected
*/
protected notify(notification: SendNotificationSignalInput, target: SignalProviderTarget): Promise<void>;
}
/**
* Type guard to check if an object is a SignalProvider.
*
* @experimental Agent signals are experimental and may change in a future release.
*/
export declare function isSignalProvider(obj: unknown): obj is SignalProvider;
//# sourceMappingURL=signal-provider.d.ts.map