Skip to main content

Scheduling

Meerkat’s scheduler persists schedules and projects concrete occurrences from them.
  • 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

Host APIs vs agent tools

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.

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"
  }
}

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
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:
  • active
  • paused
  • deleted
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.

Agent-side schedule tools

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