Notifications logo

Notifications

OrganizationPopular
vellum-ai
notifications

Send notifications through the unified notification router

Overview

Publishervellum-ai
Repositoryvellum-assistant
Skill namenotifications
Stars
1.3K
Forks
186
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by vellum-ai on GitHub. Read the source before you install it.

Installation

Install the Notifications AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git /tmp/vellum-assistant
mkdir -p .claude/skills
cp -r /tmp/vellum-assistant/skills/notifications .claude/skills/notifications
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Notifications in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Notifications on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Notifications is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Call this when something happened that the user would want to know about — a completed task with a notable outcome, an interesting observation, a positive trend you noticed in monitored data, useful research worth surfacing, a workflow that got blocked, a credential or token failure, etc. Do not call it for routine task completions where nothing notable happened. When in doubt and you have a real observation to share, share it.

Exception: you are running a schedule. The "was this notable?" test does not apply to a scheduled run. The user picked the cadence; the run happening at all is what they asked to see. A scheduled run that produces any user-facing output (a briefing, a digest, a report, or a check whose answer is "nothing changed") ends by sending that output as a notification. Writing it into the conversation and stopping does not reach the user: nobody is looking at a scheduled run's conversation.

That does not license noise. Judgment moves from whether to notify to what to say: a run with a genuinely empty result says so in one line rather than padding it, and a run that only did silent housekeeping (rotating a cache, syncing a file) with nothing to report stays quiet.

Watcher ticks are not scheduled runs. A watcher stays quiet unless its action prompt says this event is worth surfacing. Unmatched events and polls with nothing new must not produce a notification.

Sending Notifications

Always pass --title. Skipping it triggers a fallback that just truncates --message to 60 chars and shows it as the title — the user sees the same text twice with no scannability gained.

bash
assistant notifications send \
  --title "Short headline" \
  --message "Your verbatim observation in your own words"

For time-sensitive items:

bash
assistant notifications send --title "..." --message "..." --urgent

Command Reference

FlagRequiredDescription
--message <message>YesNotification body. Markdown (GFM) renders in the detail panel; the OS banner shows plain text.
--title <title>Yes in practiceShort headline (≤ 8 words). Omitting it triggers a body-truncation fallback that shows up as a duplicate of --message — always write a real title.
--urgentNoMark as needing attention now/soon
--jsonNoOutput machine-readable JSON

Title

Write a --title for every notification. It's the only line the user sees in the lock-screen popup and the collapsed row of the notification list, so a short noun phrase (≤ 8 words) is what makes the notification scannable. If you omit --title, the system falls back to the first sentence of --message (truncated at 60 chars) — that's almost always worse than what you'd write, because it duplicates body text the user is already going to read.

Avoid restating the first sentence of --message verbatim — the title should add scannability, not duplicate.

Message

The body renders as markdown (GFM) in the home feed detail panel — where the user actually opens the notification on web, iOS, and macOS. Light markdown makes multi-fact bodies scannable. The OS lock-screen banner shows the body as plain text, so prefer inline emphasis over heavy structure that looks ugly unrendered.

Supported: **bold**, *italic*, `inline code`, fenced code blocks, links, bulleted and numbered lists, blockquotes, headings, GFM tables, ~~strikethrough~~.

Use it like this:

  • Bold the headline fact when the body has more than one sentence.
  • Bullets or numbered lists when surfacing multiple discrete items (failures, files touched, missed messages).
  • Inline code for identifiers, paths, commands, and short snippets.
  • Fenced code blocks for multi-line output (stack traces, diffs).

