with one click
schedule
// Recurring and one-shot scheduling - cron, RRULE, or single fire-at time
// Recurring and one-shot scheduling - cron, RRULE, or single fire-at time
Ingest and process media files (video, audio, image)
Read, search, send, and manage messages across Gmail, Outlook, Telegram, and other platforms
Join a Google Meet call to take notes; only when the user explicitly asks.
Migrate 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.
Send notifications through the unified notification router
Analyze and reduce LLM spend by mapping call-site overrides to managed profiles (Balanced / Quality / Speed). Covers spend analysis, profile assignment, and config correctness.
| name | schedule |
| description | Recurring and one-shot scheduling - cron, RRULE, or single fire-at time |
| compatibility | Designed for Vellum personal assistants |
| metadata | {"emoji":"📅","vellum":{"display-name":"Schedule","activation-hints":["User wants to set a reminder for a future time (e.g. 'remind me at 9am tomorrow', 'remind me to take meds at 8pm')","User wants to schedule a recurring task or automation (e.g. 'every weekday at 9am', 'every Monday at noon')","User wants to schedule a one-time future action the assistant should run autonomously (e.g. 'at 5pm check my email and summarize it')","User wants to list, update, cancel, or inspect existing scheduled tasks or reminders"],"avoid-when":["User wants to add something to their task list or queue — use task-list tools instead","User wants to act immediately or run a quick command that completes within the conversation — schedule is only for deferred or recurring execution"]}} |
Manage scheduled automations. Schedules can be recurring (cron or RRULE expression) or one-shot (a single fire_at timestamp). Schedules support three modes: execute (run a message through the assistant), notify (send a notification to the user), and script (run a shell command directly without LLM involvement).
Standard 5-field cron syntax: minute hour day-of-month month day-of-week
| Field | Values | Special characters |
|---|---|---|
| Minute | 0-59 | , - * / |
| Hour | 0-23 | , - * / |
| Day of month | 1-31 | , - * / |
| Month | 1-12 | , - * / |
| Day of week | 0-7 (0,7=Sun) | , - * / |
Examples:
0 9 * * 1-5 - weekdays at 9:00 AM30 8 * * * - every day at 8:30 AM0 */2 * * * - every 2 hours0 9 1 * * - first of every month at 9:00 AMiCalendar recurrence rules for complex patterns. Must include a DTSTART line.
Supported lines (all expressions must include DTSTART + at least one RRULE or RDATE):
| Line | Purpose |
|---|---|
DTSTART | Start date/time anchor (required) |
RRULE: | Recurrence rule (multiple lines = union of occurrences) |
RDATE | Add one-off dates not covered by the pattern |
EXDATE | Exclude specific dates from the set |
EXRULE | Exclude an entire recurring series |
Exclusions (EXDATE, EXRULE) always take precedence over inclusions (RRULE, RDATE).
DTSTART:20250101T090000Z\nRRULE:FREQ=DAILY - every day at 9:00 AM UTCDTSTART:20250101T090000Z\nRRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR - Mon/Wed/Fri at 9:00 AM UTCDTSTART:20250101T090000Z\nRRULE:FREQ=MONTHLY;BYMONTHDAY=1,15 - 1st and 15th of each monthDTSTART:20250101T090000Z\nRRULE:FREQ=DAILY;COUNT=30 - daily for 30 occurrences then stopDTSTART:20250101T090000Z\nRRULE:FREQ=WEEKLY;BYDAY=MO;UNTIL=20250331T235959Z - every Monday until end of MarchDTSTART:20250101T090000Z\nRRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR\nEXDATE:20250120T090000Z - Mon/Wed/Fri except Jan 20DTSTART:20250101T090000Z\nRRULE:FREQ=DAILY\nEXRULE:FREQ=WEEKLY;BYDAY=SA,SU - every weekday (daily minus weekends)DTSTART:20250101T090000Z\nRRULE:FREQ=MONTHLY;BYMONTHDAY=1\nRDATE:20250704T090000Z - 1st of each month plus July 4thDTSTART:20250101T090000Z\nRRULE:FREQ=WEEKLY;BYDAY=TU\nRRULE:FREQ=WEEKLY;BYDAY=TH - union of Tuesdays and ThursdaysTo create a one-time schedule that fires once and is done, pass fire_at (an ISO 8601 timestamp) instead of an expression. This replaces the old reminder concept - "remind me at 3pm" becomes a one-shot schedule with fire_at.
One-shot schedules:
fired and disabled.execute and notify modes (see below).Examples:
schedule_create with fire_at: "2025-03-15T15:00:00-05:00", mode: "notify"schedule_create with fire_at, mode: "execute"The mode parameter controls what happens when a schedule fires:
script field as a shell command directly. No LLM invoked, no conversation created. stdout/stderr are captured in the schedule run record. Exit code 0 = success, non-zero = error. Commands run in the workspace directory with a 60-second timeout.Use notify for simple reminders ("remind me to take medicine at 9am"), execute for tasks that need assistant action ("check my calendar at 8am and send me a digest"), and script for lightweight shell automations that don't need LLM involvement ("refresh a cache", "poll an API", "rotate logs").
Recurring schedules reuse the same conversation across runs by default — subsequent runs continue the conversation from the last successful run, preserving context and channel thread continuity. Set reuse_conversation: false explicitly if each run should start with a fresh conversation (e.g. independent reports that shouldn't accumulate prior context). One-shot schedules always create a fresh conversation.
Control how notify-mode schedules are delivered at trigger time with routing_intent:
Optionally pass routing_hints (a JSON object) to influence routing decisions (e.g. preferred channels, exclusions).
Default to all_channels for most notifications. Users usually want to be notified wherever they are.
Use single_channel only when the user explicitly specifies a single channel (e.g. "remind me on Telegram").
Determine the originating channel for routing hints using this priority:
source_channel from <turn_context> — use directly if present. This is the authoritative channel name.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) |
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"
Use syntax + expression to specify the schedule type explicitly, or just expression to auto-detect. For one-shot schedules, use fire_at instead of expression.
schedule_create for both recurring automation ("every day at 9am") and one-time reminders ("remind me at 3pm").fire_at must be a strict ISO 8601 timestamp with timezone offset or Z (e.g. 2025-03-15T09:00:00-05:00).Phrases like "at the 45 minute mark", "at the top of the hour", "at noon", or "20 minutes in" are clock-position or anchored relative time expressions. Do NOT treat them as offsets from now.
Resolution rules (in priority order):
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") as start_time + offset.
Clock-position expressions - when no start time is in context, map directly to a wall-clock time:
Ask only if truly ambiguous - if neither rule resolves, ask for clarification. Never silently default to "from now."
Before confirming a schedule to the user, you MUST verify that you have the capabilities needed to execute the scheduled message autonomously. Scheduled messages run without user interaction - if a required integration is missing, the schedule will fail silently.
When schedule_create returns, it includes an integration status summary. Cross-reference the scheduled task's requirements against the available integrations:
If any required capability is missing:
Scheduled messages run without user interaction. If the task produces output that the user should see (e.g. a digest, summary, or report), the scheduled message must include an explicit instruction to deliver the results. Without this, the output only lives in the conversation log and never reaches the user.
Choose the right delivery tool based on the content:
messaging_send with the target platform and conversation ID. For Slack, use the Slack Web API directly via CLI (chat.postMessage). This preserves the full content and posts directly.assistant notifications send via bash to let the notification router pick the best channel. Note: the router's decision engine rewrites content into short alerts, so it is not suitable for rich content.Example schedule message for a Slack digest:
"Scan my Slack channels for the last 24 hours using the Slack Web API via bash (network_mode: proxied, credential_ids: ['slack_channel/bot_token']), then post the summary to #alex-agent-messages (C0A7STRJ4G5)."