scheduling-tasks
GitHub通过 letta cron CLI 创建、列出和管理定时任务,支持提醒、周期性检查和延迟跟进。适用于跨会话调度、指定计算机执行及历史管理,弥补 Wake 工具在当前会话调度的不足。
Trigger Scenarios
Install
npx skills add letta-ai/letta-code --skill scheduling-tasks -g -y
SKILL.md
Frontmatter
{
"name": "scheduling-tasks",
"description": "Advanced scheduling through the letta cron CLI for other conversations, computers, run history, and schedule replacement. Use Wake for ordinary create\/list\/cancel operations in the current conversation."
}
Scheduling Tasks
This skill lets you create, list, and manage scheduled tasks using the letta cron CLI. Scheduled tasks send a prompt to the agent on a timer — useful for reminders, periodic check-ins, and deferred follow-ups.
For ordinary one-shot or recurring work in the current conversation, use Wake instead. Wake is self-bound and covers create, list, and cancel without routing choices.
When to Use This Skill
- The task should run in a fresh, default, or different conversation
- The task needs a specific connected computer
- You need run history, replacement, or broader schedule inspection
- Wake cannot see or manage the schedule you need
Where Schedules Run
Execution determines schedule ownership; there is no runner selection flag:
- In a managed Cloud sandbox, schedules are durable Cloud schedules and run in the agent's Cloud sandbox.
- On a user-managed computer or self-hosted runtime, schedules are local and fire only while a Letta session is running there.
From a managed Cloud sandbox, --computer <deviceId> can run the scheduled work on a specific connected computer. Get the device ID from letta computers list. If that computer is offline at fire time, execution falls back to the Cloud sandbox. Local execution cannot target another computer.
Creation and execution follow those rules, while management commands still show and cancel both local and Cloud inventory. This keeps schedules created by older CLI versions visible without changing where new schedules run.
CLI Usage
All commands go through letta cron via the Bash tool. Output is JSON.
Creating a Task
letta cron add --name <short-name> --description <text> --prompt <text> <schedule>
Required flags:
| Flag | Description |
|---|---|
--name <text> |
Short identifier for the task (e.g. "dog-walk-reminder") |
--description <text> |
Human-readable description of what the task does |
--prompt <text> |
The message that will be sent to the agent when the task fires |
Schedule (pick one):
| Flag | Type | Example |
|---|---|---|
--every <interval> |
Recurring (cron shorthand) | 5m, 2h, 1d |
--at <time> |
One-shot | "in 45m", "2026-09-24T09:00:00-07:00" |
--cron <expr> |
Raw cron (recurring) | "0 9 * * 1-5" |
Optional flags:
| Flag | Description |
|---|---|
--agent <id> |
Agent ID (defaults to LETTA_AGENT_ID from the current shell/session) |
--conversation <id> |
Conversation target: omit or pass new for a fresh conversation per fire; pass self for the current conversation; pass default for the agent default; or pass a concrete ID |
--computer <id> |
From managed Cloud, execute on a specific connected computer |
--once |
Mark --at as one-shot (already the default for --at) |
Listing Tasks
letta cron list
Optional filters: --agent <id>, --conversation <id>
Getting a Single Task
get accepts an ID or name:
letta cron get <id-or-name> [--agent <id>]
Reading Run History
letta cron runs --id <task-id> [--limit <n>] [--agent <id>]
For local run history, --run-id <id> selects one run. Cloud history ignores that flag.
Binding a Task to the Right Conversation
If exact routing matters, pass both --agent and --conversation explicitly.
letta cron add falls back to LETTA_AGENT_ID for the agent. An omitted --conversation means "new", so every fire gets a fresh conversation. Pass --conversation self to capture the current LETTA_CONVERSATION_ID, --conversation default for the agent default, or a concrete conversation ID.
Safest pattern:
letta cron add \
--name "email-check" \
--description "Daily email summary in this conversation" \
--prompt "Check the user's email and post a summary here." \
--cron "0 10 * * *" \
--agent "$LETTA_AGENT_ID" \
--conversation self
Then verify the binding explicitly:
letta cron list --agent "$LETTA_AGENT_ID" --conversation self
Deleting or Replacing Tasks
delete accepts an ID or name; remove is an alias.
# Delete a specific task
letta cron delete <id-or-name> [--agent <id>]
# Delete all tasks for one agent
letta cron delete --all --agent "$AGENT_ID"
In-place editing is not available. To change a schedule, create and verify the replacement before deleting the old one.
Timezones
Cloud-schedule recurring expressions (both --cron and the expression --every compiles to) are interpreted in UTC. Users say times in their local timezone, so convert before writing the expression: a user in PDT asking for "9am daily" needs --cron "0 16 * * *" (9am PDT = 16:00 UTC; 17:00 during PST). State the conversion in your reply so the user can catch a wrong assumption. Local-runner recurring tasks use the computer's local timezone.
For a one-shot calendar request such as "tomorrow at 9am," resolve the date in the user's timezone and pass --at an RFC 3339 timestamp with an explicit offset. Infer a reasonable timezone from available context instead of asking a redundant follow-up. State the timezone you used in the confirmation (for example, "Scheduled for 9:00 AM PT") so the user can correct the assumption. A bare clock such as --at "9:00am" uses the current process timezone, which may be UTC in Cloud; use it only when that is the intended timezone. Relative values such as --at "in 45m" do not need a timezone.
Examples
"Remind me every morning at 9am to walk the dog" (user in UTC−7)
letta cron add \
--name "dog-walk-reminder" \
--description "Daily 9am (America/Los_Angeles) reminder to walk the dog" \
--prompt "Hey! It's 9am — time to walk the dog." \
--cron "0 16 * * *"
Note: --every 1d fires daily at midnight (UTC on a Cloud schedule), so use --cron for a specific time of day, converting the user's local time to UTC first.
"Check on the deploy in 30 minutes"
letta cron add \
--name "deploy-check" \
--description "One-time check on deployment status" \
--prompt "Check the deployment status and report the result here." \
--at "in 30m" \
--agent "$LETTA_AGENT_ID" \
--conversation self
"Every weekday at 5pm, remind me to submit my timesheet" (user in UTC−7)
letta cron add \
--name "timesheet-reminder" \
--description "Weekday 5pm (America/Los_Angeles) timesheet reminder" \
--prompt "Friendly reminder: don't forget to submit your timesheet before EOD!" \
--cron "0 0 * * 2-6"
Note the day shift: 5pm UTC−7 is midnight UTC the next day, so weekdays Mon–Fri become 2-6. Always re-derive both the hour and the day fields after converting.
"What reminders do I have?"
letta cron list
If you need to confirm the exact conversation a task is bound to, list with explicit filters instead:
letta cron list --agent "$AGENT_ID" --conversation "$CONVERSATION_ID"
"Cancel the dog walk reminder"
letta cron delete dog-walk-reminder
Writing Good Prompts
The --prompt value is what gets sent to you (the agent) when the task fires. Write it as a message that will make sense when you receive it later, with enough context to act on:
- Good: "The user asked to be reminded to review the PR for the auth refactor. Check if it's still open and nudge them."
- Bad: "reminder"
Include context about what the user originally asked for, so you can give a helpful response when the prompt arrives.
Important Notes
- Minimum granularity: 1 minute. Intervals under 60 seconds are rounded up.
- Recurring tasks: No longer auto-expire. They remain active until explicitly cancelled.
- One-shot cleanup (local runner): One-shot local tasks are garbage-collected 24 hours after firing.
- Default binding:
letta cron adduses--agentfirst, thenLETTA_AGENT_ID. Omit--conversationfor a fresh conversation per fire; use--conversation selfto captureLETTA_CONVERSATION_IDexplicitly. - Local scheduler requirement: Local schedules only fire while a Letta session is running on their computer; fires while no session runs are marked as missed. Cloud schedules fire from the cloud regardless.
--atfor specific times: prefer RFC 3339 with an explicit offset. A bare--at "3:00pm"uses the process timezone and schedules tomorrow if that time has already passed there.- Cloud schedule creation failures are loud: if creating a Cloud schedule fails in a managed Cloud sandbox, no schedule is created; it never falls back to a local schedule.
Cron Expression Reference
For --cron, use numeric 5-field cron syntax (named days/months, seconds, ?, L, and # are not supported):
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sun=0)
│ │ │ │ │
* * * * *
Common patterns (UTC on Cloud schedules):
*/5 * * * *— every 5 minutes0 */2 * * *— every 2 hours0 9 * * *— daily at 9:00 UTC0 9 * * 1-5— weekdays at 9:00 UTC30 8 1 * *— 8:30 UTC on the 1st of each month
Version History
-
1cab1b7
Current 2026-09-27 17:45
修复托管云环境下的计划任务持久化问题;新增 Wake 工具用于当前会话的定时跟进,优化了调度器的使用场景划分。
-
fae8499
2026-09-09 01:12
修正获取设备ID的命令为 'letta environments list';更新 Git 提交日志以反映远程路由标准化变更。
- ee230f3 2026-08-19 17:32
-
bec353d
2026-08-05 14:25
修复了当云端无法连接本机时回退到本地调度的问题,并默认保留活跃监听器的执行状态。
-
23446a1
2026-07-23 06:14
引入 cloud/local 双运行器机制,默认启用云端持久化调度;将 --target-device 参数重命名为 --computer 以统一文档术语;增强任务在设备离线时的可靠性和跨设备执行能力。
- b7b6330 2026-07-05 20:11


