Three Scheduling Systems
Comis includes three complementary scheduling systems, each designed for a different kind of automated work.Cron Jobs
Cron jobs are recurring tasks that run on a schedule, like “check email every morning” or “send a daily summary at 5pm.” Your agents create and manage cron jobs using the scheduling tools — you configure the limits, and they handle the details.Heartbeat Monitoring
The heartbeat system runs periodic health checks at regular intervals (every 5 minutes by default). This is how the monitoring sources — disk space, CPU, memory, systemd services, and security updates — get checked.
The heartbeat uses wake coalescing — all monitoring checks are batched together into a single heartbeat cycle rather than each running independently. This prevents multiple checks from overwhelming the system simultaneously.
Task Extraction
During a conversation, your agent might notice follow-up work — “I should check back on this tomorrow” or “remind the user about that deadline.” Task extraction lets agents automatically schedule these follow-ups.Task extraction requires explicit opt-in with
scheduler.tasks.enabled: true. Extracted work remains subject to the confidence, batch, retry, and per-conversation delivery limits above.Quiet Hours
Quiet hours control scheduled delivery and task-lane admission during specified times — for example, overnight when you do not want notifications. They do not stop the cron engine or agent heartbeat execution.
When quiet hours are active, cron and agent-heartbeat runs still execute. At the closed delivery boundary, routine and non-critical delivery is suppressed; critical heartbeat output may bypass that boundary when
criticalBypass is true. Task-lane checks defer before the model runs until the configured quiet window ends, avoiding an unnecessary model call during the window.
Wake-Gate Efficiency
A polling cron job — “check the build queue every five minutes,” “scan the inbox every ten” — usually finds nothing changed, and waking the model on every empty fire is pure waste. A wake-gate lets a job answer “nothing to do” before the model runs: a small sandboxed script inspects the world and returns a verdict, and only a verdict that says “wake” spends a model turn. A gate can also deliver a routine ✓ status straight to the channel with no model turn at all — and that routine status honors quiet hours, so an all-clear ping never lands overnight. The gate is an efficiency layer, not a suppression control, and its posture is designed to stay legible to an operator:- Fail-open. A gate that errors, times out, over-caps its output, or returns no verdict wakes the model. A broken gate can never silently drop a monitored job — the worst a misbehaving gate does is wake the model too often (spending turns), never too rarely (missing an alert).
- Skip-rate. The share of a job’s fires the gate skipped. A high skip-rate is usually the gate working — most polls found nothing — not a fault. A gate at a 100% skip-rate on a monitor you expect to fire is the signal to inspect: it may be genuinely quiet, or its logic may have broken toward always-skip.
- Net cost. A gate’s own tool calls (its
web_fetch/read/grepcost) sit beside the model turns it saved. A gate whose tool-call cost exceeds the turns it avoids is not paying for itself — compare the two numbers directly.
comis system-health health report (skip-rate, turns-saved, tool-call cost — counts only, never the gate’s gathered findings), and each per-fire decision is visible in the job’s run history via cron.runs. Because the gate runs under the agent’s own autonomy capabilities in the standard jail, it grants no new reach — see the capability model for the suppression bound.
Scheduler-initiated gates are governed deployment-wide by the scheduler.cron.wakeGate toggle. It defaults to each agent’s autonomy script surface — where an agent may run orchestrate scripts, its cron jobs may run wake-gates. Set it to false to disable scheduler-initiated pre-run gates while still allowing model-initiated orchestrate: a scheduler gate is a distinct trust context (no human or model in the loop at fire time), and with the toggle off a gated job simply runs as it would with no gate. The toggle grants no capability — it only decides whether the pre-run script runs.
Safety
Each scheduled occurrence crosses durable safety boundaries before and after runtime execution:- A durable claim prevents a second owner from dispatching the same occurrence and gives startup reconciliation an authoritative recovery record.
- A start/terminal execution ledger records the start before runtime dispatch and appends exactly one terminal outcome afterward.
maxRunsPerTicklimits, per scheduler tick, how many due occurrences are admitted (default:3); admitted occurrences execute sequentially.maxConsecutiveDependencyErrorscounts only dependency-classified failures from recurring scheduled fires and suspends the job at the configured threshold. Internal failures and manual runs do not advance this breaker.maxJobsis a positive cap on agent-authored jobs (default:100).
Execution Ledger
The execution ledger stores complete start/terminal groups. Capacity is bounded by bytes and by the number of complete groups retained; the configured byte limit must also reserve enough room for the per-tick admission limit.Full Configuration Reference
Related Pages
Monitoring
The 5 health sources checked by heartbeat
Daemon
The process that runs the scheduler
Agent Lifecycle
How agents process messages and use tools
Scheduler View
View and manage scheduled tasks in the dashboard
