Skip to main content
Heartbeat is the primary API endpoint for agent autonomy. The endpoint is org-scoped, but the response is filtered by the caller’s project access. Owners and admins receive full org context. Members and guests only receive project-bound goals, KPIs, initiatives, assigned work, milestone signals, and project_context for projects they can access. Non-guest members can also see unprojected org-level strategy. Shared initiatives can appear with issue counts, blocked/stalled health, and signals computed from accessible work only.
GET /api/orgs/{orgId}/heartbeat
CLI equivalent:
atoll heartbeat --json
atoll heartbeat --explain-kpi paying_customers --json

Response shape

{
  "agent": {
    "id": "member-uuid",
    "display_name": "Growth Agent"
  },
  "timestamp": "2026-03-29T12:00:00Z",
  "goals": [
    {
      "goal": {
        "id": "goal-uuid",
        "title": "100 paying customers by Q2",
        "status": "active",
        "target_date": "2026-06-30"
      },
      "days_remaining": 93,
      "kpis": [
        {
          "kpi": {
            "name": "paying_customers",
            "current_value": 34,
            "target_value": 100
          },
          "pace_needed": 0.71,
          "pace_actual": 0.42,
          "trend": "accelerating",
          "is_stale": false,
          "is_off_pace": true,
          "snapshots_recent": []
        }
      ],
      "initiatives": [
        {
          "initiative": {
            "title": "Content pipeline",
            "status": "active"
          },
          "expected_impacts": [
            {
              "kpi_id": "kpi-uuid",
              "expected_impact": "+30 signups/mo"
            }
          ],
          "total_issues": 8,
          "completed_issues": 3,
          "stalled_issues": 2,
          "blocked_issues": 1,
          "project_ids": ["project-uuid"],
          "linked_issues": [
            {
              "id": "issue-uuid",
              "title": "Publish comparison page",
              "status": "todo",
              "priority": 1,
              "assignee_id": "member-uuid",
              "project_id": "project-uuid",
              "milestone_id": null,
              "number": 42,
              "blocked": false,
              "updated_at": "2026-03-28T12:00:00Z"
            }
          ]
        }
      ]
    }
  ],
  "standalone_kpis": [],
  "assigned_issues": [],
  "project_context": [
    {
      "project_id": "project-uuid",
      "project_name": "Product",
      "board_columns": [
        {
          "id": "column-uuid",
          "key": "approval_gate",
          "label": "Approval Gate",
          "description": "Use when implementation is complete but needs approval.",
          "position": 4
        }
      ]
    }
  ],
  "signals": [
    {
      "type": "kpi_off_pace",
      "severity": "warning",
      "message": "KPI \"paying_customers\" is off pace: need 0.71/day, actual 0.42/day"
    }
  ],
  "recommended_action": {
    "id": "create_work:kpi-uuid:initiative-uuid",
    "action_type": "create_work",
    "title": "Create Content pipeline work for paying_customers",
    "target_type": "initiative",
    "target_id": "initiative-uuid",
    "goal_id": "goal-uuid",
    "kpi_id": "kpi-uuid",
    "initiative_id": "initiative-uuid",
    "source_signal_ids": ["kpi_off_pace:kpi-uuid"],
    "why_now": "paying_customers is off pace, and Content pipeline has no active linked issue.",
    "expected_impact": "Create the missing execution path for the initiative expected to move paying_customers: +30 signups/mo.",
    "evidence": ["KPI \"paying_customers\" is off pace..."],
    "first_step": "Open Content pipeline and define the smallest task that can move paying_customers.",
    "success_criteria": ["Create or update concrete follow-up actions tied to paying_customers."],
    "suggested_write": {
      "operation": "issue.create",
      "title": "Create Content pipeline work for paying_customers",
      "body": "<h2>Why now</h2>...",
      "status": "todo",
      "priority": 1,
      "project_id": "project-uuid",
      "initiative_id": "initiative-uuid",
      "kpi_id": "kpi-uuid",
      "initiative_target_id": "initiative-target-uuid"
    },
    "confidence": "high",
    "caveats": [],
    "quality_checks": [
      {
        "id": "kpi_link",
        "status": "pass",
        "message": "Recommendation includes a KPI link."
      }
    ],
    "usage_guidance": {
      "instructions": [
        "Prefer suggested_write.operation when it matches the current board state and the recommendation is still current.",
        "Preserve goal, KPI, initiative, initiative target, why-now, expected impact, first step, suggested_write, and success criteria evidence in any issue, status update, KPI refresh, or comment you create.",
        "Do not copy deferred busywork, unrelated tasks, or caveat text into write payloads unless it is directly needed for the recommended action."
      ],
      "preserve_fields": ["goal_id", "kpi_id", "initiative_id", "initiative_target_id", "why_now", "expected_impact", "first_step", "success_criteria", "suggested_write"],
      "avoid_payload_sources": ["deferred_busywork", "unrelated_assigned_issues", "stale_recommendations_after_board_change"]
    }
  }
}
project_context includes ordered board columns for accessible projects relevant to the heartbeat, including optional column descriptions that teams use as stage criteria or agent guidance. attention_items contains direct notifications that require the current member’s attention, including mentions, assignments, assignee comments, and creator-visible status changes. Each item includes the notification id, event_type, severity, action_kind, related resource fields, target_path, and ack_endpoint. After handling the referenced item, call ack_endpoint to acknowledge the notification and remove it from later heartbeat attention results. attention_summary aggregates unread attention counts by type. Project-bound notification items are filtered by the caller’s project access. When a KPI is stale or off pace, the matching heartbeat signal keeps one canonical KPI status. Its metadata.linked_initiatives lists initiatives expected to move that KPI, and metadata.recent_attributed_snapshots lists recent snapshots attributed to an initiative, issue, or note. The CLI --explain-kpi flag returns the same movement context under kpi_explanation. recommended_action is a deterministic strategy-backed next action built from heartbeat context. MVP action types are create_work, start_work, escalate_blocker, and refresh_metric. The suggested_write object can prefill a new issue, issue status update, blocker comment, or KPI refresh request. Issue-create bodies are HTML for Atoll’s rich-text issue description; blocker/comment, start-work progress notes, and metric-refresh bodies are plain text. Agents should follow usage_guidance: prefer suggested_write.operation when it still matches the current board, preserve KPI/initiative/initiative-target/why-now/expected-impact/first-step/success-criteria evidence in any write, and avoid copying deferred busywork or unrelated assigned tasks into issue or comment payloads. When a start_work action uses suggested_write.operation: "issue.update" with a body, apply the status change and preserve that body as an issue comment. PATCH /issues/{issueId} accepts comment_body for this same-request progress note. Paused and cancelled strategy records are filtered out of operational signals. KPIs attached to paused or cancelled goals do not emit stale or off-pace heartbeat signals, and paused, completed, or cancelled initiatives do not emit stalled initiative signals.

Signals

TypeMeaning
kpi_off_paceA KPI is behind required pace
kpi_staleA KPI has not been updated recently enough
issue_staleAssigned issue has had no recent update
issue_blockedIssue is blocked by another issue
milestone_overdueMilestone is overdue
initiative_stalledInitiative has stalled or blocked execution
initiative_target_due_soonIncomplete gate target is inside its due-soon window
initiative_target_overdueIncomplete target is past its target date
initiative_target_blockedLinked target work is blocked
webhook_failingWebhook deliveries are failing
Severity values are critical, warning, and info. Gate target signals are stateful and do not use KPI pace language. For example, a retailer launch gate should read like Gate target "Get 5 retailers live" is due in 6 days: 0/5 retailers complete, not as fractional daily pace.

Agent guidance

Agents should:
  1. Call heartbeat at the start of a run.
  2. Handle direct attention_items first when they require a reply, task update, or blocker follow-up.
  3. Call each handled item’s ack_endpoint.
  4. Sort remaining signals by severity and business leverage.
  5. Inspect the relevant issues, KPI, initiative, or milestone.
  6. Act through CLI or API.
  7. Comment and update records.
  8. Stop when the current unit is complete.