Skip to content

Coding-agent skill notification is broken by default (heartbeat.target defaults to 'none') #29215

@sir-lightyear

Description

@sir-lightyear

Summary

The bundled coding-agent skill instructs agents to run openclaw system event --text "Done: ..." --mode now when a background task finishes. This enqueues a system event and calls requestHeartbeatNow(), which triggers the heartbeat. The LLM processes the system event and generates a response — but that response is silently dropped because heartbeat.target defaults to "none".

The conflict

  1. Coding-agent skill (bundled) tells agents to notify via openclaw system event --mode now on completion
  2. This triggers requestHeartbeatNow() → heartbeat fires → LLM responds
  3. resolveHeartbeatDeliveryTarget() checks heartbeat.target → defaults to "none"buildNoHeartbeatDeliveryTarget({ reason: "target-none" })
  4. Response is discarded — never delivered to any channel

The same issue applies to the built-in maybeNotifyOnExit() handler for backgrounded exec processes, which also uses enqueueSystemEvent() + requestHeartbeatNow().

Impact

A new user who:

  1. Sets up OpenClaw with default config
  2. Uses the coding-agent skill to run a background Codex/Claude task
  3. Waits for a completion notification

...will never receive one. They must manually ask "is it done?" to discover the task completed. The notification mechanism in the skill is effectively dead code unless the user independently discovers they need heartbeat.target: "last".

Reproduction

  1. Fresh OpenClaw install, default config (no heartbeat.target set)
  2. Spawn a coding agent in background with the system event notification
  3. Wait for it to finish
  4. Observe: no message delivered to any channel

Possible fixes

  • Option A: Change the default heartbeat.target to "last" (breaking change for users who rely on silent heartbeats)
  • Option B: Add a note to the coding-agent skill that heartbeat.target: "last" is required for notifications
  • Option C: Use a different notification mechanism that doesn't depend on heartbeat delivery (e.g., direct channel send via the message tool)
  • Option D: Separate system event delivery from heartbeat delivery — system events triggered by exec completion could have their own delivery target that defaults to the originating session's last channel

Environment

  • OpenClaw installed via npm (Homebrew)
  • macOS (Apple Silicon)
  • Discovered while running Codex background task; notification worked only after manually adding heartbeat.target: "last" to config

References

  • resolveHeartbeatDeliveryTarget() in reply-*.js (line ~26974 in dist)
  • maybeNotifyOnExit() in pi-embedded-*.js (line ~15413 in dist)
  • Heartbeat docs: docs/gateway/heartbeat.md — confirms target: "none" is default
  • Coding-agent skill: skills/coding-agent/SKILL.md — "Auto-Notify on Completion" section

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions