Heartbeat
All MCP tools that schedule and manage heartbeats.
Tools for scheduling and managing heartbeats. The full external contract lives at sprout://heartbeat/authoring-guide.
Heartbeats are server-capped at 4 fires per 24h in the heartbeat's timezone. assignmentSkillId is now optional (pass it when you want the scheduler itself to be an auditable skill).
heartbeat.createSafe to retry
Schedule a run skill to fire on cron.
Scope: heartbeat:write
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
name | string | yes | Human-readable label, ≤ 100 chars. |
cron | string | yes | 5-field cron in the heartbeat's timezone. |
tz | string | no | IANA timezone. Defaults to America/New_York. |
runSkillId | string | yes | The run-shaped skill the heartbeat runs each fire. Must not declare heartbeat.create in handsReferenced. |
assignmentSkillId | string | no | The assignment-shaped skill (declares heartbeat.create). Must be distinct from runSkillId if passed. |
childId | string | no | Scope to one kid. Omit for family-wide. |
sourceChatId | string | no | Chat to inherit participants from. Defaults to the caller's family chat. |
skillInput | object | no | Structured values for the skill's {{input.*}} placeholders. Same map on every fire. |
postResultNotify | boolean | no | Whether the structured result posts to the family inbox. |
Request example
{
"method": "tools/call",
"params": {
"name": "heartbeat.create",
"arguments": {
"name": "Morning check-in refresh",
"cron": "0 8 * * 1-5",
"tz": "America/New_York",
"runSkillId": "sk_2f...",
"skillInput": {
"child_name": "Jay",
"child_id": "a4b9-...",
"today": "{{fireDate}}"
},
"postResultNotify": true
}
}
}Returns. { heartbeatId, chatId, nextFireAt }
Response example
{
"result": {
"heartbeatId": "hb_71...",
"chatId": "th_4a...",
"nextFireAt": "2026-05-24T08:00:00-04:00"
}
}Errors
BAD_INPUT: Cadence > 4 fires per 24h. Error names the computed fires/day.BAD_INPUT SCHEDULER_AS_RUN_SKILL:runSkillIddeclaresheartbeat.create, or same id passed for both.BAD_INPUT SKILL_NOT_ASSIGNMENT:assignmentSkillIddoesn't declareheartbeat.create.
heartbeat.update
Modify a heartbeat. Discrete action-based, not a partial patch.
Scope: heartbeat:write
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
heartbeatId | string | yes | The heartbeat to modify. |
action | enum | yes | edit_schedule | edit_text | edit_name | pause | resume | cancel | add_member | remove_member | promote_admin. |
cron / tz | various | no | Required when action: edit_schedule. Re-validated against 4-fires/24h cap. |
promptText | string | no | Required when action: edit_text. Free-form heartbeats only; skill-backed reject. |
name | string | no | Required when action: edit_name. |
targetUserId | string | no | Required for member actions. |
Request example
{
"method": "tools/call",
"params": {
"name": "heartbeat.update",
"arguments": {
"heartbeatId": "hb_71...",
"action": "edit_schedule",
"cron": "0 7 * * 1-5"
}
}
}Returns. { heartbeatId, status }
Response example
{
"result": { "heartbeatId": "hb_71...", "status": "updated" }
}Notes. Permission rules: admins edit, members only leave, only owners cancel.
heartbeat.describe
Dry-run preview. Returns the human-readable cadence and first-fire timestamp.
Scope: heartbeat:read
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
mode | "create" | "update" | yes | Which preview shape. |
payload (create) / patch (update) | object | yes | Same shape as the matching write tool. |
heartbeatId | string | no | Required for update. |
Request example
{
"method": "tools/call",
"params": {
"name": "heartbeat.describe",
"arguments": {
"mode": "create",
"payload": {
"name": "Morning check-in refresh",
"cron": "0 8 * * 1-5",
"tz": "America/New_York",
"runSkillId": "sk_2f..."
}
}
}
}Returns. { cadenceText, nextFireAt, preview, warnings: ["schedule_conflict" | "age_edge" | "age_mismatch" | "program_not_assignable" | "already_assigned"] }
Response example
{
"result": {
"cadenceText": "Every weekday at 8am ET",
"nextFireAt": "2026-05-24T08:00:00-04:00",
"preview": { "kind": "skill", "skillId": "sk_2f...", "name": "Refresh today's check-in" },
"warnings": []
}
}Notes. Read warnings back to the parent before committing.
heartbeat.list
Cursor-paginated list of heartbeats.
Scope: heartbeat:read
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
cursor / limit | various | no | Standard pagination. |
Request example
{
"method": "tools/call",
"params": {
"name": "heartbeat.list",
"arguments": { "limit": 50 }
}
}Returns. { items: [{ heartbeatId, name, cron, cadenceText, enabled, nextRunAt, lastRunAt, chatId }], nextCursor }
Response example
{
"result": {
"items": [
{
"heartbeatId": "hb_71...",
"name": "Morning check-in refresh",
"cron": "0 8 * * 1-5",
"cadenceText": "Every weekday at 8am ET",
"enabled": true,
"nextRunAt": "2026-05-24T08:00:00-04:00",
"lastRunAt": "2026-05-23T08:00:00-04:00",
"chatId": "th_4a..."
}
],
"nextCursor": null
}
}See also
- Model: Heartbeat
- Build: Schedule a heartbeat
- Authoring guide resource:
resources/read sprout://heartbeat/authoring-guide