name: onesignal-messages
description: Use this skill when the user wants to compose or send a one-off OneSignal message — push notification, email, SMS, or in-app message — outside of a Journey or recurring automation. Triggers on "send a push", "send an email", "send a campaign", "send a one-off / blast / broadcast", "schedule a message for [time]", "send to [segment]", "test send to me", "create an in-app message", or any single message creation that doesn't need a multi-step automation.
OneSignal Messages Skill
Purpose
Help the agent compose and send a single OneSignal message — push, email, SMS, or in-app — to a defined audience. This skill covers one-off campaigns, transactional sends, and dashboard-or-API send composition.
This is a reasoning guide, not a script.
When to Use
Trigger phrases: "send a push / email / SMS", "send a campaign / blast / broadcast", "schedule a message for [time]", "send to [segment / VIPs / Pro users]", "test send", "create an in-app message", "transactional message", "send a one-off announcement".
Lookalike intents that should NOT trigger this skill:
- A multi-step or branching flow — use
onesignal-journeys. - Reusable content alone with no send — use
onesignal-templates. - Audience definition only — use
onesignal-segments.
A single message inside a Journey is handled by the Journeys skill, not this one.
Key Concepts
A message is a single send across one channel:
- Push — mobile (iOS/Android/Huawei) or web. Requires platform credentials + opted-in push Subscriptions.
- Email — requires authenticated sending domain + email-opted-in Subscriptions.
- SMS — requires SMS setup + 10DLC/toll-free registration for US + opt-in. MMS = SMS with media.
- In-app message (IAM) — displayed inside the mobile app on next session (30+ s background then re-open). Not opt-in; targets all mobile Subscriptions matching the trigger.
A send has three parts:
- Audience — who receives it (segment include/exclude, filter, or specific subscription IDs).
- Content — the message itself (or a
template_id reference). - Delivery options — schedule, throttling, frequency capping, time-of-day delivery, intelligent delivery, A/B test, conversion tracking.
For full per-channel field catalogs, delivery semantics, compliance requirements, and analytics retention, read REFERENCE.md.
Decisions That Shape a Message
Each dimension has a priority tag:
- Channel (Critical) — push / email / SMS / in-app. Mutually exclusive per send.
- Audience (Critical) — Segment(s), filter, or specific Subscription IDs. Default include = "Subscribed Users" of that channel; exclude empty.
- Content (Critical) — start from scratch, use a template (
template_id), or paste/upload existing content. - Personalization (Often defaultable) — Liquid placeholders, multi-language variants. Default to none unless the user signals otherwise.
- Schedule (Often defaultable) — send now / scheduled timestamp / "Intelligent Delivery" (per-user optimal time) / per-user time zone.
- Throttling + frequency capping (Almost always defaultable) — defer to app-level settings unless the user explicitly raises them.
- A/B test (Almost always defaultable) — only if the user asked. Default off.
- Conversion tracking (Often defaultable) — recommend on for marketing campaigns; offer to set the conversion event.
- Name + label (Almost always defaultable) — internal-only; suggest a clear name based on purpose and date.
- For IAM only: triggers + delivery schedule + display once-per-user.
- Call
get_platform_settings (or channel-specific equivalent) to confirm the channel is set up. Push without credentials, email without an authenticated domain, SMS without 10DLC/toll-free for US — all silently fail. - Call
list_segments to see if the requested audience already exists. If the user said "send to my engaged users" and you have to define "engaged" first, route to the segments skill or surface existing matches. - Call
list_templates to see if a relevant template already exists. Suggest using it via template_id rather than re-pasting content. - Call
preview_segment_count (or equivalent) to estimate the audience size BEFORE sending — surface unusually large or unusually empty audiences in the summary. - For SMS specifically, also confirm 10DLC/toll-free registration status.
How to Reason About Questions
- Identify channel from the user's prompt. If unclear, that's the FIRST question.
- Walk Decisions; mark each Specified / Defaultable / Open.
- Ground in tools — many "Open" dimensions become "Specified" once you've checked existing data + setup.
- Skip AskUserQuestion entirely for fully-specified prompts ("Send a push to my 'Active Users' segment that says 'Hi, sale ends tonight'"). Summarize with assumptions + audience size.
- Otherwise bundle 1–4 most decisive open dimensions into ONE AskUserQuestion call.
Ambiguity to Watch For
- "send a campaign" — one-off blast vs Journey vs recurring? Default to one-off. Confirm if the user describes ongoing behavior.
- "send to everyone" — confirm "Subscribed Users" of that channel (the default), not literally every record. Surface the audience size.
- "transactional" — usually wants
template_id + per-send override + small targeted audience (often a single Subscription ID). Often better suited for the API than the dashboard. - "announcement" — usually a push or email blast to all subscribed users; default schedule = send now.
- "newsletter" — usually a recurring email with a content template; if the user says "every week", it's a recurring Journey, not a one-off.
- "schedule" without time — clarify timezone (account default vs per-user).
- "with an image" for SMS — that's MMS, has different rules and cost.
- "in-app message" — clarify what the trigger is (immediately on next session vs after a custom event).
- "test send" — usually wants to send only to Test Users segment; surface that the audience will be filtered to Test Users.
Defaults & Best Practices
Apply silently and surface as assumptions:
- Audience: "Subscribed Users" of the channel + no exclusions. If the channel-specific Subscribed Users segment is huge (all your users), confirm that's intended.
- Content: if the user pasted text, use it as-is; if they referenced a template, use
template_id; otherwise propose a draft and ask for approval. - Schedule: send now unless the user mentioned a time. For "schedule for [date/time]" without timezone, default to the account/app timezone and surface the time in summary.
- Personalization: minimal. If the user wants
{{user.first_name}}, always recommend | default: "there" to avoid empty renders. - A/B test, throttling, frequency cap, intelligent delivery: off unless asked.
- Conversion tracking: offer it for marketing campaigns; default off for transactional.
- Name: suggest based on purpose + date ("Flash Sale Push — 2026-05-12").
Best practices:
- For email blasts, surface the unsubscribe link path and note the importance of warmed-up sending domain.
- For SMS, always include opt-out language ("Reply STOP to opt out") for US sends.
- For push, recommend a click action URL even for blast campaigns.
- For IAM, recommend a delivery schedule (e.g. 7 days) so old messages don't pop up months later.
- Recommend a small test send before any large blast.
For more depth on per-channel fields, scheduling options, A/B test mechanics, conversion tracking, throttling, frequency capping, and IAM triggers, read REFERENCE.md. For full reasoning traces, read EXAMPLES.md.
Summary and Approval
Every summary must include:
- Channel + name.
- Audience (with estimated count when available).
- Content in human-readable form.
- Personalization placeholders (with "may render empty" warnings for un-set fields).
- Schedule (with timezone called out).
- Conversion tracking + A/B test status.
- Assumptions — every default applied so the user can correct them.
- Must-mention warnings for this domain:
- Push, email, and SMS only deliver to opted-in Subscriptions.
- Email needs an authenticated sending domain (SPF / DKIM / DMARC); unauthenticated sends bounce or land in spam.
- SMS needs 10DLC or toll-free registration for US; unregistered traffic is blocked by carriers.
- In-app messages require a NEW session to display (30+ s background then re-open) and display only once per user per message by default.
- Audience counts may be exact or estimated — label estimates as such.
- Schedule timezone defaults to the app's timezone unless the user picked per-user delivery.
Require explicit user approval before sending. For blasts to large audiences (>10k), require an extra confirmation and surface the count.
Anti-Patterns
Avoid:
- Sending to "everyone" without surfacing the audience size.
- Suggesting one message can send across multiple channels — false. One channel per send (a multi-channel campaign is multiple sends OR a Journey).
- Using
{{user.tags.<name>}} placeholders without confirming the tag exists; renders empty silently. - Composing SMS without including opt-out language for US.
- Skipping the conversion-tracking offer for marketing campaigns.
- Silently scheduling in the wrong timezone — always surface timezone in the summary.
- Pretending a template can be sent across channels — push templates can only be used in push sends, etc.
- Reproducing this skill's example wording verbatim — derive your own from the user's prompt.
Supporting Files
REFERENCE.md — per-channel field catalog, scheduling options (now / scheduled / Intelligent Delivery / per-user TZ), A/B test mechanics, conversion tracking, throttling, frequency capping, IAM triggers and delivery schedule, compliance.EXAMPLES.md — worked traces (vague request, push blast, scheduled email, OTP transactional, A/B test, IAM, "test send only").