claude-code - 💡(How to fix) Fix AgentView: keep-alive / external-event-trigger hook for long-running MCP-driven sessions

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

AgentView's lifecycle rule — "once a session finishes and sits unattached for about an hour, the supervisor stops its process" — makes it incompatible with a class of legitimate long-running Claude Code workflows: persistent dispatchers backed by push-based MCP servers (Slack Socket Mode, webhooks, queue consumers, file watchers). I'd love to be able to host these in AgentView like everything else, but today they need their own dedicated foreground terminal.

Filing as a feature request to either expose a keep-alive opt-out, or to teach the supervisor that MCP-server activity counts as "active."

Error Message

  1. The supervisor restarts sessions on user attach/peek/reply, not on external events. There's no hook for "wake this session when MCP server X receives data." So even if the dispatcher's process is killed, the next Slack event won't bring it back. The bot would silently go dark — no error surface for the operator until someone in Slack pings it and gets nothing.

Root Cause

When 2.1.139 dropped AgentView, the natural question was: can this dispatcher move to a background session and show up in claude agents alongside everything else? Reading the docs carefully, the answer right now is no, and the reason is the supervisor's idle-kill heuristic.

Fix Action

Fix / Workaround

AgentView's lifecycle rule — "once a session finishes and sits unattached for about an hour, the supervisor stops its process" — makes it incompatible with a class of legitimate long-running Claude Code workflows: persistent dispatchers backed by push-based MCP servers (Slack Socket Mode, webhooks, queue consumers, file watchers). I'd love to be able to host these in AgentView like everything else, but today they need their own dedicated foreground terminal.

I run a Slack bot (retrodigio/claude-channel-slack) where one Claude Code session is the dispatcher: it holds an open Socket Mode WebSocket via an MCP server, receives Slack events as <channel source="slack"> tool notifications, and either replies directly (DMs) or spawns subagents (channels) routed to per-project repos. It's been running great as a long-lived foreground session for ~3 weeks now.

When 2.1.139 dropped AgentView, the natural question was: can this dispatcher move to a background session and show up in claude agents alongside everything else? Reading the docs carefully, the answer right now is no, and the reason is the supervisor's idle-kill heuristic.

RAW_BUFFERClick to expand / collapse

Summary

AgentView's lifecycle rule — "once a session finishes and sits unattached for about an hour, the supervisor stops its process" — makes it incompatible with a class of legitimate long-running Claude Code workflows: persistent dispatchers backed by push-based MCP servers (Slack Socket Mode, webhooks, queue consumers, file watchers). I'd love to be able to host these in AgentView like everything else, but today they need their own dedicated foreground terminal.

Filing as a feature request to either expose a keep-alive opt-out, or to teach the supervisor that MCP-server activity counts as "active."

Concrete use case

I run a Slack bot (retrodigio/claude-channel-slack) where one Claude Code session is the dispatcher: it holds an open Socket Mode WebSocket via an MCP server, receives Slack events as <channel source="slack"> tool notifications, and either replies directly (DMs) or spawns subagents (channels) routed to per-project repos. It's been running great as a long-lived foreground session for ~3 weeks now.

When 2.1.139 dropped AgentView, the natural question was: can this dispatcher move to a background session and show up in claude agents alongside everything else? Reading the docs carefully, the answer right now is no, and the reason is the supervisor's idle-kill heuristic.

Why this dispatcher doesn't fit today

  1. The MCP server is inside the Claude Code process. The slack-channel plugin spawns a child process from this Claude Code instance and holds Socket Mode there. When the Claude Code process exits, the MCP server exits with it, the WebSocket closes, and Slack stops delivering events. Socket Mode has no offline buffer — missed events while disconnected are gone.

  2. The dispatcher is idle most of the time. Between Slack events it has no active work. The supervisor's heuristic ("actively working, waiting for your input, or has a terminal attached") treats it as completed-unattached and reaps it after ~1hr.

  3. The supervisor restarts sessions on user attach/peek/reply, not on external events. There's no hook for "wake this session when MCP server X receives data." So even if the dispatcher's process is killed, the next Slack event won't bring it back. The bot would silently go dark — no error surface for the operator until someone in Slack pings it and gets nothing.

  4. /loop doesn't fit. Polling on a schedule defeats the point of Socket Mode (push, real-time) and would add fetch_messages API cost for every poll regardless of whether anything happened.

Proposed (three options, ranked by my preference)

Option A — --no-idle-timeout / keepAlive: true flag. The simplest: let a session opt out of the idle-kill on dispatch. claude --bg --no-idle-timeout "<prompt>" or a frontmatter field on subagents. Operator takes responsibility for the resource cost; the supervisor honors the opt-out. Minimal API surface change.

Option B — Treat MCP server activity as "active." The supervisor could subscribe to MCP server connection state on each session: if any of the session's MCP servers has an open external connection (Socket Mode WebSocket, persistent HTTP, long-poll), the session is "active" for lifecycle purposes regardless of whether the LLM is generating. This is the most architecturally clean — the supervisor would Just Work for event-driven cases — but it requires MCP servers to surface that state. Could be best-effort with a heartbeat protocol (server advertises "I'm holding an external connection that needs the session alive").

Option C — A new claude --service mode that's distinct from --bg. Documented up front as "long-running event-driven session with no idle timeout, manage explicitly with claude stop." Cleaner separation from --bg (which is task-oriented) — different semantics, different rules. Most discoverable in docs.

Any one of these would unblock our use case. I'd default to A for fast iteration and add B later as the right long-term answer.

Broader class this would unblock

This isn't just Slack bots. The same pattern applies to:

  • GitHub event watchers (webhook consumer → dispatcher → per-PR subagent)
  • Linear/Jira webhook handlers (issue-event-driven coding agents)
  • CI/CD log monitors (subscribe to a build stream, dispatch on failure)
  • File watchers for triggered ingestion (e.g., a folder under ~/Downloads/ triggers a research subagent)
  • Message queue consumers (Kafka, SQS, Redis Streams)
  • MCP servers exposing IoT or sensor data

Today all of these require their own dedicated foreground terminal (or a custom tmux/screen setup), which loses the AgentView benefits — single-pane visibility, pinned/peek/attach UX, the Haiku-generated summary, state-grouped list.

What I've tried / workaround today

Keeping the dispatcher in a dedicated foreground terminal works fine — it's how I've been running this for weeks. Just means it doesn't participate in AgentView, which is the gap I'd like to close.

References

Happy to discuss design tradeoffs or contribute if useful. Thanks for AgentView — it's already changed how I work; this would let one more workflow join the party.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING