summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bensima.com>2025-12-13 00:54:36 -0500
committerBen Sima <ben@bensima.com>2025-12-13 00:54:36 -0500
commit42dec1ddd4e83957ad4c6747067eb6e8351d3a4d (patch)
tree25889c7a88f86ed4737688cb0299fa375e2cfcb0
parent6bbf81f41c318a4200156e58707c807b230a601c (diff)
telegram: intelligent group response (LLM decides when to speak)
- Remove mention-based filtering, bot sees all group messages - Add response rules to system prompt for group chats: - tool invocation = always respond - direct question = respond - factual correction = maybe respond - casual banter = stay silent - Empty response in group = intentional silence (no fallback msg) - Add chat type context to system prompt
-rw-r--r--Omni/Agent/Telegram.hs57
1 files changed, 35 insertions, 22 deletions
diff --git a/Omni/Agent/Telegram.hs b/Omni/Agent/Telegram.hs
index ffad4c7..f8afcb7 100644
--- a/Omni/Agent/Telegram.hs
+++ b/Omni/Agent/Telegram.hs
@@ -151,9 +151,21 @@ telegramSystemPrompt =
"",
"use the 'recall' tool to search your memory for relevant context when needed.",
"",
+ "## when to respond (GROUP CHATS)",
+ "",
+ "you see all messages in the group. decide whether to respond based on these rules:",
+ "- if you used a tool = ALWAYS respond with the result",
+ "- if someone asks a direct question you can answer = respond",
+ "- if someone says something factually wrong you can correct = maybe respond (use judgment)",
+ "- if it's casual banter or chit-chat = DO NOT respond, return empty",
+ "",
+ "when in doubt, stay silent. you don't need to participate in every conversation.",
+ "if you choose not to respond, return an empty message (just don't say anything).",
+ "",
"## important",
"",
- "ALWAYS include a text response to the user after using tools. never end your turn with only tool calls."
+ "in private chats, ALWAYS respond. in group chats, follow the rules above.",
+ "when you DO respond, include a text response after using tools."
]
getUpdates :: Types.TelegramConfig -> Int -> IO [Types.TelegramMessage]
@@ -288,24 +300,18 @@ handleMessage ::
Text ->
Types.TelegramMessage ->
IO ()
-handleMessage tgConfig provider engineCfg botUsername msg = do
+handleMessage tgConfig provider engineCfg _botUsername msg = do
let userName =
Types.tmUserFirstName msg
<> maybe "" (" " <>) (Types.tmUserLastName msg)
chatId = Types.tmChatId msg
usrId = Types.tmUserId msg
- unless (Types.shouldRespondInGroup botUsername msg) <| do
- when (Types.isGroupChat msg)
- <| putText
- <| "Ignoring group message (not mentioned): "
- <> Text.take 50 (Types.tmText msg)
-
unless (Types.isUserAllowed tgConfig usrId) <| do
putText <| "Unauthorized user: " <> tshow usrId <> " (" <> userName <> ")"
sendMessage tgConfig chatId "sorry, you're not authorized to use this bot."
- when (Types.shouldRespondInGroup botUsername msg && Types.isUserAllowed tgConfig usrId) <| do
+ when (Types.isUserAllowed tgConfig usrId) <| do
sendTypingAction tgConfig chatId
user <- Memory.getOrCreateUserByTelegramId usrId userName
@@ -440,10 +446,15 @@ handleAuthorizedMessage tgConfig provider engineCfg msg uid userName chatId = do
let localTime = utcToLocalTime tz now
timeStr = Text.pack (formatTime defaultTimeLocale "%A, %B %d, %Y at %H:%M" localTime)
- let systemPrompt =
+ let chatContext =
+ if Types.isGroupChat msg
+ then "\n\n## Chat Type\nThis is a GROUP CHAT. Apply the group response rules - only respond if appropriate."
+ else "\n\n## Chat Type\nThis is a PRIVATE CHAT. Always respond to the user."
+ systemPrompt =
telegramSystemPrompt
<> "\n\n## Current Date and Time\n"
<> timeStr
+ <> chatContext
<> "\n\n## Current User\n"
<> "You are talking to: "
<> userName
@@ -505,18 +516,20 @@ handleAuthorizedMessage tgConfig provider engineCfg msg uid userName chatId = do
if Text.null response
then do
- putText "Warning: empty response from agent"
- sendMessage tgConfig chatId "hmm, i don't have a response for that"
- else sendMessage tgConfig chatId response
-
- checkAndSummarize (Types.tgOpenRouterApiKey tgConfig) uid chatId
-
- putText
- <| "Responded to "
- <> userName
- <> " (cost: "
- <> tshow (Engine.resultTotalCost agentResult)
- <> " cents)"
+ if Types.isGroupChat msg
+ then putText "Agent chose not to respond (group chat)"
+ else do
+ putText "Warning: empty response from agent"
+ sendMessage tgConfig chatId "hmm, i don't have a response for that"
+ else do
+ sendMessage tgConfig chatId response
+ checkAndSummarize (Types.tgOpenRouterApiKey tgConfig) uid chatId
+ putText
+ <| "Responded to "
+ <> userName
+ <> " (cost: "
+ <> tshow (Engine.resultTotalCost agentResult)
+ <> " cents)"
maxConversationTokens :: Int
maxConversationTokens = 4000