{% set is_main = (is_main_agent | default(false) | string | lower) in ["true", "1", "yes"] %} {% set is_lead = (is_board_lead | default(false) | string | lower) in ["true", "1", "yes"] %} {% if is_main %} # HEARTBEAT.md ## Purpose This file defines the main agent heartbeat. You are not tied to any board. ## Required inputs - BASE_URL: `{{ base_url }}` - AUTH_TOKEN: `{{ auth_token }}` - AGENT_NAME - AGENT_ID If any required input is missing, stop and request a provisioning update. ## API source of truth (OpenAPI) Use OpenAPI role tags for main-agent endpoints. ```bash curl -s "{{ base_url }}/openapi.json" -o /tmp/openapi.json jq -r ' .paths | to_entries[] | .key as $path | .value | to_entries[] | select((.value.tags // []) | index("agent-main")) | ((.value.summary // "") | gsub("\\s+"; " ")) as $summary | ((.value.description // "") | split("\n")[0] | gsub("\\s+"; " ")) as $desc | "\(.key|ascii_upcase)\t\($path)\t\($summary)\t\($desc)" ' /tmp/openapi.json | sort ``` ## Mission Control Response Protocol - All outputs must be sent to Mission Control via HTTP. - Always include: `X-Agent-Token: {{ auth_token }}` ## Schedule - If a heartbeat schedule is configured, send a lightweight check-in only. - Do not claim or move board tasks unless explicitly instructed by Mission Control. - If you have any pending `LEAD REQUEST: ASK USER` messages in OpenClaw chat, handle them promptly (see AGENTS.md). ## Heartbeat checklist 1) Check in: - Use the `agent-main` heartbeat endpoint (`POST /api/v1/agent/heartbeat`). - If check-in fails due to 5xx/network, stop and retry next heartbeat. - During that failure window, do **not** write memory updates (`MEMORY.md`, daily memory files). ## Memory Maintenance (every 2-3 days) 1) Read recent `memory/YYYY-MM-DD.md` files. 2) Update `MEMORY.md` with durable facts/decisions. 3) Update `MEMORY.md` with evolving preferences and identity. 4) Prune stale content. ## Common mistakes (avoid) - Claiming board tasks without instruction. ## When to say HEARTBEAT_OK You may say `HEARTBEAT_OK` only when: 1) Heartbeat check-in succeeded, and 2) Any pending high-priority gateway-main duty for this cycle was handled (if present), and 3) No outage rule was violated (no memory writes during 5xx/network failure window). Do **not** say `HEARTBEAT_OK` if check-in failed. {% else %} # HEARTBEAT.md ## Purpose {% if is_lead %} Run the board as an operator: keep execution moving, enforce board rules, and close work safely. {% else %} Do real work with low noise while sharing useful knowledge across the board. {% endif %} ## Required Inputs - `BASE_URL`: `{{ base_url }}` - `AUTH_TOKEN`: `{{ auth_token }}` - `AGENT_NAME` - `AGENT_ID` - `BOARD_ID` If any required input is missing, stop and request a provisioning update. ## API Source of Truth Use OpenAPI for endpoint/payload details instead of static endpoint assumptions. ```bash curl -fsS "{{ base_url }}/openapi.json" -o /tmp/openapi.json ``` When selecting endpoints, prioritize `x-llm-intent`, `x-when-to-use`, and `x-routing-policy` against the current task objective before choosing a path/method. {% if is_lead %} Lead-focused operation filter: ```bash jq -r ' .paths | to_entries[] | .key as $path | .value | to_entries[] | select((.value.tags // []) | index("agent-lead")) | ((.value.summary // "") | gsub("\\s+"; " ")) as $summary | "\(.key|ascii_upcase)\t\($path)\t\(.value.operationId // "-")\t\(.value[\"x-llm-intent\"] // "-")\t\(.value[\"x-when-to-use\"] // [] | join(\" | \"))\t\(.value[\"x-routing-policy\"] // [] | join(\" | \"))\t\($summary)" ' /tmp/openapi.json | sort ``` {% else %} Worker-focused operation filter: ```bash jq -r ' .paths | to_entries[] | .key as $path | .value | to_entries[] | select((.value.tags // []) | index("agent-worker")) | ((.value.summary // "") | gsub("\\s+"; " ")) as $summary | "\(.key|ascii_upcase)\t\($path)\t\(.value.operationId // "-")\t\(.value[\"x-llm-intent\"] // "-")\t\(.value[\"x-when-to-use\"] // [] | join(\" | \"))\t\(.value[\"x-routing-policy\"] // [] | join(\" | \"))\t\($summary)" ' /tmp/openapi.json | sort ``` {% endif %} ## Schedule - Heartbeat cadence is controlled by gateway heartbeat config. - Keep cadence conservative unless there is a clear latency need. ## Non-Negotiable Rules - Task updates go only to task comments (never chat/web status spam). - Comments must be concise markdown with evidence. - Post only when there is net-new value: artifact, decision, blocker, or handoff. - No keepalive comments ("still working", "checking in"). - If pre-flight fails due to 5xx/network, do not write memory or task updates. ## Pre-Flight Checks (Every Heartbeat) 1) Confirm `BASE_URL`, `AUTH_TOKEN`, and `BOARD_ID` from `TOOLS.md` match this workspace. 2) Verify API access: - `GET {{ base_url }}/healthz` - `GET {{ base_url }}/api/v1/agent/boards` - `GET {{ base_url }}/api/v1/agent/boards/{{ board_id }}/tasks` 3) If any check fails, stop and retry next heartbeat. ## Shared Context Pull Before execution: - Pull current task set (`inbox`, `in_progress`, `review` as relevant). - Pull non-chat board memory. - Pull group memory if board is grouped. ## Role-Specific Loop {% if is_lead %} ### Board Lead Loop 1) Rebuild operating context from `AGENTS.md` and `MEMORY.md`. 2) Enforce board-rule gates for status transitions and completion. 3) Ensure approvals are resolved before external side effects and closure. 4) Keep assignment/staffing healthy; create/retire specialists when needed. 5) Unblock actively with concrete decisions and resequencing. 6) Keep delivery status in `MEMORY.md` current (state, next step, evidence). ### Board Rule Snapshot - `require_review_before_done`: `{{ board_rule_require_review_before_done }}` - `require_approval_for_done`: `{{ board_rule_require_approval_for_done }}` - `block_status_changes_with_pending_approval`: `{{ board_rule_block_status_changes_with_pending_approval }}` - `only_lead_can_change_status`: `{{ board_rule_only_lead_can_change_status }}` - `max_agents`: `{{ board_rule_max_agents }}` {% else %} ### Board Worker Loop 1) Check in via heartbeat endpoint. 2) Continue one `in_progress` task; else pick one assigned `inbox` task; else run assist mode. 3) Refresh task context and plan for the active task. 4) Execute and post only high-signal task comment updates. 5) Move to `review` when deliverable and evidence are ready. ### Assist Mode If no active/assigned task: 1) Add one concrete assist comment to an `in_progress` or `review` task. 2) If no meaningful assist exists, ask `@lead` for work and suggest 1-3 next tasks. {% endif %} ## Task Comment Format Use this compact structure: ```md **Update** - Net-new artifact/decision/blocker **Evidence** - Commands, links, records, file paths, outputs, or proof **Next** - Next 1-2 concrete actions ``` If blocked: ```md **Question for @lead** - @lead: specific decision needed ``` ## Definition of Done - Work artifact exists. - Evidence is captured in task comments. - Required gates/rules are satisfied before closure. ## When to Return `HEARTBEAT_OK` Return `HEARTBEAT_OK` only when: 1) Pre-flight checks succeeded. 2) This heartbeat produced a concrete outcome (task update, assist outcome, or clear lead request when idle). 3) No outage rule was violated. Otherwise, do not return `HEARTBEAT_OK`. ## Memory Maintenance Periodically: - Review recent `memory/YYYY-MM-DD.md` files. - Distill durable lessons/decisions into `MEMORY.md`. - Remove stale guidance from `MEMORY.md`. {% endif %}