Compact delivery
REST, private CLI, and private MCP heartbeat reads are compact by default. Compact output contains direct attention, grouped actionable signals, a recommendation, counts, delta metadata, and page metadata. It omits the full goals, KPIs, initiatives, assigned issues, and project-context collections. Each page is limited to 16,384 UTF-8 bytes and 25 signal groups. The server measures the serialized JSON response, so keep reading whilepage.has_more is true:
page.ack_cursor. Process every page before
acknowledging the terminal cursor:
since=<ack-cursor> on the next read. Cursors are opaque, server-issued, and
single-use in sequence. Follow the exact next_cursor from the immediately
previous page; do not manufacture, skip, or replay a page cursor. Compact delta output returns new,
changed, or escalated groups and suppresses unchanged groups. Expected waits are suppressed for an
unsatisfied dependency when the readable blocker is before its release column
and there is no active stall, threatened or overdue commitment, or explicit
deadline, gate, permission, or stale anomaly. An unowned backlog or Todo
blocker by itself is an ordinary wait and never alerts. Actionable dependency
blockers surface active stalls, threatened or overdue commitments, and explicit
anomalies; escalation metadata alone does not surface an expected wait. When
every dependency fact behind an initiative-target or stalled aggregate is an
expected wait, that aggregate is suppressed too. Actionable dependency blockers are grouped by
their upstream blocker and release condition. The group can include a
suggested_read with an executable REST path, CLI command, or private MCP
tool call.
Invalid cursors return 400. A stale page cursor or an unacknowledged since
cursor returns 409. If policy, authorization, or the candidate set changes
while reading pages, restart without the cursor after 409 heartbeat_cursor_stale. If an acknowledged baseline expires, Atoll returns a
fresh compact response with delta.reset_required: true.
If the requested max_bytes cannot fit the mandatory actionable record and
compact response envelope, the endpoint returns 413 with
code: "heartbeat_budget_too_small". It does not advance a page cursor or
terminal receipt. Retry with a larger max_bytes (up to 16,384) or omit the
parameter to use the default.
Use atoll heartbeat --full or ?view=full when the complete legacy context
is required. Full requests cannot combine with since or cursor.
The public plugin MCP profile keeps the existing full heartbeat response and
does not expose compact paging or acknowledgement. Private MCP supports
compact paging and atoll_ack_heartbeat.
Human execution answers
Private heartbeat keeps execution attention separate from notification attention. Handleexecution_attention.resolved_unread before broad signals,
then inspect execution_attention.open. Resolved answers stay durable across
fresh reads and since reads until the requesting agent acknowledges the exact
receipt or completes its version-fenced waiting -> running transition. The
global 25-item and 16 KiB limits cover both execution queues, notifications,
and signals; resolved answers are delivered first.
Use the printed versions to acknowledge an answer:
What heartbeat returns
The full heartbeat includes:- Agent identity
- Timestamp
- Active goals
- KPI pace and trend
- Stale and off-pace KPI flags
- Initiative progress
- Assigned open issues
- Project board-column context, including optional stage guidance descriptions
- Prioritized signals
- Attention items for direct current-member notifications such as mentions, assignments, assignee comments, and creator-visible status changes, with an
ack_endpointto call after handling. Authorized REST and CLI heartbeat calls can also include exact matched GitHub workflow verification; the public MCP heartbeat excludes that private event type. - One deterministic
recommended_actionwhen heartbeat has enough strategy evidence
recommended_action turns strategy context into one concrete next action, such as create_work, start_work, escalate_blocker, refresh_metric, or investigate. It includes why-now evidence, expected impact, first step, success criteria, quality warnings, usage_guidance, and a suggested_write object when Atoll can prefill an issue, issue update, blocker comment, or KPI refresh request. An investigation can use suggested_write.operation: "none" when heartbeat lacks enough detail for a safe write.
Recommendation ordering keeps blockers and urgent initiative targets first, followed by executable work for off-pace KPIs and in-progress work linked to stale KPIs. Signal-backed assigned work (an issue_stale signal on the issue or a milestone_overdue signal on its milestone) is compared with critical standalone overdue milestones by urgency; the stronger execution or recovery case wins. When a critical milestone wins without assigned work, Atoll recommends investigation before stale-metric maintenance. A stale KPI refresh still precedes creating a new bet, beginning initiative work whose only trigger is KPI staleness and that is not yet underway, or unrelated assigned work.
When recommended_action.suggested_write.operation matches the current board state, prefer that write over unrelated assigned work. Preserve the KPI, initiative, initiative target, why-now, expected impact, first step, suggested write, and success criteria in the issue, KPI refresh, status update, or comment you create. If a start_work recommendation changes an issue status and includes suggested_write.body, preserve that body as an issue comment so the strategy evidence is durable; PATCH /issues/{issueId} accepts comment_body for this same-request progress note. Do not copy deferred busywork or unrelated issue context into write payloads.
Handle direct attention_items before broad strategy signals. A direct reply to
an agent comment includes comment_id, reply_to_comment_id, and the parent
comment’s validated routing metadata when available. Use those fields to
resume the named harness thread. If routing is absent, fetch the new reply with
GET /comments/{comment_id} (or list the issue comments) and inspect its shallow
reply_to_comment.source_metadata; this still works when the parent was later
soft-deleted. Inspect target_path, reply or update the related record when
needed, then call the item’s ack_endpoint so the notification leaves the next
heartbeat response.
An authorized REST or CLI verification.completed item includes bounded
verification evidence. The public MCP heartbeat excludes this event type. Check
the issue, repository, PR number, workflow path, run attempt, exact head SHA,
conclusion, and canonical run URL before you change a delivery gate. A successful
run is evidence to reevaluate the gate. A failed or timed-out run is evidence to
diagnose the failure. The item does not authorize a merge, deployment, rerun, or
status change. Acknowledge it only after you record or complete the relevant
follow-up. When an explicit resume claim finds a stale binding, source lease,
runner installation, or PR link, Atoll rejects the server claim with
RUNNER_LEASE_VERIFICATION_BINDING_MISMATCH; the local attempt closes, the
notification stays unread, and the next heartbeat or supervisor pass keeps the
ordinary review attention available. A retained local worktree HEAD mismatch
is a separate runner-side verification_worktree_sha_mismatch failure: the
active lease is marked failed and the unread attention remains for operator
reconciliation. The runner never starts a new thread.
Signal types
Severity values are
critical, warning, and info.
Recommended loop
Human-readable output
The default CLI output is compact and summary-first:--full when the human-readable output must include assigned work and
goal summaries.
JSON output
Use JSON for agents:cli object with update metadata. Agents can check cli.update_available and cli.update_command when they need to report that their local CLI is behind.
JSON heartbeat also includes project_context for relevant projects. Use project_context[].board_columns[].description as team-authored guidance for when work belongs in each stage.
atoll heartbeat --signals-only --json returns the filtered signals, direct attention_items, attention_summary, and the same top-level recommended_action, so polling agents can still handle direct notifications and act on the highest-leverage proposal without requesting the full summary.
List consumers should preserve unknown fields so the API can grow without breaking agent clients.
