signal
Skill: Signal — Smart Notification Engine
Set up AI-powered notifications that decide IF, WHAT, WHEN, and HOW to notify each person. Signal uses Personize memory and governance to send the right message, to the right person, at the right time — or stay quiet when silence is better.
What This Skill Solves
Most notification systems are dumb rules: "if event X, send template Y." They don't know who the person is, what they care about, what was already sent, or whether this notification will help or annoy.
Signal replaces rules with intelligence:
- IF — Should this person be notified at all? (AI scores 0-100 based on full entity context)
- WHAT — What should the message say? (Uniquely personalized using everything known about the person)
- WHEN — Now, or later in a digest? (AI decides priority: immediate / standard / digest)
- HOW — Which channel? (Email, Slack, in-app, SMS — chosen based on context)
The intelligence comes from Personize SDK — memory, governance, and AI. Signal packages the orchestration into a reusable engine.
When This Skill is Activated
If the developer mentions notifications, alerts, or messaging, start with ASSESS.
If the developer has a specific question (e.g., "how do I add a Slack channel to Signal"), jump to the relevant action.
If the developer wants to understand the architecture, walk them through the engine flow.
When NOT to Use This Skill
- Need raw memory operations → use entity-memory
- Need shared workspaces without notifications → use collaboration
- Need governance rules without notifications → use governance
- Need CRM data sync → use entity-memory (CRM sync section)
Actions
| Action | When to Use |
|---|---|
| ASSESS | Understand their stack, events, channels, and recipients |
| CONFIGURE | Generate Signal initialization code |
| CONNECT | Scaffold event hooks for their framework |
| GOVERN | Set up governance rules for notification guidelines |
| TEST | Run a dry-run evaluation and verify the decision |
Action: ASSESS
Understand what the developer needs before writing code.
Questions to Ask
-
What events matter? — What happens in your product that should potentially trigger a notification?
- User lifecycle: signup, login, trial expiry, churn risk
- Usage: milestones, drops, feature adoption
- CRM: deal changes, meeting outcomes, support tickets
- System: sync complete, errors, billing events
-
Who are the recipients? — Who gets notified?
- End users (in-app, email)
- Internal team (Slack, email)
- Both (different channels)
-
What channels? — How should messages be delivered?
- Email (SES, SendGrid)
- Slack (webhook)
- In-app (bridge to existing UI)
- SMS (Twilio — community channel)
-
What governance rules exist? — What constraints apply?
- Max notifications per day per user
- Quiet hours / time zones
- Content policies (tone, compliance)
- Opt-out preferences
-
What framework? — Where do events originate?
- Express.js / Fastify / Next.js / NestJS
- Trigger.dev / n8n / cron jobs
- Webhook-based (external system pushes events)
Output
After assessment, summarize:
- Events to handle (with types like
user.signup,usage.drop) - Channels needed
- Governance constraints
- Framework/integration approach
Action: CONFIGURE
Generate the Signal initialization code based on the assessment.
Minimal Setup
import { Personize } from '@personize/sdk';
import { Signal, ConsoleChannel, ManualSource } from '@personize/signal';
const client = new Personize({ secretKey: process.env.PERSONIZE_SECRET_KEY! });
const manual = new ManualSource();
const signal = new Signal({
client,
channels: [new ConsoleChannel()],
sources: [manual],
});
await signal.start();
Production Setup
import { Personize } from '@personize/sdk';
import {
Signal,
ManualSource,
SesChannel, // or SendGridChannel
SlackChannel,
InAppChannel,
} from '@personize/signal';
const client = new Personize({ secretKey: process.env.PERSONIZE_SECRET_KEY! });
const manual = new ManualSource();
const signal = new Signal({
client,
channels: [
new SesChannel({ sourceEmail: 'notifications@yourapp.com' }),
new SlackChannel({ webhookUrl: process.env.SLACK_WEBHOOK! }),
new InAppChannel(async (recipient, payload) => {
// Bridge to your existing notification UI
await yourNotificationService.create({
userId: recipient.userId,
title: payload.subject,
body: payload.body,
});
return { success: true, channel: 'in-app', timestamp: new Date().toISOString() };
}),
],
sources: [manual],
engine: {
dailyCap: 5, // max per user per day
deduplicationWindowMs: 6 * 60 * 60 * 1000, // 6 hours
memorize: true, // feedback loop
workspaceUpdates: true, // track in workspace
},
});
await signal.start();
// Schedule daily digests (weekdays 9 AM)
signal.schedule('daily-digest', '0 9 * * 1-5', async () => {
const users = await getActiveUsers();
await signal.digest.runBatch(users);
});
Configuration Reference
| Option | Default | Description |
|---|---|---|
engine.dailyCap |
5 | Max notifications per email per day |
engine.deduplicationWindowMs |
6h | Skip same event type within window |
engine.memorize |
true | Record sent notifications in memory |
engine.workspaceUpdates |
false | Create workspace entries on SEND/DEFER |
engine.concurrency |
5 | Max parallel evaluations |
engine.maxEvaluationsPerMinute |
20 | Rate limit for batch processing |
Action: CONNECT
Scaffold event hooks that push product events into Signal.
Express.js Pattern
// event-hooks.ts — fire-and-forget, never throws, never blocks
import { ManualSource } from '@personize/signal';
const manual = new ManualSource(); // same instance used in Signal config
export const EventHooks = {
async onUserSignup(email: string, data?: Record<string, unknown>) {
manual.emit({
id: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,
type: 'user.signup',
email,
data: data || {},
timestamp: new Date().toISOString(),
metadata: { team: 'product' },
});
},
async onUsageDrop(email: string, data: { metric: string; dropPercent: number }) {
manual.emit({
id: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,
type: 'usage.drop',
email,
data,
timestamp: new Date().toISOString(),
metadata: { team: 'product' },
});
},
};
Using in Controllers
// In your signup controller
router.post('/signup', async (req, res) => {
const user = await createUser(req.body);
EventHooks.onUserSignup(user.email, { plan: user.plan }).catch(() => {});
res.json(user);
});
Webhook Source (external events)
import { WebhookSource } from '@personize/signal';
const webhookSource = new WebhookSource({
path: '/webhooks/signal',
secret: process.env.WEBHOOK_SECRET,
parser: (body) => ({
id: body.id || `wh_${Date.now()}`,
type: body.event || 'webhook.received',
email: body.email || body.user_email,
data: body.data || body,
timestamp: body.timestamp || new Date().toISOString(),
}),
});
// Mount on Express
app.use(webhookSource.middleware());
Action: GOVERN
Set up governance rules that guide Signal's AI decisions.
Governance Variables to Create
Use the Personize web app or SDK to create these governance variables:
1. Notification Guidelines (tag: notifications)
Notification Policy:
- Never notify about events the user has already seen in the product
- Prioritize actionable insights over informational updates
- Match tone to the urgency: critical = direct, informational = friendly
- Always include a specific next step, not generic "check it out"
- Maximum 3 notifications per user per day (engine enforces 5 as hard cap)
2. Channel Routing (tag: notifications)
Channel Selection:
- Slack: For internal team alerts (sales, support, ops)
- Email: For user-facing notifications that need persistence
- In-app: For real-time product notifications when user is active
- Digest: For low-priority updates that can wait for weekly summary
3. Frequency Policy (tag: communications)
Communication Frequency:
- New users (< 30 days): Max 1 notification per day. Focus on onboarding milestones.
- Active users: Max 3 per week. Only high-signal events.
- At-risk users: Increase frequency for re-engagement. Max 1 per day.
- Churned users: Do not notify. Only send win-back campaigns via marketing.
How Governance Flows into Signal
Signal's engine calls smartGuidelines() and smartDigest() in step 3 (context assembly). The AI sees these governance rules alongside the entity's full context and makes decisions accordingly. No code changes needed — update governance variables and Signal adapts.
Action: TEST
Verify Signal is working with a dry-run evaluation.
Quick Test
const result = await signal.trigger({
id: 'test_001',
type: 'user.signup',
email: 'test@example.com',
data: { plan: 'trial', source: 'website' },
timestamp: new Date().toISOString(),
});
console.log('Action:', result.action); // SEND | DEFER | SKIP
console.log('Score:', result.score); // 0-100
console.log('Reasoning:', result.reasoning);
console.log('SDK calls:', result.sdkCallsUsed);
console.log('Duration:', result.durationMs, 'ms');
What to Verify
- Pre-check works — Trigger the same event twice within 6 hours. Second should SKIP instantly (0 SDK calls).
- Daily cap works — Trigger 6 events for the same email. The 6th should SKIP.
- AI decision varies — Trigger different event types. Scores should vary based on context relevance.
- Feedback loop — After a SEND, check that the notification was memorized:
client.memory.recall({ query: 'signal:sent', email: '...' }). - Dedup via memory — After step 4, trigger a similar event. The AI should reference the recently sent notification in its reasoning.
Console Channel for Testing
Use ConsoleChannel during development — it logs decisions without delivering:
const signal = new Signal({
client,
channels: [new ConsoleChannel()], // logs to stdout
sources: [manual],
});
Available Resources
| Resource | Contents |
|---|---|
../../signal/README.md |
Full Signal documentation — architecture, channels, sources, workspace, digest, cost controls |
../../signal/CLAUDE.md |
AI tool instructions for Signal package |
../../signal/examples/quickstart/ |
Minimal setup example |
../../signal/examples/saas-onboarding/ |
Signup → nurture → convert sequence |
../../signal/examples/sales-alerts/ |
Usage drop alerts to sales team |
../../signal/examples/weekly-digest/ |
Deferred items → compiled digest |
../../signal/examples/multi-team/ |
Product + Sales + Marketing on same records |
../../signal/templates/CHANNEL_TEMPLATE.md |
How to build a new channel |
../../signal/templates/SOURCE_TEMPLATE.md |
How to build a new source |
recipes/quickstart.ts |
Minimal Signal setup recipe |
recipes/multi-team.ts |
Multi-team configuration recipe |
More from personizeai/personize-skills
personize-memory
Stores and retrieves persistent memory about records — contacts, companies, employees, members, and more. Handles memorization (single and batch with per-property AI extraction), semantic recall, entity digests, and data export. Use this skill whenever the user wants to store data, sync records from a CRM or database, query or search memory, recall what's known about a person or company, assemble context for personalization, import CSV or spreadsheet data, or do anything involving the Personize SDK's memory methods (memorize, recall, smartRecall, smartDigest, search, memorizeBatch). Also use when the user mentions contacts, leads, accounts, customer data, or entity properties.
21entity-memory
Stores and retrieves persistent memory about records — contacts, companies, employees, members, and more. Handles memorization (single and batch with per-property AI extraction), semantic recall, entity digests, and data export. Use this skill whenever the user wants to store data, sync records from a CRM or database, query or search memory, recall what's known about a person or company, assemble context for personalization, import CSV or spreadsheet data, or do anything involving the Personize SDK's memory methods (memorize, recall, smartRecall, smartDigest, search, memorizeBatch). Also use when the user mentions contacts, leads, accounts, customer data, or entity properties.
12no-code-pipelines
Generates importable n8n workflow JSON files that sync data between Personize and 400+ apps. Produces ready-to-import workflows for batch sync, webhook ingestion, per-record AI enrichment, and data export — no code required. Use this skill whenever the user wants no-code integrations, visual workflows, n8n automation, or to connect Personize to HubSpot, Salesforce, Google Sheets, Slack, Postgres, or any app without writing code. Also trigger when they mention 'workflow automation', 'scheduled sync without code', 'visual pipeline', or 'connect Personize to [app]' and don't want to write TypeScript.
12code-pipelines
Builds, deploys, and iterates production-ready AI agent pipelines using Trigger.dev and the Personize SDK. Handles the full lifecycle: interview the user about what they want, design the schema and governance, write the pipeline code, deploy it, monitor results, and iterate based on feedback. Generates TypeScript tasks for outbound sequences, inbound lead processing, conversational reply handlers, enrichment pipelines, and account signal monitoring — all backed by Personize memory, AI context, and governance. Use this skill whenever someone wants to build an AI agent, automated workflow, email sequence, drip campaign, cold outreach, lead enrichment, reply handler, account monitor, CRM automation, daily digest, or any durable pipeline — whether they provide technical specs or just describe what they want in plain language. Also trigger for Trigger.dev, background tasks, self-scheduling follow-ups, GTM automation, 'build me an agent that...', or 'I want to automate...'.
11collaboration
Turn any record into a shared workspace where agents and humans collaborate. Attach a simple workspace schema to any entity — contacts, companies, deals, projects, tickets — and let any participant contribute updates, tasks, notes, and issues. Use this skill whenever the user wants multi-agent collaboration, shared context on an entity, agent handoffs, workspace-based coordination, or the three-layer agent operating model (Guidelines + Memory + Workspace). Also trigger when they mention multiple agents working on the same record, deal rooms, account intelligence, customer health monitoring, cross-functional coordination, or progressive autonomy for AI agents.
11governance
Manages organizational guidelines, policies, and best practices as governance variables accessible to all AI agents via SmartContext. Use this skill whenever the user wants to create, update, or manage guidelines, brand voice, compliance policies, playbooks, ICPs, sales playbooks, tone rules, or any organizational rules. Also trigger when the user mentions smartGuidelines, governance variables, GitOps sync of policies, team knowledge sharing, AI agent rules, or when they want all their AI tools to follow the same policies. Even if they just say 'set up rules' or 'add a policy', this is the right skill.
11