You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Claude's PushNotification is never delivered from T3 threads (disabledReason: user_present) #25645
Agents on long-running background threads use Claude Code's PushNotification tool to alert the user, and in T3 it isn't delivered. Both calls from the PR Takeovers dispatcher thread (mcp:launch:870f4a9a-16a6-4ff8-a844-a7c824708e01:orchestrator-prlabels-v1, Claude) returned:
"Not sent — this terminal is active, so your output here already reaches the user; a separate notification would be redundant."
{"pushSent": false, "localSent": false, "disabledReason": "user_present"}
2026-10-24T11:30:12Z: "Issue leads pushed to contributor forks 4x today (…) — needs a push guard"
2026-10-26T02:05:31Z: "t3code fleet.lock stuck 46 min … blocks all fleet ops. Kill it?"
It's a scheduled background dispatcher thread. The agent got pushSent: false back but had no other way to reach the user.
Cause
The decision is made inside Claude Code: it treats its SDK session as an active terminal. T3 doesn't intercept or replace the tool (no PushNotification handling in apps/server), so the alert goes nowhere.
Expected
In T3, an agent's push notification reaches the user through T3's own notifications (desktop / phone push), or the tool is disabled for T3 sessions and agents get a T3 path that does deliver. At minimum, the agent shouldn't be told the user is present when T3 has no client looking at that thread.
Claude's PushNotification decides delivery inside the CLI. An Agent SDK session counts as an active terminal, so the tool returns disabledReason: "user_present" and T3 never sees the call. CLAUDE_CODE_DISABLE_NOTIFICATION_PRESENCE_CHECK only changes that into no_transport: there is no OSC terminal and no Claude Remote Control session to deliver through. Disabling the tool would also leave the agent with no path that actually reaches anyone.
The fix is a PostToolUse hook on PushNotification in the Claude adapter:
Ignore Claude's presence result. user_present means "this SDK session looks like a terminal," not "someone is looking at the thread in T3."
Deliver the message through T3: desktop and web notifications on the existing client path, and a one-shot phone push through the relay. This stays off the agent-activity phase, so a running thread is not marked as waiting for input.
Rewrite the tool result with updatedToolOutput before the model sees it, so the agent hears that T3 sent it (or that a T3 client has the thread open) instead of "this terminal is active."
Existing completion, approval, and input alerts are unchanged. They only fire on a phase change, and these calls happen while the thread is still running.
Activity
watashiwaaniket commentedon Oct 27, 2026
We're fixing this.
Claude's
PushNotificationdecides delivery inside the CLI. An Agent SDK session counts as an active terminal, so the tool returnsdisabledReason: "user_present"and T3 never sees the call.CLAUDE_CODE_DISABLE_NOTIFICATION_PRESENCE_CHECKonly changes that intono_transport: there is no OSC terminal and no Claude Remote Control session to deliver through. Disabling the tool would also leave the agent with no path that actually reaches anyone.The fix is a
PostToolUsehook onPushNotificationin the Claude adapter:user_presentmeans "this SDK session looks like a terminal," not "someone is looking at the thread in T3."updatedToolOutputbefore the model sees it, so the agent hears that T3 sent it (or that a T3 client has the thread open) instead of "this terminal is active."Existing completion, approval, and input alerts are unchanged. They only fire on a phase change, and these calls happen while the thread is still running.