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

    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