Subscriptions, watchlists, alerts
The canonical 1:1 handler registration (ADR-0019) dispatches one trigger to one handler per (client_id × action_class). Subscriptions add a parallel, customer-driven channel: your app declares narrow slices of substrate activity it wants to receive dispatches for — filtered by counterparty, mode, or action class.
The five tools
subscriptions.create({...})— declare interest in(action_class, counterparty_filter, mode_filter, expires_at?).subscriptions.list({ active_only? })— read active subscriptions for your client.subscriptions.delete(subscription_id)— retire a subscription. Soft-deletes; historical match records preserved.watchlists.add({ counterparty_id, alert_on? })— shorthand for a per-counterparty subscription.alert_ontakes any subset ofnew_episode,commitment_due,trust_change.alerts.set({ target, trigger_at })— one-shot subscription with an explicit fire time. Auto-cleaned after firing.
Fan-out ordering
Subscriptions are evaluated before the canonical 1:1 dispatch in ADR-0019's pipeline. The rules:
- A matching subscription with the same
(client_id × action_class)as the canonical handler does not double-dispatch. The subscription is informational; the canonical handler still fires. - A matching subscription with a different
client_idfans out an additional dispatch. Forward-compatible with cross-app routing (V1.x+). - Subscription matches carry
source: 'subscription_match'metadata in the trigger envelope so your handler can distinguish them from canonical dispatches if it matters.
Example: a watchlist for high-stakes counterparties
ts
// Build a "VIP counterparties" surface that fires when anything happens
// involving these contacts. Watchlists are shorthand for per-counterparty
// subscriptions with alert_on filters.
await Promise.all(
vipCounterpartyIds.map(id =>
cortex.tools.call('watchlists.add', {
counterparty_id: id,
alert_on: ['new_episode', 'commitment_due', 'trust_change'],
})
)
);
// Your handler now receives dispatches for any substrate activity
// involving those counterparties in addition to canonical action dispatches.Quota and capacity
- Per-tenant subscription count caps apply (see rate limits).
- Counterparty-filter complexity bounded: a subscription can name at most 50 counterparty ids explicitly; classification filters are unbounded.
- Subscription tool calls count against
daily_tool_calls. Subscription reads count againstdaily_substrate_read_calls.
Cross-references
- Concept: Cross-app routing (read-preview) — subscriptions are the inbound-interest analog of the routing engine's outbound handler selection.
- Dispatch protocol (ADR-0019) — subscriptions ride the same dispatch pipeline as canonical handler registration.
- ADR-0021 §subscriptions; Architecture §4a.9 (Subscriptions & Watchlists).