refactor(heartbeat): harden dm delivery classification

This commit is contained in:
Peter Steinberger
2026-02-25 02:12:59 +00:00
parent 91ae82ae19
commit 24d7612ddf
8 changed files with 292 additions and 105 deletions

View File

@@ -812,7 +812,7 @@ Periodic heartbeat runs.
- `every`: duration string (ms/s/m/h). Default: `30m`.
- `suppressToolErrorWarnings`: when true, suppresses tool error warning payloads during heartbeat runs.
- Heartbeats never deliver to DM-style `user:<id>` targets; those runs still execute, but outbound delivery is skipped.
- Heartbeats never deliver to direct/DM chat targets when the destination can be classified as direct (for example `user:<id>`, Telegram user chat IDs, or WhatsApp direct numbers/JIDs); those runs still execute, but outbound delivery is skipped.
- Per-agent: set `agents.list[].heartbeat`. When any agent defines `heartbeat`, **only those agents** run heartbeats.
- Heartbeats run full agent turns — shorter intervals burn more tokens.

View File

@@ -215,7 +215,7 @@ Use `accountId` to target a specific account on multi-account channels like Tele
- `last`: deliver to the last used external channel.
- explicit channel: `whatsapp` / `telegram` / `discord` / `googlechat` / `slack` / `msteams` / `signal` / `imessage`.
- `none` (default): run the heartbeat but **do not deliver** externally.
- DM-style heartbeat destinations are blocked (`user:<id>` targets resolve to no-delivery).
- Direct/DM heartbeat destinations are blocked when target parsing identifies a direct chat (for example `user:<id>`, Telegram user chat IDs, or WhatsApp direct numbers/JIDs).
- `to`: optional recipient override (channel-specific id, e.g. E.164 for WhatsApp or a Telegram chat id). For Telegram topics/threads, use `<chatId>:topic:<messageThreadId>`.
- `accountId`: optional account id for multi-account channels. When `target: "last"`, the account id applies to the resolved last channel if it supports accounts; otherwise it is ignored. If the account id does not match a configured account for the resolved channel, delivery is skipped.
- `prompt`: overrides the default prompt body (not merged).
@@ -236,7 +236,7 @@ Use `accountId` to target a specific account on multi-account channels like Tele
- `session` only affects the run context; delivery is controlled by `target` and `to`.
- To deliver to a specific channel/recipient, set `target` + `to`. With
`target: "last"`, delivery uses the last external channel for that session.
- Heartbeat deliveries never send to DM-style `user:<id>` targets; those runs still execute, but outbound delivery is skipped.
- Heartbeat deliveries never send to direct/DM targets when the destination is identified as direct; those runs still execute, but outbound delivery is skipped.
- If the main queue is busy, the heartbeat is skipped and retried later.
- If `target` resolves to no external destination, the run still happens but no
outbound message is sent.