Feature #104 » README.md
Frappe Telegram AI
A Telegram bot that answers questions from your Frappe / ERPNext data.
Each person logs in with their own Frappe account, and the bot only shows what their Frappe role allows.
Telegram user
│ Frappe username + password (asked by the bot)
▼
Bot backend ── POST /api/method/login ──► Frappe checks the credentials
│ │
│◄──────────── session id (sid) ─────────┘
▼
sid encrypted and saved against the Telegram user id
│
▼
Question ──► AI picks Frappe lookups ──► Frappe REST API (as that user) ──► AI writes the answer
- Frappe decides every permission. There are no users, roles or permission lists in
config.yaml. - The password is used once for the login call and never stored. The password message is deleted from the chat.
- The Frappe session id is stored encrypted and is re-checked with Frappe every few minutes.
- The AI never receives passwords or session ids, only the data the user is allowed to see.
- Read-only: the bot cannot create, change, submit or delete records.
How roles and permissions work: docs/ACCESS_CONTROL.md
1. Install
Python 3.10 or newer.
python -m venv .venv
# Windows: .venv\Scripts\activate
# Linux/Mac: source .venv/bin/activate
pip install -r requirements.txt
2. Configure config/config.yaml
Every setting is in config/config.yaml (a clean copy is in config/config.example.yaml). Fill in:
| Setting | What to put |
|---|---|
telegram.bot_token |
Token from @BotFather in Telegram |
frappe.url |
Your site, e.g. https://erp.example.com
|
frappe.api.* |
Frappe REST endpoints. Defaults work for Frappe v14/v15; change only if needed |
ai.provider |
openrouter, openai, groq, gemini, ollama or custom
|
ai.api_key |
Your AI provider key (not needed for ollama) |
ai.model |
A model that supports tool calling, e.g. openai/gpt-4o-mini on OpenRouter |
ai.base_url |
Leave empty to use the provider default. Required for custom
|
security.encryption_key |
Run python main.py genkey and paste the output |
The other settings (limits, lockout, session check time) have sensible defaults and are explained in the file.
Check everything:
python main.py check
It checks the file, then tests Frappe, the Telegram token and the AI service.
3. Frappe side
- The REST API must be reachable from the machine running the bot.
- Each person needs a normal Frappe user with a password.
- Accounts with two-factor authentication cannot log in through the bot.
4. Start
python main.py
The bot uses long polling, so no public URL is needed.
5. Use
Open the bot in a private chat:
- Send
/start. The bot asks for your Frappe username, then your password. - Ask questions in normal language:
Show my last 5 sales ordersHow many open leads do we have?Total unpaid sales invoices this month by customerShow the details of SO-00045
Commands: /login (switch account), /logout, /me (your user and roles), /new (new conversation), /cancel, /help.
Project structure
frappe_telegram_ai/
├── main.py start / check / genkey
├── config/
│ ├── config.yaml your settings
│ └── config.example.yaml clean template
├── app/
│ ├── core/ settings loader, logging
│ ├── frappe/ Frappe REST client (runs as the logged-in user)
│ ├── auth/ Frappe login, session check, user roles
│ ├── storage/ encrypted session store (SQLite)
│ ├── security/ encryption, login lockout, rate limit
│ ├── ai/ OpenAI-compatible AI client
│ ├── agent/ AI tool loop, Frappe tools, query validation
│ ├── bot/ Telegram handlers and messages
│ └── runtime.py wires everything together
└── docs/
├── ACCESS_CONTROL.md
└── TROUBLESHOOTING.md
Local data: data/sessions.db (created on first start) holds the encrypted sessions.
Production notes
- Keep
config/config.yamlout of version control (already in.gitignore) and readable only by the bot's user. - Run the bot under a process manager (systemd, Supervisor, Docker).
- Run only one copy of the bot per token (Telegram allows one polling client).