Trigger when the user wants to hand a task to background async execution, run it on a cron/recurring schedule, delegate it to a project Agent for a long run, or inspect/approve/cancel tasks on the board. Typical phrasings: "every day at 9am help me X", "let the coder agent run this", "what's pending approval". **Not for**: one-shot immediate answers (→ just use tools directly), real calendar meetings/appointments (→ calendar-ops-skill), one-off plan approvals (→ `SubmitPlan`).
73
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
| Tool | Responsibility | Read-only |
|---|---|---|
ScheduledTaskManage | Task creation and management (action: create / cancel / delete / resolve / archive, etc.) | No |
ScheduledTaskStatus | Query task snapshots (status / executionSummary / lastError) | Yes |
ScheduledTaskWait | Block until a given task reaches a terminal state or times out (mandatory partner for immediate tasks) | Yes |
Loading: All are deferred tools. Before calling, activate their schemas via
ToolSearch(names: "ScheduledTaskManage,ScheduledTaskStatus,ScheduledTaskWait").
ScheduledTaskStatusScheduledTaskManage (create / cancel / delete / archive, etc.)ScheduledTaskManage with the resolve action (approve / reject / rework)ScheduledTaskManage(create, skipPlanConfirm:true) immediately followed by ScheduledTaskWaitScheduledTaskStatus to get the list, then ScheduledTaskManage one by oneThis is the single most important decision point in this skill. Task completion does not surface itself in the conversation automatically — the Agent receives no async notifications. The only way to learn a task's result is to actively call a tool to fetch it (semantically similar to Claude Code's Sleep tool).
When the user describes something to do right now ("run this script", "check system status", "generate a report", "help me X now"):
ScheduledTaskManage(action:'create', skipPlanConfirm:true, ...) to kick it offScheduledTaskWait({taskId, timeoutSec:60}) to block until completionScheduledTaskWait tool_result, then end_turnFields returned by ScheduledTaskWait:
status: done — task succeeded, read summary (executionSummary)status: cancelled — task was cancelled or exceeded the failure threshold, read error (lastError)status: timeout — 60s elapsed without completion, read currentStatus (usually still running)When the user describes something for the future or recurring ("every day at 8am", "in 5 minutes", "every Monday", "tomorrow morning"):
ScheduledTaskManage(action:'create', schedule:{...}) to create the scheduled taskNever call ScheduledTaskWait on a scheduled task — scheduled tasks only fire at some future time. Calling ScheduledTaskWait just stalls the current turn until timeout (up to 300s), wasting model tokens and making the user wait for nothing.
When ScheduledTaskWait returns after a 60s timeout, the task is still running in the background. Your options:
ScheduledTaskWait({taskId, timeoutSec:120}) once more to keep waitingWrong approach (wastes tokens, inefficient, duplicates what ScheduledTaskWait already does):
Bash(sleep 5)
ScheduledTaskStatus(taskId) → still running
Bash(sleep 5)
ScheduledTaskStatus(taskId) → still running
...Correct approach:
ScheduledTaskWait({taskId, timeoutSec: 60}) → one call, event-driven, zero wasted round-tripsScheduledTaskWait subscribes to task completion events internally and returns the instant the task reaches a terminal state. There's no need to simulate the same thing with Bash sleep + polling.
When the user says "what do I have to deal with", "what's on my plate", or "what's happening today", they could mean tasks, calendar events, or unread email. Prefer ScheduledTaskStatus to check tasks, but tell the user explicitly that you only looked at the tasks dimension. If context hints at calendar or email (e.g. "any meetings today"), suggest the corresponding skill instead of guessing.
Tasks default to a "plan → approve → execute" two-phase flow. The reason is simple: some operations cannot be undone once executed — files get modified, emails get sent, data gets deleted. Two-phase lets the user see the Agent's execution plan before any irreversible action, and decide whether to proceed.
The flow: after the Agent receives a task, it first generates an execution plan, and the task enters the review state awaiting user review. Once the user sees the plan, they can approve, reject, or request changes (rework, with modification notes). Only after approval does the Agent actually execute. The result then enters review again for user confirmation, and finally gets marked done.
Full state transition: todo → running(plan) → review(plan) → approve → running(execute) → review(result) → done
Setting skipPlanConfirm: true makes the task execute directly, simplifying the flow to: todo → running → done.
Use this for read-only, side-effect-free operations — checking server status, fetching weather, summarizing information, generating a report digest. Even if such a task goes wrong, nothing is lost, and the extra approval step just slows things down.
Rule of thumb: if the result turns out bad, can the user simply ignore it? If yes, use skipPlanConfirm: true. If no, keep the default two-phase flow.
Concrete examples:
Note: scheduled tasks (with schedule) default to skipPlanConfirm: true, because the user usually isn't online to approve when the timer fires. If a scheduled task involves irreversible operations, explicitly set skipPlanConfirm: false.
When creating a task, first decide whether it needs scheduling. Tasks without schedule run immediately and never enter the scheduling system.
User needs it once? → once
Provide scheduleAt (ISO 8601 timestamp, must be in the future). Fits "send the weekly report at 5pm Friday" or "remind me about the meeting tomorrow morning".
User needs it repeated at a fixed interval? → interval
Provide intervalMs (milliseconds), minimum 60000 (1 minute). Fits "check the server every 30 minutes" (intervalMs: 1800000) or "sync data every 2 hours" (intervalMs: 7200000).
User needs a complex time rule? → cron
Provide cronExpr (5-field format: minute hour day month weekday) plus timezone. Fits "check email at 9am on weekdays" (cronExpr: "0 9 * * 1-5") or "generate a report on the 1st of every month" (cronExpr: "0 10 1 * *").
Common cron examples: 0 9 * * * (every day at 9am) · 0 9 * * 1-5 (weekdays at 9am) · 0 * * * * (every hour on the hour) · 0 10 1 * * (1st of every month at 10am) · 0 8 * * 1 (every Monday at 8am)
When a task is in the review state, use the resolve action:
reason explaining what to change, and the Agent will replan accordinglyScheduledTaskManage { action: "resolve", taskId: "xxx", resolveAction: "rework", reason: "please add error handling" }date via Bash to confirm the current time and timezoneScheduledTaskManage with the create action and the schedule configWriting title and description: title is a short summary (5-15 chars, distill the user's intent rather than quoting them verbatim); description is the Agent's execution handbook and must clearly spell out the goal (what to do), the deliverable (output format, e.g. "save report.md to the project root"), and the completion criteria (objectively verifiable conditions, not vague phrases like "good quality"). For tasks with skipPlanConfirm: false, the description must be thorough (add constraints and hard red lines); for tasks with skipPlanConfirm: true, the description can be concise, but goal and deliverable cannot be omitted.
ScheduledTaskStatus {} to fetch all active tasksreviewScheduledTaskStatus {} first to display all current tasks and confirm the blast radiusinterval too small — intervalMs below 60000 is rejected. Why: 1 minute is the hard floor; 5-30 minutes is enough for most monitoring scenarios, and shorter intervals exhaust system resources.
cron without timezone — Without timezone, cron runs in UTC, so "9am" turns into 1am for the user. Why: the server defaults to UTC, which differs from the user's local time. Always ask or infer the user's timezone from context and pass it explicitly.
deleteAll without checking first — deleteAll only deletes terminated tasks (done / cancelled) and never touches active ones. Still, call ScheduledTaskStatus first and let the user confirm the list. Why: the user may have forgotten that a completed task contains important execution logs.
Creating a task when you shouldn't — If the user says "check the weather" or "what time is it", just do it — don't create a task. Why: the task system has scheduling and state-management overhead; only bother when you actually need scheduling, recurrence, deferred execution, or an approval flow.
scheduleAt in the past — scheduleAt for once tasks must be in the future. Why: past times cannot be scheduled and will be rejected. Verify the current time with Bash date before creating.
delete on an active task — Only tasks in done or cancelled state can be deleted. Why: running tasks must be cancelled first to stop the Agent, then deleted to clean up the record.
Forgetting ScheduledTaskWait after creating an immediate task — When the user says "run a script right now", calling only ScheduledTaskManage(create) and replying "started" leaves the user waiting in a black box — task completion will not surface unless they ask again. Correct: follow create immediately with ScheduledTaskWait and deliver the result in one shot.
Calling ScheduledTaskWait on a scheduled task — A scheduled task only runs at a future time, so ScheduledTaskWait will stall the current turn until timeout. Correct: for scheduled tasks, reply "scheduled" right after create and end_turn.
Bash sleep + ScheduledTaskStatus polling — This was a stopgap before ScheduledTaskWait existed and is now obsolete. ScheduledTaskWait is event-driven with zero wasted round-trips — just use it.
a1ab5be
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.