Avoid large headings (#, ##) and wide tables — they render fine in the panel but look noisy in the banner preview.

Urgent semantics

Use --urgent for items needing attention now/soon (blocked work, broken auth, time-sensitive issues). Skip for items the user should see when they have time.

Examples

bash
# Plain notification — bold the headline fact
assistant notifications send \
  --title "Backup complete" \
  --message "Nightly backup finished — **12.4 GB** archived to cold storage across **3** datasets."

# Urgent notification — inline code for the identifier
assistant notifications send \
  --title "Auth token expired" \
  --message "Sync is paused until you reauthenticate the \`GitHub\` integration." \
  --urgent

Response Format

json
{ "ok": true, "signalId": "...", "dispatched": true }

Reading Surfaced Notifications

bash
assistant notifications list --json

Reads from the user's home feed ($VELLUM_WORKSPACE_DIR/data/home-feed.json) — the inbox that mirrors background and async notifications surfaced via the unified pipeline. Real-time chat pushes that did not mirror to the feed (direct Telegram/Slack/Vellum-chat sends without --is-async-background) will not appear here.

When to call

  • Before sending: check whether you already surfaced a similar item recently (filter by --conversation-id or --after to dedupe).
  • Catch-up summaries: when the user asks "what did I miss" or returns after a session break, list the items they haven't dismissed.
  • Lookup: when the user references a past notification ("the email thing you flagged earlier"), find it by --conversation-id or date range.

Filters

FlagPurpose
--allInclude dismissed items (default: excluded — assistant cares about outstanding work)
--status <s>Filter by status (new / seen / acted_on / dismissed); repeatable. Overrides the --all default.
--before <iso> / --after <iso>ISO-8601 createdAt bounds (strict; = is excluded).
--urgency <u>Filter by urgency (low / medium / high / critical); repeatable.
--category <c>Filter by category (security / scheduling / background / email / system); repeatable.
--conversation-id <id>Only items tied to this conversation.
--from-assistantOnly items the assistant herself emitted.
--noteworthyOnly items flagged as noteworthy.
--limit <n>Default 20, max 200.
--offset <n>Pagination offset. Combine with --limit to walk older pages.

Examples

bash
# What's outstanding right now (defaults: skip dismissed, newest first)
assistant notifications list --json

# Everything you've shown the user today
assistant notifications list --after 2026-05-28T00:00:00Z --all --json

# Only high-stakes items
assistant notifications list --urgency high --urgency critical --json

# Pre-send dedupe: anything you already surfaced for this conversation
assistant notifications list --conversation-id 7fab234c --after 2026-05-28T00:00:00Z --json

# Walk older pages
assistant notifications list --limit 20 --offset 20 --json

Response shape

json
{
  "ok": true,
  "items": [
    /* FeedItem records: id, title?, summary, status, urgency?, category?, conversationId?, createdAt, ... */
  ],
  "total": 12,
  "returned": 3,
  "hasMore": true,
  "updatedAt": "2026-05-28T10:30:00.000Z"
}

Editing Notifications

Use edit when an already-sent notification needs revising — a typo in the body, a status update on something you previously surfaced (e.g. "in progress" → "done"), or de-escalating the urgency of a stale alert. Prefer editing over re-sending: a fresh notification with the corrected text creates duplicate noise in the user's inbox and pings them twice.

bash
assistant notifications edit --id <notif:uuid> --message "Corrected body"

Finding the id

The id field is the full notif:<uuid> printed by notifications list --json under items[].id. Bare uuids (without the notif: prefix) are also accepted.

bash
assistant notifications list --json | jq '.items[] | {id, title, summary}'

Command Reference

FlagRequiredDescription
--id <id>YesFeed item id (notif:<uuid>) or bare uuid
--message <text>No*New body — updates the home-feed summary AND the delivered channel message where supported
--title <text>No*New short headline (≤ 8 words)
--urgency <level>No*Change urgency (low/medium/high/critical). Feed-only — does not re-push channel messages
--status <state>No*Lifecycle transition (new/seen/acted_on/dismissed). Feed-only
--jsonNoMachine-readable JSON

*At least one of --message, --title, --urgency, or --status must be supplied.

Channel behavior

ChannelEdit behavior
Home feed (macOS/iOS inbox)Always updated when the item exists.
SlackUpdated in-place via chat.update when the original delivery captured a Slack ts. Deliveries older than this feature returned messageId: null and report outcome: "unsupported".
Push, email, SMSCannot be edited — reported as outcome: "unsupported" in the result.

Response shape

json
{
  "ok": true,
  "feedItem": {
    "id": "notif:...",
    "title": "...",
    "summary": "...",
    "status": "new",
    "urgency": "low"
  },
  "channels": [
    { "channel": "slack", "deliveryId": "...", "outcome": "updated" },
    {
      "channel": "platform",
      "deliveryId": "...",
      "outcome": "unsupported",
      "reason": "platform adapter does not support in-place edits"
    }
  ]
}

outcome values: "updated" (channel message edited successfully), "unsupported" (channel cannot edit at all), "skipped" (delivery wasn't in sent status), "failed" (channel-side error — see reason).

Examples

bash
# Fix a typo in the body
assistant notifications edit \
  --id notif:abc12345-... \
  --message "Backup completed — 12.4 GB archived to cold storage."

# De-escalate an urgent alert that resolved itself
assistant notifications edit --id notif:abc12345-... --urgency low

# Dismiss a notification you previously surfaced
assistant notifications edit --id notif:abc12345-... --status dismissed

Important

  • Do NOT use AppleScript display notification or other OS-level notification commands for assistant-managed alerts. Always use assistant notifications send.
  • For a digest, summary, or report that should land in a specific chat or email destination, use messaging_send. It reaches Gmail and Outlook as a draft, and posts to a Slack, Telegram, Discord, or WhatsApp chat through that channel's own transport, where the post is recorded.
  • For the user's notification inbox and connected push channels, use assistant notifications send and pass the complete authored body as --message. The pipeline keeps that body. Do not rewrite it into a short alert first. A scheduled run should also pass --source-channel scheduler.
  • Send notifications that fire immediately with no delay capability. For one-time future alerts, use schedule_create with fire_at. For recurring alerts, use schedule_create with an expression (cron/RRULE).

Frequently asked questions

What does the Notifications AI skill do?

Send notifications through the unified notification router

Why use Notifications on TypingMind?

Because you install it once and use it with any model. Notifications is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Notifications in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/vellum-ai/vellum-assistant/tree/main/skills/notifications. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Notifications?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Notifications?

As many as you like. As long as a model supports skills, you can use Notifications with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Notifications AI skill free?

Yes. It is published on GitHub by vellum-ai under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