Documentation Index
Fetch the complete documentation index at: https://docs.rkat.ai/llms.txt
Use this file to discover all available pages before exploring further.
Scheduling
Meerkat’s scheduler persists schedules and projects concrete occurrences from them.
What this guide is for
Use this guide when you want to:
-
create durable automated work
-
understand trigger and target shapes
-
choose overlap/misfire policies
-
decide between host APIs and agent-side schedule tools
-
A schedule is the durable rule: trigger + target + policies.
-
An occurrence is one planned delivery produced from that rule.
-
The driver claims due occurrences and delivers them to the target at runtime.
Schedule (trigger + target + policies)
-> projected occurrences
-> driver claims due work
-> runtime delivery
-> completed / skipped / misfired / delivery_failed
Use the typed host APIs when your application is managing schedules directly:
- JSON-RPC:
schedule/create, schedule/list, schedule/get, schedule/update, schedule/pause, schedule/resume, schedule/delete, schedule/occurrences
- REST:
POST /schedules, GET /schedules, GET /schedules/{id}, PATCH /schedules/{id}, POST /schedules/{id}/pause, POST /schedules/{id}/resume, DELETE /schedules/{id}, GET /schedules/{id}/occurrences
Inside an agent session, the scheduler is exposed through typed schedule tools such as meerkat_schedule_create, meerkat_schedule_get, and meerkat_schedule_occurrences.
When skills are enabled and the schedule capability is available, agents can
load the schedule-workflow companion skill for schedule authoring guidance.
Use WorkGraph for shared pending work and dependencies; use Schedule for time.
Create a schedule
{
"jsonrpc": "2.0",
"id": 1,
"method": "schedule/create",
"params": {
"name": "hourly-health-check",
"trigger": {
"type": "interval",
"start_at_utc": "2026-04-21T09:00:00Z",
"every_seconds": 3600
},
"target": {
"target_kind": "session",
"type": "materialize_on_demand_session",
"create": {
"model": "claude-sonnet-4-6",
"system_prompt": "You are a health-check assistant."
},
"action": {
"type": "prompt",
"prompt": "Check system health and report anomalies."
}
},
"misfire_policy": { "type": "skip" },
"overlap_policy": "skip_if_running",
"missing_target_policy": "mark_misfired"
}
}
curl -X POST http://localhost:8080/schedules \
-H "Content-Type: application/json" \
-d '{
"name": "hourly-health-check",
"trigger": {
"type": "interval",
"start_at_utc": "2026-04-21T09:00:00Z",
"every_seconds": 3600
},
"target": {
"target_kind": "session",
"type": "materialize_on_demand_session",
"create": {
"model": "claude-sonnet-4-6",
"system_prompt": "You are a health-check assistant."
},
"action": {
"type": "prompt",
"prompt": "Check system health and report anomalies."
}
},
"misfire_policy": { "type": "skip" },
"overlap_policy": "skip_if_running",
"missing_target_policy": "mark_misfired"
}'
use chrono::Utc;
use meerkat_schedule::{
CreateScheduleRequest, IntervalTriggerSpec, MissingTargetPolicy,
MisfirePolicy, OverlapPolicy, ScheduleService, SessionMaterializationSpec,
SessionTargetBinding, TriggerSpec, TargetBinding, ScheduledSessionAction,
};
use std::collections::BTreeMap;
let schedule = service.create(CreateScheduleRequest {
name: Some("hourly-health-check".into()),
description: None,
trigger: TriggerSpec::Interval(IntervalTriggerSpec {
start_at_utc: Utc::now(),
every_seconds: 3600,
end_at_utc: None,
}),
target: TargetBinding::session(SessionTargetBinding::materialize_on_demand(
SessionMaterializationSpec {
model: "claude-sonnet-4-6".into(),
system_prompt: Some("You are a health-check assistant.".into()),
..Default::default()
},
ScheduledSessionAction::Prompt {
prompt: "Check system health and report anomalies.".into(),
system_prompt: None,
render_metadata: None,
skill_refs: Vec::new(),
additional_instructions: Vec::new(),
},
)),
misfire_policy: MisfirePolicy::Skip,
overlap_policy: OverlapPolicy::SkipIfRunning,
missing_target_policy: MissingTargetPolicy::MarkMisfired,
labels: BTreeMap::new(),
planning_horizon_days: None,
planning_horizon_occurrences: None,
}).await?;
Trigger types
Once
Fire one time at an exact UTC timestamp.
{
"type": "once",
"due_at_utc": "2026-04-21T15:00:00Z"
}
Interval
Fire repeatedly at a fixed cadence.
{
"type": "interval",
"start_at_utc": "2026-04-21T09:00:00Z",
"every_seconds": 3600
}
Add end_at_utc to stop the schedule automatically:
{
"type": "interval",
"start_at_utc": "2026-04-21T09:00:00Z",
"every_seconds": 3600,
"end_at_utc": "2026-04-22T09:00:00Z"
}
Calendar
Fire at named wall-clock times in a timezone. Omitted fields default to {"kind":"any"}.
{
"type": "calendar",
"timezone": "Europe/Stockholm",
"minute": { "kind": "values", "values": [0] },
"hour": { "kind": "values", "values": [9] },
"day_of_week": { "kind": "values", "values": [1, 2, 3, 4, 5] }
}
That means “09:00 every weekday in Stockholm”.
Target types
Session targets
target_kind must be "session" with one of these type variants:
exact_session: deliver to one specific existing session
resumable_session: deliver to a specific session that may be idle/suspended
materialize_on_demand_session: create a session on first fire, then reuse it
Example exact-session prompt delivery:
{
"target_kind": "session",
"type": "exact_session",
"session_id": "01936f8a-7b2c-7000-8000-000000000001",
"action": {
"type": "prompt",
"prompt": "Run the daily follow-up."
}
}
Example event delivery:
{
"target_kind": "session",
"type": "resumable_session",
"session_id": "01936f8a-7b2c-7000-8000-000000000001",
"action": {
"type": "event",
"event_type": "deploy_complete",
"payload": { "environment": "prod" }
}
}
Mob targets
target_kind must be "mob" with one of these type variants:
member: deliver content to a specific mob member
flow: run a named mob flow
spawn_helper: create a helper in a mob and wait for it
fork_helper: fork from an existing member and wait for it
Example flow target:
{
"target_kind": "mob",
"type": "flow",
"mob_id": "release-triage",
"flow_id": "triage",
"params": { "severity": "high" }
}
Policies
Misfire policy
What happens when an occurrence is materially late:
{"type":"skip"}: skip overdue work after the grace window
{"type":"catch_up_within","window_seconds":300}: catch up if still within the lateness window
Overlap policy
What happens when the next occurrence fires while previous work is still active:
skip_if_running (recommended)
allow_concurrent
Missing target policy
What happens when the target is missing at fire time:
mark_misfired (recommended)
skip
Recommended defaults
For most recurring jobs, start with:
{
"misfire_policy": { "type": "skip" },
"overlap_policy": "skip_if_running",
"missing_target_policy": "mark_misfired"
}
Schedule lifecycle
Schedule phase is intentionally small:
Occurrence phase is more detailed:
pending
claimed
dispatching
awaiting_completion
completed
skipped
misfired
superseded
delivery_failed
Use schedule/occurrences or GET /schedules/{id}/occurrences to inspect what actually fired and why.
When scheduling is exposed inside a running agent, the canonical tool names are:
meerkat_schedule_create
meerkat_schedule_get
meerkat_schedule_list
meerkat_schedule_update
meerkat_schedule_pause
meerkat_schedule_resume
meerkat_schedule_delete
meerkat_schedule_occurrences
These are distinct from the host APIs (schedule/* over RPC and /schedules/* over REST).
See also