Feature request: let a successful delivery-tool call (e.g. a messaging MCP reply) satisfy the turn's visible-output requirement
Plain-English summary. We run Claude Code as an always-on assistant whose owner reads its replies in a Telegram chat, not in the terminal. For an agent like that, "send the Telegram reply" IS the user-visible output of a turn. Claude Code, however, requires every turn to end with visible assistant text in the transcript, and nudges the model to keep talking when a turn ends with only tool calls, even when one of those tool calls just delivered the user's answer. This request is to let a successful delivery-tool call count as the turn's visible output (or to make the nudge configurable).
Use case. Headless Claude Code deployment; all user-facing output goes through an MCP reply tool (Telegram). A repo hook enforces channel-only communication: assistant prose in the transcript is invisible to the operator and gets blocked.
Problem. The harness requires every assistant turn to end with visible assistant text. When a turn correctly ends right after a successful reply-tool call, the harness injects a nudge equivalent to "your previous response had no visible output, please continue." For a channel-mediated agent this creates an irreconcilable conflict: the hook (rightly) blocks trailing prose, the harness (wrongly, for this topology) demands it. Under that squeeze the model's discovered escape was emitting no-op tool calls (e.g. a true-only Bash) to end turns, which reads as a hung session and cost us a multi-hour outage before we found it.
Repro.
- Configure an agent whose user reads a side channel (a messaging MCP tool), not the terminal.
- Add a Stop/PreToolUse hook that blocks assistant text on reply turns (channel-only communication).
- Have the agent answer a user message by calling the delivery tool (successful send), then end the turn.
- Observe: the harness reports "no visible output" and injects the continue-nudge, even though the user received the message.
Local workaround. A stop-hook whitelist for a literal sentinel string the model emits after each reply ([reply sent]). It works, but it costs one wasted text block per reply turn and depends on the model reliably emitting the exact literal. Three independent model reviews of the incident all converged on the same upstream fix.
Requested behavior (either would resolve it):
- (a) A successful call to a tool marked as user-facing delivery (MCP tool annotation, or a settings list of tool names) counts as the turn's visible output; or
- (b) the no-visible-output nudge is suppressible per session/config (e.g. a settings.json flag), so channel-mediated deployments can opt out.
Environment. Claude Code 2.1.x, macOS, Telegram MCP plugin, custom stop hooks. Happy to provide the hook and transcript details.