Answers support messages in Telegram from your own material, and hands anything it cannot answer to a person instead of guessing.

UsesOpenAITelegram

Telegram support bot that hands over to a person

Whenever a customer writes to your Telegram support bot, they get an immediate reply. The AI answers from the support material you give it. For anything else, the person who takes handovers is sent the message first, and only once that has gone through is the customer told that someone from your business will get back to them.

Handing over is the rule, not the exception. Refunds, billing, cancellations, complaints, anything about safety or personal data, and anything your material does not cover all go to a person, as does a reply that arrives empty, in the wrong shape or not at all. A handover notifies someone; it closes nothing. The holding reply says plainly that nothing has been changed, and a draft that claims an account was fixed, refunded or closed is handed over instead of sent. If the handover cannot be delivered, the customer is asked to try again later rather than told someone has it, and the run is marked as failed. Messages from your own team are left alone.

You need Telegram (your bot) and OpenAI connected, your answers and policies written down, the chat ID of whoever takes handovers (they must open your bot and press Start once), and your team's Telegram user IDs.

TelegramTelegramWhen a new message is received. Save it as incomingMessage.When a new message is received. Save it as incomingMessage.
ValuesSet businessName to blank.Set businessName to blank.
ValuesSet supportKnowledge to blank.Set supportKnowledge to blank.
ValuesSet humanChatId to blank.Set humanChatId to blank.
ValuesSet teamMemberIds to blank.Set teamMemberIds to blank.
ValuesSet chatId to incomingMessage.chat_id.Set chatId to incomingMessage.chat_id.
Decisions & LoopsIf chatId is emptyIf chatId is empty
Yes
Decisions & LoopsStop and report a problem: That message did not say which chat it came from, so there was nowhere to reply.Stop and report a problem: That message did not say which chat it came from, so there was nowhere to reply.
No
No steps
TextSplit teamMemberIds by , and save it as teamMembers.Split teamMemberIds by , and save it as teamMembers.
ValuesSet senderId to incomingMessage.from_user_id.Set senderId to incomingMessage.from_user_id.
Decisions & LoopsIf teamMembers contains senderIdIf teamMembers contains senderId
Yes
Decisions & LoopsFinish the run: That message came from someone on your team (Telegram user ID senderId, listed in 'teamMemberIds'), so the assistant left it alone.Finish the run: That message came from someone on your team (Telegram user ID senderId, listed in 'teamMemberIds'), so the assistant left it alone.
No
No steps
Decisions & LoopsIf humanChatId is chatIdIf humanChatId is chatId
Yes
Decisions & LoopsStop and report a problem: Set the 'humanChatId' step to a different chat from the one being watched - the handover note is internal and must not be posted to the customer.Stop and report a problem: Set the 'humanChatId' step to a different chat from the one being watched - the handover note is internal and must not be posted to the customer.
No
No steps
ValuesSet customerMessage to blank.Set customerMessage to blank.
Decisions & LoopsIf a step below fails, save the error as messageErrorIf a step below fails, save the error as messageError
Try
TextTrim incomingMessage.text and save it as customerMessage.Trim incomingMessage.text and save it as customerMessage.
On error
Decisions & LoopsFinish the run: That message had no text in it, so there was nothing to answer.Finish the run: That message had no text in it, so there was nothing to answer.
Decisions & LoopsIf customerMessage starts with Support assistantIf customerMessage starts with Support assistant
Yes
Decisions & LoopsFinish the run: That message was a reply this workflow already sent, so it was left alone.Finish the run: That message was a reply this workflow already sent, so it was left alone.
No
No steps
Decisions & LoopsIf customerMessage starts with Needs a personIf customerMessage starts with Needs a person
Yes
Decisions & LoopsFinish the run: That message was a handover note this workflow already sent, so it was left alone.Finish the run: That message was a handover note this workflow already sent, so it was left alone.
No
No steps
Decisions & LoopsIf customerMessage is emptyIf customerMessage is empty
Yes
Decisions & LoopsFinish the run: That message was empty, so there was nothing to answer.Finish the run: That message was empty, so there was nothing to answer.
No
No steps
ValuesSet askedBy to a customer in this chat.Set askedBy to a customer in this chat.
Decisions & LoopsIf a step below fails, save the error as senderErrorIf a step below fails, save the error as senderError
Try
TextTrim incomingMessage.from_username and save it as senderName.Trim incomingMessage.from_username and save it as senderName.
Decisions & LoopsIf senderName isn't emptyIf senderName isn't empty
Yes
ValuesChange askedBy to @@senderName.Change askedBy to @@senderName.
No
No steps
On error
ValuesChange askedBy to a customer in this chat.Change askedBy to a customer in this chat.
ValuesSet promptRole to You are the first-line support assistant for businessName, replying in a Telegram chat.Set promptRole to You are the first-line support assistant for businessName, replying in a Telegram chat.
ValuesSet promptKnowledge to This is the only material you may answer from:Set promptKnowledge to This is the only material you may answer from: supportKnowledge truncated to 6000 characters using ... as the ellipsis .
ValuesSet promptFormat to Answer in this exact format.Set promptFormat to Answer in this exact format. First line: the single word ANSWER or the single word ESCALATE, nothing else. Every line after that: the message to send to the customer.
ValuesSet promptWhenAnswer to Use ANSWER only when the material above fully answers what they asked, and the reply needs nothing done to their account.Set promptWhenAnswer to Use ANSWER only when the material above fully answers what they asked, and the reply needs nothing done to their account.
ValuesSet promptWhenEscalate to Use ESCALATE for everything else, including: anything the material above does not cover; refunds, billing, cancellations or any change to an account; a complaint, or a message that sounds upset; anything about safety, legal matters or personal data; and anything you are unsure about. When you escalate, write a short note for the colleague picking it up instead of a reply to the customer.Set promptWhenEscalate to Use ESCALATE for everything else, including: anything the material above does not cover; refunds, billing, cancellations or any change to an account; a complaint, or a message that sounds upset; anything about safety, legal matters or personal data; and anything you are unsure about. When you escalate, write a short note for the colleague picking it up instead of a reply to the customer.
ValuesSet promptHonesty to You cannot do anything to anyone's account. Never say that you have fixed, resolved, refunded, cancelled, changed or closed anything, and never say a problem is now sorted. Say only what is true: what the material says, or that a person will pick it up.Set promptHonesty to You cannot do anything to anyone's account. Never say that you have fixed, resolved, refunded, cancelled, changed or closed anything, and never say a problem is now sorted. Say only what is true: what the material says, or that a person will pick it up.
ValuesSet supportPrompt to promptRole@promptKnowledge@promptFormat@promptWhenAnswer@promptWhenEscalate@promptHonestyMessage from askedBy:Set supportPrompt to promptRole@promptKnowledge@promptFormat@promptWhenAnswer@promptWhenEscalate@promptHonestyMessage from askedBy: customerMessage truncated to 3000 characters using ... as the ellipsis .
ValuesSet modelResult to nothing.Set modelResult to nothing.
ValuesSet modelReachable to true.Set modelReachable to true.
Decisions & LoopsIf a step below fails, save the error as modelCallErrorIf a step below fails, save the error as modelCallError
Try
OpenAIOpenAIAsk OpenAI: supportPrompt. Save it as modelResult.Ask OpenAI: supportPrompt. Save it as modelResult.
On error
ValuesChange modelReachable to false.Change modelReachable to false.
ValuesSet modelText to blank.Set modelText to blank.
Decisions & LoopsIf modelReachable is yesIf modelReachable is yes
Yes
Decisions & LoopsIf a step below fails, save the error as modelReadErrorIf a step below fails, save the error as modelReadError
Try
TextTrim modelResult.response_text and save it as modelText.Trim modelResult.response_text and save it as modelText.
On error
ValuesChange modelText to blank.Change modelText to blank.
No
No steps
ValuesSet verdictWord to blank.Set verdictWord to blank.
ValuesSet draftReply to blank.Set draftReply to blank.
Decisions & LoopsIf modelText isn't emptyIf modelText isn't empty
Yes
TextSplit modelText by a new line and save it as modelLines.Split modelText by a new line and save it as modelLines.
TextTrim the first item of modelLines in lowercase with : replaced by with . replaced by and save it as verdictWord.Trim the first item of modelLines in lowercase with : replaced by with . replaced by and save it as verdictWord.
TextTrim the items from index 1 onward of modelLines joined by a new line and save it as draftReply.Trim the items from index 1 onward of modelLines joined by a new line and save it as draftReply.
No
No steps
ValuesSet handToAPerson to true.Set handToAPerson to true.
ValuesSet handoverReason to The assistant could not be reached, so the message was passed on rather than left unanswered..Set handoverReason to The assistant could not be reached, so the message was passed on rather than left unanswered..
Decisions & LoopsIf modelReachable is yesIf modelReachable is yes
Yes
ValuesChange handoverReason to The assistant did not answer at all, so the message was passed on rather than guessed at..Change handoverReason to The assistant did not answer at all, so the message was passed on rather than guessed at..
Decisions & LoopsIf modelText isn't emptyIf modelText isn't empty
Yes
Decisions & LoopsIf verdictWord is answerIf verdictWord is answer
Yes
ValuesChange handoverReason to The assistant said it could answer but wrote no reply, so it was passed on..Change handoverReason to The assistant said it could answer but wrote no reply, so it was passed on..
Decisions & LoopsIf draftReply isn't emptyIf draftReply isn't empty
Yes
ValuesChange handToAPerson to false.Change handToAPerson to false.
No
No steps
Else if @verdictWord is "escalate"
ValuesChange handoverReason to The assistant judged this one to need a person..Change handoverReason to The assistant judged this one to need a person..
Otherwise
ValuesChange handoverReason to The assistant did not answer in the expected form, so it was passed on rather than guessed at..Change handoverReason to The assistant did not answer in the expected form, so it was passed on rather than guessed at..
No
No steps
No
No steps
ListsCreate a list of [i have fixed, i've fixed, i have resolved, i've resolved, now resolved, i have refunded, i've refunded, i have issued a refund, i have cancelled, i've cancelled, i have canceled, i have updated your account, i have changed your account, i have processed, your ticket is closed, marked as resolved, this is sorted] and save it as resolutionClaims.Create a list of [i have fixed, i've fixed, i have resolved, i've resolved, now resolved, i have refunded, i've refunded, i have issued a refund, i have cancelled, i've cancelled, i have canceled, i have updated your account, i have changed your account, i have processed, your ticket is closed, marked as resolved, this is sorted] and save it as resolutionClaims.
Decisions & LoopsIf handToAPerson is noIf handToAPerson is no
Yes
TextMake draftReply lowercase and save it as draftLower.Make draftReply lowercase and save it as draftLower.
Decisions & LoopsFor each claim in resolutionClaims:For each claim in resolutionClaims:
Decisions & Loops If draftLower contains claim If draftLower contains claim
Yes
ValuesChange handToAPerson to true.Change handToAPerson to true.
ValuesChange handoverReason to The assistant's draft claimed something had been done to the customer's account, which it cannot do, so the draft was not sent..Change handoverReason to The assistant's draft claimed something had been done to the customer's account, which it cannot do, so the draft was not sent..
Decisions & LoopsStop repeating.Stop repeating.
No
No steps
No
No steps
Decisions & LoopsIf handToAPerson is yesIf handToAPerson is yes
Yes
ValuesSet reachThem to They have no Telegram username, so you cannot message them directly. They have been asked to reply here with another way to reach them, and that reply will come to you too..Set reachThem to They have no Telegram username, so you cannot message them directly. They have been asked to reply here with another way to reach them, and that reply will come to you too..
ValuesSet contactAsk to If there is a better way to reach you, such as an email address, reply here with it..Set contactAsk to If there is a better way to reach you, such as an email address, reply here with it..
Decisions & LoopsIf chatId is less than 0If chatId is less than 0
Yes
ValuesChange reachThem to Reply to them in the support group..Change reachThem to Reply to them in the support group..
ValuesChange contactAsk to blank.Change contactAsk to blank.
Else if @askedBy starts with "@"
TextBuild the text Message them on Telegram: @askedBy and save it as reachThem.Build the text Message them on Telegram: @askedBy and save it as reachThem.
ValuesChange contactAsk to blank.Change contactAsk to blank.
Otherwise
No steps
TextBuild the text Needs a person A support message is waiting for you. From: @askedBy Chat ID: @chatId How to reach them: @reachThem and save it as handoverHead.Build the text Needs a person A support message is waiting for you. From: @askedBy Chat ID: @chatId How to reach them: @reachThem and save it as handoverHead.
ValuesSet handoverBody to What they said:Set handoverBody to What they said: customerMessage truncated to 1500 characters using ... as the ellipsis Why it came to you: handoverReason .
ValuesSet handoverExtra to blank.Set handoverExtra to blank.
Decisions & LoopsIf draftReply isn't emptyIf draftReply isn't empty
Yes
ValuesChange handoverExtra to Change handoverExtra to The assistant's note (not sent to the customer): draftReply truncated to 800 characters using ... as the ellipsis .
No
No steps
MathSet handoverNote to handoverHead plus handoverBody plus handoverExtra.Set handoverNote to handoverHead plus handoverBody plus handoverExtra.
ValuesSet handedOver to false.Set handedOver to false.
ValuesSet handoverProblem to blank.Set handoverProblem to blank.
Decisions & LoopsIf a step below fails, save the error as handoverErrorIf a step below fails, save the error as handoverError
Try
TelegramTelegramSend a message to chat humanChatId.Send a message to chat humanChatId.handoverNote truncated to 3800 characters using "..." as the ellipsis
ValuesChange handedOver to true.Change handedOver to true.
On error
ValuesChange handoverProblem to handoverError.message.Change handoverProblem to handoverError.message.
Decisions & LoopsIf handedOver is noIf handedOver is no
Yes
ValuesSet customerTold to They were asked to try again a little later..Set customerTold to They were asked to try again a little later..
Decisions & LoopsIf a step below fails, save the error as fallbackErrorIf a step below fails, save the error as fallbackError
Try
TelegramTelegramSend a message to chat chatId.Send a message to chat chatId.Support assistant Thanks for writing in. I have not been able to answer this one myself, and I could not reach the businessName team just now, so please try again a little later. Nothing has been changed on your account.
On error
TextBuild the text They could not be sent a reply either (@fallbackError.message). and save it as customerTold.Build the text They could not be sent a reply either (@fallbackError.message). and save it as customerTold.
Decisions & LoopsStop and report a problem: Could not pass a support message on to the 'humanChatId' chat (handoverProblem), so nobody has been told about it. Check that 'humanChatId' is right and that the person taking handovers has opened your bot in Telegram and pressed Start. The customer (askedBy, chat ID chatId) wrote: customerMessageStop and report a problem: Could not pass a support message on to the 'humanChatId' chat (handoverProblem), so nobody has been told about it. Check that 'humanChatId' is right and that the person taking handovers has opened your bot in Telegram and pressed Start. The customer (askedBy, chat ID chatId) wrote: customerMessage customerTold.
No
No steps
TextBuild the text Support assistant Thanks for writing in. I have not been able to answer this one myself, so I have passed it to the @businessName team and someone will get bac... and save it as holdingReply.Build the text Support assistant Thanks for writing in. I have not been able to answer this one myself, so I have passed it to the @businessName team and someone will get bac... and save it as holdingReply.
TelegramTelegramSend a message to chat chatId.Send a message to chat chatId.holdingReply
Decisions & LoopsFinish the run: The person taking handovers was notified first, then the customer was told someone will get back to them. Nothing was marked resolved.Finish the run: The person taking handovers was notified first, then the customer was told someone will get back to them. Nothing was marked resolved.
No
ValuesSet answerReply to Support assistantSet answerReply to Support assistant draftReply truncated to 3200 characters using ... as the ellipsis (keeping words whole) If that did not answer it, reply here and a person will pick it up.
TelegramTelegramSend a message to chat chatId.Send a message to chat chatId.answerReply
Decisions & LoopsFinish the run: The question was answered from your support material. It is still open until the customer says otherwise.Finish the run: The question was answered from your support material. It is still open until the customer says otherwise.