From de5801a1e5723f61da8f058627e7d34802556ae9 Mon Sep 17 00:00:00 2001 From: Alexander Bychinskiy Date: Thu, 28 May 2026 11:26:14 +0400 Subject: [PATCH] telegram-bridge: append reply directive to inbound messages Adds a TG_REPLY_DIRECTIVE suffix to every prompt forwarded from Telegram to a worker pane (single-target, broadcast, and attachment paths). The directive reminds the worker that: - the user cannot see the tmux pane - replying requires calling the notify MCP tool, not pane output - returned message_id should be quoted in taskbox/board references Without the directive, workers commonly reply in-pane and the user sees silence on Telegram. --- scripts/telegram-bridge.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/telegram-bridge.py b/scripts/telegram-bridge.py index 25d45e2..31772b8 100644 --- a/scripts/telegram-bridge.py +++ b/scripts/telegram-bridge.py @@ -60,6 +60,17 @@ RUNTIME_DIR = PROJECT_DIR / ".octobots" RELAY_SCRIPT = OCTOBOTS_DIR / "skills" / "taskbox" / "scripts" / "relay.py" +# Appended to every inbound Telegram message so workers cannot assume their +# pane is visible to the user. The bridge is one-way (user → worker via +# tmux send-keys); worker → user only works through the `notify` MCP. +# Without this directive, workers reply in-pane and the user sees silence. +TG_REPLY_DIRECTIVE = ( + "\n\n⚠️ This message is from a real Telegram user. They CANNOT see your " + "pane. You MUST reply by calling mcp__notify__notify(message=\"...\"). " + "Pane-only output = silence to the user. Capture the returned message_id " + "and quote it in any subsequent taskbox/board reference to this exchange." +) + def _check_env() -> None: if not TG_TOKEN: @@ -820,7 +831,7 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> sent = [] failed = [] for role_name, _ in sorted(pane_map.items()): - if tmux_send(role_name, f"[User via Telegram to everyone]: {text}"): + if tmux_send(role_name, f"[User via Telegram to everyone]: {text}{TG_REPLY_DIRECTIVE}"): display = DISPLAY_NAMES.get(role_name, role_name) sent.append(display) else: @@ -852,7 +863,7 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> return # Send directly to the role's tmux pane - success = tmux_send(target_pane, f"[User via Telegram]: {text}") + success = tmux_send(target_pane, f"[User via Telegram]: {text}{TG_REPLY_DIRECTIVE}") if success: logger.info("Telegram → %s: %s", target_pane, text[:80]) @@ -954,7 +965,7 @@ async def handle_attachment(update: Update, context: ContextTypes.DEFAULT_TYPE) else: prompt = f"[User via Telegram] sent file '{filename}' (saved to {local_path}): {caption} -- Use the Read tool on {local_path} to view it." - success = tmux_send(target_pane, prompt) + success = tmux_send(target_pane, prompt + TG_REPLY_DIRECTIVE) if success: await send_telegram(