-
-
Notifications
You must be signed in to change notification settings - Fork 202
Autoreply and AI
The bot supports two auto-reply mechanisms: keyword-based canned responses (built-in) and AI-powered replies via LLM (optional). Both can be used simultaneously — keyword rules are checked first, and the LLM handles messages that don't match any rule. On top of that, the LLM can triage tickets, remember conversations and translate staff replies.
Define question-answer pairs in config.yaml. When a user message contains the question text as a substring, the answer is sent automatically. First matching rule wins.
autoreply:
- question: "install"
answer: "You can install using our [Getting Started guide](https://github.com/bostrot/telegram-support-bot/wiki/Getting-started)"
- question: "refund policy"
answer: "We offer full refunds within 30 days of purchase."
- question: "hours"
answer: "Our support team is available Monday-Friday, 9am-5pm CET."| User Message | Matches Rule | Reason |
|---|---|---|
| "How do I install?" | question: "install" |
Substring match |
| "What's your refund policy?" | question: "refund policy" |
Substring match |
| "Do you offer refunds?" | no match | "refund policy" does not appear as a whole |
| "Installation help please" | question: "install" |
Matches substring "install" |
Matching is a plain includes() — write the question in the casing users are likely to type, or add several rules.
When an auto-reply is sent, the following occurs based on your settings:
- If
show_auto_replied: true, the ticket is still forwarded to the staff chat, marked withlanguage.automatedReplySent - The user sees the reply with a signature from
language.automatedReplyAuthor(default: "BottyBot") - Users can provide feedback via the
doesntHelp("This does not help") button on auto-replies
Auto-reply answers support Markdown formatting. Use \n for line breaks within YAML strings:
autoreply:
- question: "pricing"
answer: "*Plans:* \n- Basic: $9/mo \n- Pro: $19/mo \n- Enterprise: Contact us"Enable AI-generated responses using OpenAI or any OpenAI-compatible endpoint (LiteLLM, Ollama, vLLM, …). The bot sends the user's message along with your knowledge base to the LLM, which answers only from that knowledge base.
use_llm: true # Enable LLM auto-replies
llm_api_key: 'sk-your-api-key-here' # API key for your provider
llm_base_url: 'https://api.openai.com/v1' # LiteLLM proxy or direct API endpoint
llm_model: 'gpt-4o-mini' # Model identifier
llm_knowledge: | # Custom knowledge base (multi-line string)
Company ABC provides cloud hosting services.
Pricing tiers:
- Starter: $5/mo, 10GB storage, shared resources
- Business: $20/mo, 100GB storage, dedicated CPU
- Enterprise: Custom pricing
Support hours: Mon-Fri 9am-6pm CET.
Refund policy: Full refund within first 14 days. No refunds after that.| Setting | Type | Default | Description |
|---|---|---|---|
use_llm |
boolean | false |
Enable/disable LLM auto-replies. Automatically sets show_auto_replied: true. |
llm_api_key |
string | — | API key for the LLM provider or proxy |
llm_base_url |
string | — | Base URL of the OpenAI-compatible endpoint |
llm_model |
string | — | Model name (e.g., gpt-4o-mini, qwen/qwen3.6-35b-a3b, claude-3-haiku via LiteLLM) |
llm_knowledge |
string | (empty) | Knowledge base injected as context. Required — with an empty knowledge base the model is told to answer null and never replies (the bot logs a warning at startup). |
llm_memory_depth |
integer | 10 |
Previous messages of the same ticket sent along as conversation history (0 = disabled) |
- User sends a message that doesn't match any keyword autoreply rule
- Bot builds a prompt: system instructions +
llm_knowledge+ the lastllm_memory_depthmessages of the ticket + the new message - Sends the request to the configured endpoint
- If the model answers, the reply is sent to the user attributed as an automated reply; if it answers
null(question not covered), the bot logsLLM returned no answerand the message becomes a normal ticket
If the LLM request fails (network error, rate limit, invalid key) the error is logged (Error in LLM response: …) and the message falls through to normal ticket handling: it is forwarded to the staff chat as a regular ticket. The user won't see an error — they'll receive a human response instead.
LiteLLM allows you to use any LLM provider through a single OpenAI-compatible endpoint:
- Install and run LiteLLM proxy
- Configure it with your preferred providers (OpenAI, Anthropic, Mistral, local models, …)
- Point
llm_base_urlto your LiteLLM instance:
use_llm: true
llm_api_key: 'your-litellm-proxy-key'
llm_base_url: 'http://localhost:4000/v1' # Your LiteLLM proxy URL
llm_model: 'claude-3-haiku' # Any model your proxy routes to- Keep
llm_knowledgeconcise and well-structured — Q/A pairs or short sections work best - Include pricing, policies, common procedures, and product details
- The config is read at startup: restart the bot after editing the knowledge base
With auto_triage: true every new ticket is classified by the LLM before it reaches staff:
auto_triage: true
sentiment_alert_threshold: 2 # 1 = very angry … 5 = happyThe model returns a category (one of your configured categories, if any), a priority (low/normal/high/urgent), a one-line summary and a sentiment score. Priority and summary are prefixed to the ticket in the staff chat, the priority is stored on the ticket, and when the sentiment score is at or below sentiment_alert_threshold the language.sentimentAlert warning is added.
translate_enabled: true
translate_target_language: 'en'When enabled, staff replies are translated to translate_target_language by the LLM before they are sent to the user. Incoming user messages are forwarded unchanged.
staff_assist is present in config-sample.yaml and the code contains a draft generator, but it is not wired to any command yet — the setting currently has no effect.
When both are configured, the bot checks in this order:
- Keyword autoreply rules → if matched, send canned answer immediately
-
LLM auto-reply → if no keyword match and
use_llm: true, ask the model; it answers only when the knowledge base covers the question - Normal ticket → if neither applies (or the LLM fails), forward to the staff group as a regular ticket
This means you can use keyword rules for exact, policy-critical answers (refund terms, legal disclaimers) while letting the LLM handle open-ended questions.
Please tell me if something is missing in this guide or should be added — open an issue on GitHub.
Home · Getting Started · Configuration · Commands · Categories · Auto-reply and AI · Addons · Markdown · Troubleshooting · Upgrading