Overview
Add a new built-in toolset, scheduler, that lets an agent schedule an instruction to run once at a specific time, after a delay, or on a recurring interval (every N minutes/hours, or the presets minutely / hourly / daily / weekly). When a schedule is due, the toolset injects the instruction back into the agent loop via the runtime's Recall mechanism, and the agent carries out the action using whatever tools it already has (shell, api, fetch, …).
Tools:
create_schedule(prompt, when, name?) — register a schedule; returns its id and next fire time.
list_schedules() — list active schedules (id, name, spec, next fire, recurring?).
cancel_schedule(id) — remove a schedule.
when accepts: in:<duration> (e.g. in:10m), at:<RFC3339> (e.g. at:2026-07-14T09:00:00Z), every:<duration> (e.g. every:1h), or a preset (minutely, hourly, daily, weekly).
Motivation
Agents can start long-running work (background_jobs) and be recalled when it finishes, but there is no way to make something happen at a chosen time or on a repeating cadence — e.g. "every hour, check the build status and tell me if it broke," or "at 09:00 tomorrow, summarize the overnight logs." Today a user has to leave the agent idle and prompt it manually each time. A scheduler turns docker-agent into something that can drive recurring/timed workflows on its own while a session (interactive TUI, serve) is running.
Use cases
- Recurring monitoring:
create_schedule(prompt="Run \git fetch` and tell me if main moved", when="every:15m")`.
- Timed one-shot:
create_schedule(prompt="Post the daily standup summary", when="at:2026-07-14T09:00:00Z").
- Delay:
create_schedule(prompt="Re-check the flaky test", when="in:5m").
- Housekeeping:
every:hourly cleanup / health-check loops the agent runs unattended during a long session.
Proposed solution
New toolset type scheduler (in pkg/tools/builtin/scheduler/), registered in pkg/teamloader/toolsets/toolsets.go and documented in the built-in toolset catalog (pkg/teamloader/toolsets/catalog.go) — the existing catalog drift-guard test forces the catalog entry to exist, so the new type can't ship undocumented.
Execution model (deliberate choice): the scheduler does not execute shell/api itself. When a schedule fires it calls Runtime.Recall(ctx, "<instruction>"), and the agent performs the action with its normal tools. This:
- works with any tool the agent has, not just shell;
- reuses
Recall exactly as designed ("background work completed → inject a message");
- keeps the shell/permission/sandbox surface with the
shell tool, instead of adding a second, unattended command-runner.
A deterministic-execution variant (the scheduler runs a shell command itself, like background_jobs) is a possible follow-up but is intentionally out of scope for v1 to keep the security surface small.
Lifecycle: the toolset implements tools.Startable; Stop cancels all pending timers so no goroutine outlives the session. Schedules live in memory for the process lifetime (not persisted across restarts in v1). Scheduling requires host recall support (Runtime.Supports(CapabilityRecall)); if unavailable, create_schedule returns a clear error.
Alternatives
background_jobs runs a command now and recalls on completion — it cannot schedule for later or repeat.
- External
cron + docker agent run --exec works for one-shot batch invocations but can't schedule from within a live agent session or react in-conversation.
- Prompting the agent manually each time (the status quo).
Related issues
No response
Additional context
No response
Overview
Add a new built-in toolset,
scheduler, that lets an agent schedule an instruction to run once at a specific time, after a delay, or on a recurring interval (every N minutes/hours, or the presetsminutely/hourly/daily/weekly). When a schedule is due, the toolset injects the instruction back into the agent loop via the runtime'sRecallmechanism, and the agent carries out the action using whatever tools it already has (shell,api,fetch, …).Tools:
create_schedule(prompt, when, name?)— register a schedule; returns its id and next fire time.list_schedules()— list active schedules (id, name, spec, next fire, recurring?).cancel_schedule(id)— remove a schedule.whenaccepts:in:<duration>(e.g.in:10m),at:<RFC3339>(e.g.at:2026-07-14T09:00:00Z),every:<duration>(e.g.every:1h), or a preset (minutely,hourly,daily,weekly).Motivation
Agents can start long-running work (
background_jobs) and be recalled when it finishes, but there is no way to make something happen at a chosen time or on a repeating cadence — e.g. "every hour, check the build status and tell me if it broke," or "at 09:00 tomorrow, summarize the overnight logs." Today a user has to leave the agent idle and prompt it manually each time. A scheduler turns docker-agent into something that can drive recurring/timed workflows on its own while a session (interactive TUI,serve) is running.Use cases
create_schedule(prompt="Run \git fetch` and tell me if main moved", when="every:15m")`.create_schedule(prompt="Post the daily standup summary", when="at:2026-07-14T09:00:00Z").create_schedule(prompt="Re-check the flaky test", when="in:5m").every:hourlycleanup / health-check loops the agent runs unattended during a long session.Proposed solution
New toolset type
scheduler(inpkg/tools/builtin/scheduler/), registered inpkg/teamloader/toolsets/toolsets.goand documented in the built-in toolset catalog (pkg/teamloader/toolsets/catalog.go) — the existing catalog drift-guard test forces the catalog entry to exist, so the new type can't ship undocumented.Execution model (deliberate choice): the scheduler does not execute shell/api itself. When a schedule fires it calls
Runtime.Recall(ctx, "<instruction>"), and the agent performs the action with its normal tools. This:Recallexactly as designed ("background work completed → inject a message");shelltool, instead of adding a second, unattended command-runner.A deterministic-execution variant (the scheduler runs a shell command itself, like
background_jobs) is a possible follow-up but is intentionally out of scope for v1 to keep the security surface small.Lifecycle: the toolset implements
tools.Startable;Stopcancels all pending timers so no goroutine outlives the session. Schedules live in memory for the process lifetime (not persisted across restarts in v1). Scheduling requires host recall support (Runtime.Supports(CapabilityRecall)); if unavailable,create_schedulereturns a clear error.Alternatives
background_jobsruns a command now and recalls on completion — it cannot schedule for later or repeat.cron+docker agent run --execworks for one-shot batch invocations but can't schedule from within a live agent session or react in-conversation.Related issues
No response
Additional context
No response