Skip to content

Feature request: emit periodic heartbeat hook events during agent processing #2701

@cmacboyd

Description

@cmacboyd

Problem

Tools that integrate with Copilot CLI via the hook system (e.g. agent-deck) rely on lifecycle events like UserPromptSubmit and Stop to track whether the agent is actively working. However, there are no events emitted while the agent is processing — only a start event and an end event.

For long-running operations (multi-minute responses, complex code generation, large refactors), external tools have no signal that the agent is still alive. They must either:

  • Trust the last event indefinitely (risks showing "running" for crashed sessions)
  • Use a freshness window and fall back to heuristics (loses accurate status after timeout)

Neither option is great. Agent-deck currently uses a 10-minute freshness window with tmux activity heuristics as a fallback, but this is fragile.

Proposed Solution

Emit a periodic Heartbeat (or Processing) hook event every 15-30 seconds while the agent is actively working (between UserPromptSubmit/BeforeAgent and Stop/AfterAgent).

The payload would be identical to existing hook events:

{
  "hook_event_name": "Heartbeat",
  "session_id": "session-uuid-here"
}

Why this works well

  • Zero protocol changes — same JSON format, same stdin delivery, same hook handler invocation
  • Minimal implementation — a timer that fires during processing and calls the existing hook dispatch
  • Graceful degradation — tools that dont recognize Heartbeat ignore it (unknown events already map to no-op)
  • Solves the freshness problem — external tools reset their freshness timer on each heartbeat, keeping accurate status for arbitrarily long operations

What tools get from this

  • Accurate "running" vs "idle" status for long operations
  • Reliable detection of crashed/hung sessions (heartbeats stop = session is dead)
  • No need for fragile heuristics (tmux pane activity polling, process tree inspection)

Alternatives Considered

  • Tool-use events — emitting a hook on each tool invocation (file edit, bash, grep) would also reset freshness, but is more invasive and couples the hook protocol to internal tool execution
  • Longer freshness windows — what we do today; works but loses accuracy for sessions that genuinely crash during a long operation

Context

This came up while investigating status tracking gaps in agent-deck, where Copilot sessions would show as "idle" in the TUI even though they were actively processing. The root cause is the silence between start/end events during long operations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:pluginsPlugin system, marketplace, hooks, skills, extensions, and custom agents
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions