← Back to PRs

#17583: feat(heartbeat): add agentId to route default heartbeat to a specific agent

by scottgl9 open 2026-02-15 23:13 View on GitHub →
docs gateway stale size: S
## Problem To run heartbeats as a non-default agent, users currently have to either: 1. **Disable the main heartbeat** (`every: "0m"`) and duplicate the entire heartbeat config into the target agent's `agents.list[].heartbeat` block 2. **Make the target agent the default** — which changes routing for everything else too This is unnecessarily complex for a common use case: "I want my heartbeat to run as my `ops` agent, not my `main` agent." ## Solution Add `agents.defaults.heartbeat.agentId` — a single field that routes the default heartbeat to a specific agent: ```json5 { agents: { defaults: { heartbeat: { every: "30m", agentId: "ops", // ← just add this target: "last", }, }, list: [ { id: "main", default: true }, { id: "ops" }, ], }, } ``` **Before:** disable main heartbeat + duplicate config into per-agent block **After:** one field, same defaults config, different agent ### Precedence - If any `agents.list[]` entry has a `heartbeat` block → `agentId` is ignored (per-agent blocks take full control, same as today) - If no per-agent heartbeat blocks exist → heartbeat runs as `agentId` (or the default agent if `agentId` is not set) This is fully backward compatible — the behavior when `agentId` is not set is identical to today. ## Implementation - **`src/config/types.agent-defaults.ts`** — Added `agentId?: string` to heartbeat config type with JSDoc - **`src/infra/heartbeat-runner.ts`** — Updated `resolveHeartbeatAgents()` and `isHeartbeatEnabledForAgent()` to respect `agentId` - **`docs/gateway/heartbeat.md`** — Documented `agentId` field, added routing section, updated config example and field notes - **`src/infra/heartbeat-runner.agent-routing.test.ts`** — 4 tests covering: default routing, agentId routing, per-agent precedence, single-agent setup ## Testing - [x] 4 new tests for agent routing (all passing) - [x] 98 existing heartbeat tests still pass - [x] Build passes - [x] Lint passes - [x] Backward compatible ## Notes - AI-assisted PR (Claude) — fully tested - This is a feature proposal — happy to adjust naming or behavior based on maintainer feedback - Discussion: https://github.com/openclaw/openclaw/discussions/17553 <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds `agents.defaults.heartbeat.agentId` field to route the default heartbeat to a specific agent without needing per-agent heartbeat blocks. This simplifies configuration for the common use case of running heartbeats as a non-default agent (e.g., running as "ops" instead of "main"). **Changes:** - Added `agentId?: string` to the heartbeat config type with comprehensive JSDoc explaining behavior and precedence rules (src/config/types.agent-defaults.ts:183) - Updated `isHeartbeatEnabledForAgent()` to check `agentId` when no per-agent heartbeat blocks exist (src/infra/heartbeat-runner.ts:134-136) - Updated `resolveHeartbeatAgents()` to use `agentId` as fallback before defaulting to the default agent (src/infra/heartbeat-runner.ts:216-218) - Documented the feature with examples and precedence rules in docs/gateway/heartbeat.md - Added 4 test cases covering default routing, `agentId` routing, per-agent precedence, and single-agent setup **Backward compatibility:** Fully backward compatible - when `agentId` is not set, behavior is identical to current implementation. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - The implementation is simple, well-tested (4 new tests covering key scenarios), fully backward compatible, and follows existing patterns in the codebase. The change only affects heartbeat routing logic when the new optional field is set, with clear precedence rules. All existing tests pass according to the PR description. - No files require special attention <sub>Last reviewed commit: 1335cb8</sub> <!-- greptile_other_comments_section --> <sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs