-
-
Notifications
You must be signed in to change notification settings - Fork 202
Configuration
All settings are defined in config/config.yaml. Copy config/config-sample.yaml to config/config.yaml before editing. The file is read once at startup — restart the bot after changing it. Every setting except bot_token, staffchat_id and owner_id has a default.
| Setting | Type | Default | Description |
|---|---|---|---|
bot_token |
string | (required) | Telegram Bot API token from @BotFather (e.g., 123456789:AbCdeFghIjKlMnOpQrStUvWxYz) |
staffchat_id |
string | (required) | Supergroup chat ID where staff receive tickets (negative number, e.g., -1001234567890) |
owner_id |
string | (required) | Your Telegram user ID — the bot owner who has admin privileges |
staffchat_type |
enum | 'telegram' |
Staff communication platform: 'telegram' or 'signal' (Slack/Discord addons cannot be the staff chat yet) |
staffchat_parse_mode |
enum | 'MarkdownV2' |
Formatting mode for messages sent to staff chat: 'MarkdownV2', 'Markdown', 'HTML', or 'plaintext'
|
mongodb_uri |
string | mongodb://mongodb:27017/support |
MongoDB connection URI for ticket storage. The Docker Compose stack passes it via the MONGO_URI environment variable; set it in the config for external databases. |
| Setting | Type | Default | Description |
|---|---|---|---|
spam_time |
integer (ms) |
300000 (5 min) |
Time window during which the message limit applies. Set to 0 to disable spam protection entirely. |
spam_cant_msg |
integer | 5 |
Number of messages allowed within the spam_time window before rate limiting kicks in |
Example: With defaults, a user can send up to 5 messages per 5 minutes. The 6th message triggers a spam warning and blocks further forwarding until the window resets.
| Setting | Type | Default | Description |
|---|---|---|---|
allow_private |
boolean | false |
Enables "Reply in private" button on user messages in staff chat — opens a 1-on-1 private tunnel between the staff member and the user. An "End Private Chat" button closes it. |
direct_reply |
boolean | false |
Requires allow_private: true. Instead of creating a relay tunnel, forwards the staff member directly to the user's Telegram profile for direct messaging. |
auto_close_tickets |
boolean | true |
Automatically closes a ticket after the first staff reply. A closed ticket cannot receive further replies unless reopened with /reopen. |
anonymous_tickets |
boolean | true |
Hides the user's Telegram ID from tickets in the staff chat for privacy. |
anonymous_replies |
boolean | true |
Hides the staff member's name from responses sent back to users — replies appear as coming from the bot directly. |
| Setting | Type | Default | Description |
|---|---|---|---|
show_auto_replied |
boolean | false |
Forwards auto-replied messages (from autoreply rules or LLM) to the staff chat for visibility. Automatically enabled when use_llm: true. |
show_user_ticket |
boolean | false |
Displays the ticket ID in bot responses sent back to users, so they can reference it in follow-up conversations. |
autoreply_confirmation |
boolean | true |
Sends the language.confirmationMessage acknowledgment on each incoming user message before it's forwarded to staff. |
clean_replies |
boolean | false |
Removes staff attribution signatures from forwarded replies — messages appear without "from [staff name]" header/footer. |
pass_start |
boolean | false |
Forwards the /start command message to the staff chat instead of handling it automatically with the welcome message. Useful for custom onboarding flows. |
parse_mode |
enum | 'Markdown' |
Formatting mode for bot responses sent to end users: 'Markdown', 'MarkdownV2', or 'HTML'. See Markdown for syntax reference. |
| Setting | Type | Default | Description |
|---|---|---|---|
log_level |
enum | 'NONE' |
Mirrors console output to config/debug.log: 'NONE' (no file), 'ERROR' (errors only), or 'INFO' (everything) |
dev_mode |
boolean | true |
Shows a "Dev mode is on" notice with every bot message, alerting users that the bot may experience delays or errors. Disable in production. |
All user-facing messages are customizable under the language: section. See Commands for which strings correspond to which commands.
| Key | Used In | Description |
|---|---|---|
startCommandText |
/start command response |
Welcome message shown when user first interacts with bot |
faqCommandText |
/faq command response |
FAQ content displayed to users |
helpCommandText |
/help (user) |
Help text for end users |
helpCommandStaffText |
/help (staff in group) |
Extended help text with staff commands listed |
confirmationMessage |
After first user message | Acknowledgment sent to user after ticket is created (gated by autoreply_confirmation). The legacy key contactMessage is used as fallback. |
blockedSpam |
Spam rate limit triggered | Warning shown when user exceeds spam threshold |
ticket |
Ticket prefix | Label used in ticket messages (e.g., "Ticket #123") |
closed |
Closed ticket label | Status text appended to closed tickets |
acceptedBy |
Staff reply attribution | Text like "was accepted by [staff name]" on forwarded replies |
dear |
Reply salutation prefix | Greeting prepended to staff replies (e.g., "Hi") |
regards |
Reply sign-off | Closing appended to staff replies (e.g., "Regards,") |
from |
Attribution label | Label in "from [staff name]" attribution on forwarded messages |
language |
Language selector | Label for language selection interface |
msg_sent |
System notification | Confirmation when a message is sent to user |
file_sent |
System notification | Confirmation when a file is sent to user |
usr_with_ticket |
Context label | Text identifying the user associated with a ticket |
banned |
Ban notification | Status text shown when a user is banned |
replyPrivate |
Button label | Text on "Reply in private" button (requires allow_private) |
services |
Category intro | Message before category selection list |
customer |
User reference | Label used for customer/user references |
msgForwarding |
Forward notification | Info message when messages are forwarded to a group |
back |
Navigation button | Text on "Go back" navigation buttons in category flow |
whatSubCategory |
Subcategory prompt | Question shown before subcategory selection |
prvChatEnded |
Private chat close | Notification that private chat has ended |
prvChatOpened |
Private chat open (staff) | Notification to staff member when private chat opens |
prvChatEnd |
End button label | Text on "End Private Chat" button |
prvChatOpenedCustomer |
Private chat open (user) | Notification to user when private chat is opened by staff |
instructionsSent |
Instructions forwarded | Confirmation that instructions were sent in private chat |
openTickets |
/open command header | Title text for the /open tickets list |
support |
General label | Support department name used in various contexts |
prvChatOnly |
Error message | Shown when a private-chat-only command is used elsewhere |
ticketClosed |
Close notification | Message to user when staff closes their ticket |
links |
Direct links header | Title for direct support links section |
textFirst |
File warning | Prompt asking users to send text before images |
ticketClosedError |
Reply error | Shown when trying to reply to a closed ticket |
automatedReply |
Auto-reply label | Label on automated/canned responses |
automatedReplyAuthor |
Auto-reply signature | Author attribution on auto-replied messages |
doesntHelp |
Feedback button | "This does not help" feedback option on auto-replies |
automatedReplySent |
Staff notification | Confirmation to staff when an automated reply was sent |
ticketReopened |
Reopen confirmation | Notification when a ticket is reopened with /reopen
|
regardsGroup |
Group sign-off | Department/group name in reply sign-offs |
| Key | Used In | Description |
|---|---|---|
csatRatingRequest |
CSAT survey prompt | Question shown to user after ticket close (e.g., "How would you rate your support experience?") |
csatThankYou |
CSAT thank-you message | Shown after user submits a rating |
triagePriority |
Auto-triage label | Label for AI-generated priority classification |
triageSummary |
Auto-triage label | Label for AI-generated ticket summary |
sentimentAlert |
Sentiment alert | Warning text when customer sentiment drops below threshold (e.g., "🚨 Frustrated customer detected") |
ticketAssignedTo |
Assignment notification | Text shown when a ticket is assigned to a staff member |
ticketUnassigned |
Unassignment notification | Text shown when assignment is removed |
assignedBy |
Attribution label | Label showing who performed the assignment |
internalNote |
Internal note header | Header text for internal notes visible only to staff |
noteAddedBy |
Note attribution | Label showing which staff member added a note |
offlineMessage |
Business hours offline | Message shown when bot is outside business hours |
businessHoursClosed |
Hours notification | Detailed message about support being unavailable |
escalationNotify |
Escalation alert | Text prefix for auto-escalation notifications to supervisors |
All language strings support MarkdownV2 formatting.
Keyword-based canned responses. When a user message contains the question keyword (case-insensitive substring match), 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."Enable AI-powered responses using any LiteLLM-compatible proxy (supports OpenAI, Anthropic, Mistral, etc.):
| Setting | Type | Default | Description |
|---|---|---|---|
use_llm |
boolean | false |
Enable LLM-powered auto-replies. Automatically sets show_auto_replied: true. |
llm_api_key |
string | — | API key for the LLM provider or LiteLLM proxy |
llm_base_url |
string | — | Base URL of the LLM API endpoint (e.g., https://api.openai.com/v1) |
llm_model |
string | — | Model identifier (e.g., gpt-4o, mistralai/ministral-3b, claude-3-haiku) |
llm_knowledge |
string | (empty) | Knowledge base injected as context for AI responses. Required for auto-replies — the model only answers from it and stays silent otherwise (a warning is logged at startup when it is empty). |
| Setting | Type | Default | Description |
|---|---|---|---|
llm_memory_depth |
integer | 10 |
Number of recent messages of the ticket to include as conversation history for context-aware responses. Set to 0 to disable memory and use only the current message. |
auto_triage |
boolean | false |
Automatically classify incoming tickets using AI: assigns category, priority level (low, normal, high, urgent), and generates a one-line summary. Results appear as metadata on the ticket in staff chat. |
sentiment_alert_threshold |
integer (1-5) | 2 |
When auto_triage is enabled, sends an alert to staff chat if the customer's sentiment score falls at or below this value. Lower = more negative. |
staff_assist |
boolean | false |
Reserved — the draft generator exists but is not wired to a command yet; the setting currently has no effect. |
translate_enabled |
boolean | false |
Translates staff replies to translate_target_language via the LLM before sending them to the user. Incoming user messages are forwarded unchanged. |
translate_target_language |
string (ISO code) | 'en' |
Target language for translated staff replies (e.g., 'de', 'fr', 'ja'). |
Route tickets from different user topics to specific staff groups. See Categories for full documentation and examples.
categories:
- name: "Technical Support"
group_id: "-1009876543210"
- name: "Sales"
subgroups:
- name: "Enterprise"
group_id: "-1001112223334"
- name: "Small Business"
group_id: "-1005556667778"
- name: "Other issues"
tag: "#other" # Auto-tag tickets in this category
msg: "Please describe your issue..."
group_id: "-1003334445556"Define staff roles, enable CSAT surveys, and schedule daily analytics summaries.
| Setting | Type | Default | Description |
|---|---|---|---|
enable_csat |
boolean | false |
Send a star-rating survey (1-5 stars) to users when their ticket is closed. Ratings are tracked for analytics. |
daily_summary_time |
string (HH:MM UTC) | '09:00' |
Time (UTC) to automatically send an analytics summary to the staff chat, including ticket counts, average response/resolution time, and CSAT score. Set to an empty string ('') to disable. |
staff_roles |
array | [] |
List of staff members with assigned roles. See below for format. |
staff_roles:
- telegram_id: "123456789"
role: "admin" # admin, supervisor, or agent
name: "John Doe"
- telegram_id: "987654321"
role: "supervisor"
name: "Jane Smith"| Role | Effect |
|---|---|
admin |
Full access to all staff commands |
supervisor |
Same as admin for ticket commands; receives notify_supervisor escalation alerts |
agent |
Handles tickets, uses canned responses and notes |
Staff not listed in staff_roles still act as regular group admins; roles mainly matter for escalation notifications and /staff.
Send event-driven notifications to external URLs. Useful for integrating with monitoring tools, dashboards, or custom automation systems.
webhooks:
- url: "https://example.com/webhook"
events: ["ticket.created", "ticket.closed"]
secret: "whsec_your-secret-here" # Optional — enables HMAC verification| Event | Triggered When |
|---|---|
ticket.created |
A new ticket is created (first user message) |
ticket.replied |
Staff replies to a ticket |
ticket.closed |
A ticket is closed by staff or auto-closed |
ticket.banned |
A user is banned from the bot |
csat.rated |
A user submits a CSAT rating after ticket close |
ticket.escalated |
A ticket is auto-escalated due to inactivity rules |
When a secret is configured, each webhook request includes an X-TSB-Signature header containing a SHA256 HMAC of the request body. Verify this signature on your end to confirm authenticity:
HMAC_SHA256(body, secret) → X-TSB-Signature header value
Mirror tickets to a Slack channel so staff can handle support from Slack instead of (or alongside) Telegram.
| Setting | Type | Default | Description |
|---|---|---|---|
slack_enabled |
boolean | false |
Enable Slack integration for ticket mirroring |
slack_bot_token |
string | — | Slack bot token (xoxb-...) from your Slack app |
slack_channel_id |
string | — | Slack channel ID (e.g., C012ABC3DEF or #general) |
The addon connects over Slack's RTM API and registers the bot's command handlers in that channel. It is experimental: staffchat_type: slack is not supported yet, so the staff chat stays on Telegram or Signal.
Mirror tickets to a Discord text channel using a Discord bot.
| Setting | Type | Default | Description |
|---|---|---|---|
discord_enabled |
boolean | false |
Enable Discord integration for ticket mirroring |
discord_bot_token |
string | — | Discord bot token from the Developer Portal |
discord_channel_id |
string | — | Discord text channel ID (numeric, e.g., 123456789012345678) |
The addon connects over the Discord gateway (needs the Message Content intent) and registers the bot's command handlers in that channel. It is experimental: staffchat_type: discord is not supported yet.
api_enabled / api_token appear in config-sample.yaml but the REST API is not implemented yet — the settings are reserved and currently ignored. Use webhooks for integrations.
Use Signal as the staff communication platform instead of Telegram. See Addons → Signal for setup details.
| Setting | Type | Default | Description |
|---|---|---|---|
signal_enabled |
boolean | false |
Enable Signal integration |
signal_number |
string | — | Phone number for the Signal account used by staff (e.g., "+1234567890") |
signal_host |
string | "localhost:40153" |
Host and port of the signal-cli REST API (Compose maps the container to 127.0.0.1:40153; inside the stack signal-cli:8080 also works) |
Embed a web chat widget on your website. See Addons → Web Chat for details.
| Setting | Type | Default | Description |
|---|---|---|---|
web_server |
boolean | false |
Enable the built-in web chat HTTP server and widget (/chat.js) |
web_server_port |
integer | 8080 |
Port the web server listens on |
web_server_ssl_cert |
string | — | Path to SSL certificate file for HTTPS (e.g., "../src/web/ssl.crt") |
web_server_ssl_key |
string | — | Path to SSL private key file for HTTPS (e.g., "../src/web/ssl.key") |
The web_chat.business_hours block applies to every channel: outside the window users get language.businessHoursClosed (or offline_message) and nothing is forwarded to staff.
web_chat:
business_hours:
enabled: true
start: "09:00"
end: "18:00" # overnight windows (e.g. 22:00-06:00) are supported
timezone: "Europe/Berlin" # IANA timezone, default UTC
offline_message: "" # optional override for language.businessHoursClosedThe remaining
web_chatkeys in the sample (enabled,greeting,primary_color,logo_url,position,pre_chat_form) are reserved for a future widget and are currently ignored — useweb_server: trueto enable the widget.
Pre-written reply templates. Staff list them with /templates and send one by replying to a ticket with /<key> (e.g. /shipping). Keys must be single words.
canned_responses:
- key: "shipping"
text: "Your order should arrive within 3-5 business days."
- key: "refund"
text: "We process refunds within 14 days. A team member will reach out shortly."
- key: "password_reset"
text: "Go to Settings > Account and click 'Reset Password'. Check your email for the reset link."Automatically escalate tickets that go unanswered beyond a time threshold.
escalation_rules:
- after_hours: 4 # Hours of inactivity before escalation triggers
action: "notify_supervisor" # Action: "notify_supervisor" or "tag_urgent"Rules are evaluated every 30 minutes for open tickets that are not assigned and are older than after_hours hours.
| Action | Effect |
|---|---|
notify_supervisor |
Sends language.escalationNotify with the ticket id to every staff member with role supervisor (via staffchat_type) and records a ticket.escalated event |
tag_urgent |
Sets the ticket priority to urgent and adds the tag auto-escalated
|
auto_close_after_days: 7 # Close tickets with no activity for N days (0 = disabled)Checked every 30 minutes together with the escalation rules. This is separate from auto_close_tickets (which closes after the first reply); it targets stale tickets that were never resolved.
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