time-based-actions
$
npx mdskill add vellum-ai/vellum-assistant/time-based-actionsQuick-reference decision guide for choosing the right tool when users ask about time-triggered actions, recurring automation, notifications, or task tracking.
SKILL.md
.github/skills/time-based-actionsView on GitHub ↗
---
name: time-based-actions
description: Unified routing guide for reminders, schedules, notifications, and tasks - prevents common misrouting
compatibility: "Designed for Vellum personal assistants"
metadata:
emoji: "⏰"
vellum:
category: "productivity"
display-name: "Time-Based Actions"
---
Quick-reference decision guide for choosing the right tool when users ask about time-triggered actions, recurring automation, notifications, or task tracking.
## Decision Tree
1. **Does the request have a specific future time AND should fire only once?**
- YES -> `reminder_create`
- Examples: "remind me at 3pm", "remind me in 5 minutes", "alert me tomorrow at 9am"
2. **Does the request have a recurring pattern?**
- YES -> `schedule_create` with `mode: "notify"` (for recurring reminders/alerts) or `mode: "execute"` (if the assistant should act autonomously each recurrence)
- Default to `mode: "notify"` for recurring reminder-style requests. Use `mode: "execute"` only when each recurrence should trigger the assistant to perform a task (e.g. "every morning, check my email and summarize it").
- Examples: "every day at 9am", "weekly on Mondays", "every 2 hours"
3. **Does the request need an alert RIGHT NOW (no delay)?**
- YES -> `assistant notifications send` via `bash`
- Examples: "send me a notification", "alert me now", "ping me"
4. **Is the request about tracking work with no time trigger?**
- YES -> `task_list_add`
- Examples: "add to my tasks", "remind me to do X" (no time), "put this on my list"
## Critical Warning: `assistant notifications send` is IMMEDIATE-ONLY
`assistant notifications send` fires **instantly** when called. It has **NO delay, scheduling, or future-time capability**. NEVER use it for:
- "Remind me in 5 minutes" -> use `reminder_create`
- "Alert me at 3pm" -> use `reminder_create`
- "Notify me tomorrow" -> use `reminder_create`
If you use `assistant notifications send` for any of these, the notification fires immediately and the user misses their intended reminder.
## Critical Warning: `task_list_add` has NO time trigger
`task_list_add` creates a work queue item. It does **NOT** fire at a specific time. NEVER use it as a workaround for delayed notifications. If the user wants a timed alert, use `reminder_create`.
## Time Grounding Source
Use the `current_time:` field from the injected `<turn_context>` block as the authoritative clock source. The format is:
```
current_time: 2026-04-02 (Wednesday) 14:30:00 -05:00 (America/Chicago)
```
It contains the date, weekday name, local time (HH:MM:SS), UTC offset, and IANA timezone name in parentheses.
**Timezone confidence check:** The timezone shown may be the assistant host's timezone rather than the user's actual timezone (this happens when the user hasn't configured `Settings → Appearance → User timezone`). If you have no prior confirmation of the user's timezone (from conversation history or memory) and the request is locale-specific (e.g. "at 3pm", "tomorrow morning", "tonight"), confirm the timezone once before scheduling. If the user confirms, suggest saving it in Settings → Appearance → User timezone so future requests resolve correctly without re-asking.
## Relative Time Parsing
When the user says "in X minutes/hours", compute the ISO 8601 timestamp yourself:
- Take the time and offset from the `current_time:` field (e.g. `23:26:00 -05:00`)
- Add the requested offset
- Format as ISO 8601 with timezone: `2025-03-15T09:05:00-05:00`
- Pass to `reminder_create` as `fire_at`
### Anchored & Ambiguous Relative Time
Phrases like "at the 45 minute mark", "at the top of the hour", "on the half-hour", "at noon", "20 minutes in", or "when I hit an hour" are **clock-position or anchored relative time** expressions. Do NOT treat them as offsets from now.
**Resolution rules (in priority order):**
1. **Conversation-anchored expressions** - if the user mentioned a start time earlier in conversation ("I got here at 9", "meeting started at 2:10"), interpret offset-style phrases ("the 45 minute mark", "20 minutes in", "when I hit an hour") as `start_time + offset`. This takes precedence because the conversational anchor overrides any wall-clock interpretation.
2. **Clock-position expressions** - when no start time is in context, map directly to a wall-clock time:
- "top of the hour" / "on the hour" → next :00 (e.g. 10:00 AM)
- "the X minute mark" / "at :XX" → current hour's :XX; if already past, advance one hour
- "the half-hour mark" / "half past" → nearest upcoming :30
- "noon" / "midnight" → 12:00 PM or 12:00 AM today; if past, tomorrow
- "quarter past" / "quarter to" → :15 or :45 of current or next hour
3. **Ask only if truly ambiguous** - if neither rule 1 nor rule 2 resolves, ask: "Do you mean [clock time] or [X minutes from now]?" Never silently default to "from now."
**Examples:**
- "meeting started at 2:10, remind me at the 45 minute mark" → 2:55 PM (start + 45 min)
- "20 minutes in, I started at 2pm" → 2:20 PM (start + 20 min)
- "at the 45 min mark" (no start time, now: 9:39) → 9:45 AM (wall-clock)
- "at the 45 min mark" (no start time, now: 9:50) → 10:45 AM (wall-clock, next hour)
- "top of the hour" (now: 9:39) → 10:00 AM
- "at noon" → 12:00 PM today
- "at the hour mark" with no start time → ask for clarification
## "Remind me to X" Disambiguation
The word "remind" is ambiguous. Route based on whether a time is specified:
| User says | Time present? | Tool |
| ------------------------------------------- | --------------- | ----------------- |
| "Remind me to buy milk" | No | `task_list_add` |
| "Remind me to buy milk at 5pm" | Yes | `reminder_create` |
| "Remind me in 10 minutes to check the oven" | Yes (relative) | `reminder_create` |
| "Remind me every morning to take vitamins" | Yes (recurring) | `schedule_create` |
## Reminder Modes
`reminder_create` supports two modes:
- **`notify`** (default) - shows a notification to the user when the reminder fires
- **`execute`** - sends the reminder message to a background assistant conversation for autonomous handling
Use `notify` for simple alerts. Use `execute` when the reminder should trigger the assistant to do something (e.g., "in 30 minutes, check if the build passed").
## Reminder Routing
`reminder_create` supports a `routing_intent` parameter that controls how the reminder is delivered at trigger time:
- **`single_channel`** - deliver to one best channel
- **`multi_channel`** - deliver to a subset of channels
- **`all_channels`** (default) - deliver to every available channel
You can also pass `routing_hints` (a JSON object) to influence routing decisions (e.g. preferred channels, exclusions).
### Routing Defaults
Use the following heuristics to pick `routing_intent`:
- **Default to `all_channels`** for most reminders. Users setting reminders usually want to be notified wherever they are, and redundant notifications are less harmful than missed ones.
- **Use `single_channel`** only when the user explicitly specifies a single channel (e.g. "remind me on Telegram") or the reminder is low-stakes and noise reduction matters.
- **Determine the originating channel** for routing hints using this priority:
1. **`source_channel`** from `<turn_context>` — use directly if present. This is the authoritative channel name.
2. **`interface` fallback** — if `source_channel` is absent (common for guardian/direct users), map the `interface` value to a channel name:
| `interface` value | Channel name |
| --- | --- |
| `macos`, `ios` | `vellum` |
| `telegram` | `telegram` |
| `slack` | `slack` |
| `cli` | _(omit — no routable channel)_ |
3. If neither field is present or the interface is `cli`, omit `preferred_channels`.
When a channel is determined, include it as a routing hint:
```
routing_hints: { preferred_channels: ["<resolved channel>"] }
routing_intent: "all_channels"
```
- **Never use `single_channel` as a passive default.** If you haven't thought about which channel to use, use `all_channels`.
### Examples
| Scenario | routing_intent | routing_hints |
| ------------------------------------------ | ---------------- | -------------------------------------- |
| `source_channel: telegram` in turn_context | `all_channels` | `{ preferred_channels: ["telegram"] }` |
| No `source_channel`, `interface: macos` | `all_channels` | `{ preferred_channels: ["vellum"] }` |
| No `source_channel`, `interface: ios` | `all_channels` | `{ preferred_channels: ["vellum"] }` |
| User says "remind me on Telegram" | `single_channel` | `{ preferred_channels: ["telegram"] }` |
| No `source_channel`, `interface: cli` | `all_channels` | `{}` |
| No channel info available | `all_channels` | `{}` |
## Tool Summary
| Tool | Timing | Recurrence | Purpose |
| ------------------------------ | ---------------------- | ---------------- | --------------------------------------------- |
| `reminder_create` | Future time (one-shot) | No | Timed notification or timed autonomous action |
| `schedule_create` | Recurring pattern | Yes (cron/RRULE) | Recurring automated jobs |
| `assistant notifications send` | **Immediate only** | No | Alert the user right now |
| `task_list_add` | **No time trigger** | No | Track work in the task queue |
More from vellum-ai/vellum-assistant
- acpSpawn external coding agents via the Agent Client Protocol (ACP)
- amazonShop on Amazon and Amazon Fresh through your browser
- api-mappingRecord and analyze API surfaces of web services
- app-builderBuild and edit small, personal visual tools and artifacts — dashboards, trackers, calculators, data visualizations, charts, simple landing pages, and slide decks the user wants for THEMSELVES. This is the right skill whenever the user asks to "visualize this," "make a chart," or "build an artifact" for their own use, or to edit an app they already built here. Do NOT reach for a ui_show dynamic_page to fake an artifact — build a real persistent app here. NOT for complex, multi-user, or shippable products — those go to a real project folder with a coding agent (see Scope below).
- app-controlDrive a specific named macOS app via raw input bypassing the Accessibility tree
- assistant-migrationMigrate from ChatGPT, Claude, OpenClaw, Hermes, Manus, and other AI assistants into Vellum by inspecting their data exports, conversation archives, files, prompts, custom instructions, memory, saved memories, tools, GPTs, workflows, integrations, and relationships, then mapping as much as safely possible into Vellum primitives. Handles single-source and multi-source migrations with a unified, deduplicated inventory.
- chatgpt-importImport conversation history from ChatGPT into Vellum
- cli-discoverDiscover which CLI tools are installed, their versions, and authentication status
- computer-useControl the macOS desktop
- contactsManage contacts, communication channels, access control, and invite links