Self-hosted Telegram-first AI assistant with async tooling, memory, and scheduling.
Project description
MiniBot 🤖
Your personal AI assistant for Telegram - self-hosted, auditable, and intentionally opinionated.
Overview
MiniBot is a lightweight personal AI assistant you run on your own infrastructure. It is built for people who want reliable automation and chat assistance without a giant platform footprint.
The project is intentionally opinionated: Telegram-first, SQLite-first, async-first. You get a focused, production-practical bot with clear boundaries, predictable behavior, and enough tools to be useful daily.
Quickstart
poetry installcp config.example.toml config.toml- Populate secrets in
config.toml(bot token, allowed chat IDs, provider key). poetry run minibot
Up & Running with Telegram
- Launch Telegram
@BotFatherand create a bot to obtain a token. - Update
config.toml:- set
channels.telegram.bot_token - populate
allowed_chat_idsorallowed_user_idswith your ID numbers - configure the LLM provider section (
provider,api_key,model)
- set
- Run
poetry run minibotand send a message to your bot. Expect a simple synchronous reply (LLM, memory backed). - Monitor
logs(Logfmt vialogfmter) andhtmlcov/index.htmlfor coverage during dev.
Top features
- 🤖 Personal assistant, not SaaS: your chats, memory, and scheduled prompts stay in your instance.
- 🎯 Opinionated by design: Telegram-centric flow, small tool surface, and explicit config over hidden magic.
- 🏠 Self-hostable: Dockerfile + docker-compose provided for easy local deployment.
- 💬 Telegram channel with chat/user allowlists and long-polling or webhook modes; accepts text, images, and file uploads (multimodal inputs when enabled).
- 🧠 Focused provider support (via llm-async): currently
openai,openai_responses, andopenrouteronly. - 🖼️ Multimodal support: media inputs (images/documents) are supported with
llm.provider = "openai_responses","openai", and"openrouter".openai_responsesuses Responses API content types;openai/openrouteruse Chat Completions content types. - 🧰 Small, configurable tools: chat memory, KV notes, HTTP fetch, calculator, current_datetime, and optional Python execution.
- 🌐 Optional browser automation with Playwright (
browser_navigate,browser_info,browser_get_data,browser_wait_for,browser_click,browser_query_selector,browser_close). - ⏰ Scheduled prompts (one-shot and interval recurrence) persisted in SQLite.
- 📊 Structured logfmt logs, request correlation IDs, and a focused test suite (
pytest+pytest-asyncio).
Why self-host
- Privacy & ownership: all transcripts, KV notes, and scheduled prompts are stored in your instance (SQLite files), not a third-party service.
- Cost & provider control: pick where to route LLM calls and manage API usage independently.
- Network & runtime control: deploy behind your firewall, restrict outbound access, and run the daemon as an unprivileged user.
Configuration Reference
Use config.example.toml as the source of truth—copy it to config.toml and update secrets before launching. Key sections:
-
Byte-size fields accept raw integers or quoted size strings; SI units are preferred in examples (for example
"16KB","5MB","2GB"). IEC units are also accepted (for example"16KiB","5MiB"). -
[runtime]: global flags such as log level and environment. -
[channels.telegram]: enables the Telegram adapter, provides the bot token, and lets you whitelist chats/users plus set polling/webhook mode. -
[llm]: configures the chosen llm-async provider (currentlyopenai,openai_responses, oropenrouter), plus API key, model, optional temperature/token/reasoning params,max_tool_iterations, and system prompt. Request params are only sent when present inconfig.toml(omit keys liketemperature,max_new_tokens, orreasoning_effortto avoid sending them). For OpenRouter, optionalllm.openrouter.modelslets you provide a fallback model pool,llm.openrouter.providerlets you send routing controls (order,allow_fallbacks,only,ignore,sort, throughput/latency preferences,max_price, andprovider_extrafor future keys), andllm.openrouter.pluginslets you pass request plugins (for examplefile-parserPDF engine selection). -
[memory]: conversation history backend (default SQLite). TheSQLAlchemyMemoryBackendstores session exchanges soLLMMessageHandlercan build context windows.max_history_messagesoptionally enables automatic trimming of old transcript messages after each user/assistant append; when unset, transcript retention is unlimited. -
[scheduler.prompts]: configures delayed prompt execution storage/polling and recurrence safety (min_recurrence_interval_secondsguards interval jobs). -
[tools.kv_memory]: optional key/value store powering the KV tools. It has its own database URL, pool/echo tuning, and pagination defaults. Enable it only when you need tool-based memory storage. -
[tools.http_client]: toggles the HTTP client tool. Configure timeout +max_bytes(raw byte cap), optionalmax_chars(LLM-facing char cap), andresponse_processing_mode(auto/none) for response shaping via aiosonic. -
[tools.playwright]: enables browser automation with Playwright. Configurebrowser(chromium,firefox,webkit), Chromiumlaunch_channel(for examplechrome) and optionalchromium_executable_path, launch args, browser fingerprint/context defaults (UA, viewport, locale, timezone, geolocation, headers), output caps, session TTL, and egress restrictions (allowed_domains,allow_http,block_private_networks). Browser outputs can be post-processed in Python before reaching the LLM (postprocess_outputs, enabled by default), with optional raw snapshot exposure (postprocess_expose_raw) and a snapshot cache TTL (postprocess_snapshot_ttl_seconds). Post-processed text is emitted as compact Markdown with links preserved. -
[tools.calculator]: controls the built-in arithmetic calculator tool (enabled by default) with Decimal precision, expression length limits, and exponent guardrails. -
[tools.python_exec]: configures host Python execution with interpreter selection (python_path/venv_path), timeout/output/code caps, environment policy, and optional pseudo-sandbox modes (none,basic,rlimit,cgroup,jail). -
[logging]: structured log flags (logfmt, separators) consumed byadapters/logging/setup.py.
Every section has comments + defaults in config.example.toml—read that file for hints.
Scheduler Guide
Schedule by chatting naturally. MiniBot understands reminders for one-time and recurring prompts, and keeps jobs persisted in SQLite so they survive restarts.
Use plain prompts like:
- "Remind me in 30 minutes to check my email."
- "At 7:00 AM tomorrow, ask me for my daily priorities."
- "Every day at 9 AM, remind me to send standup."
- "List my active reminders."
- "Cancel the standup reminder."
Notes:
-
One-time and recurring reminders are supported.
-
Recurrence minimum interval is
scheduler.prompts.min_recurrence_interval_seconds(default60). -
Configure scheduler storage/polling under
[scheduler.prompts]inconfig.toml. -
Typical flow: ask for a reminder in plain language, then ask to list/cancel it later if needed.
Security & sandboxing
MiniBot intentionally exposes a very limited surface of server-side tools. The most sensitive capability is
python_execute, which can run arbitrary Python code on the host if enabled. Treat it as a powerful but
potentially dangerous tool and follow these recommendations:
- Disable
tools.python_execunless you need it; toggle it viaconfig.example.toml. - Prefer non-host execution or explicit isolation when executing untrusted code (
sandbox_modeoptions includerlimit,cgroup, andjail). - If using
jailmode, configuretools.python_exec.jail.command_prefixto wrap execution with a tool like Firejail and restrict filesystem/network access. - Run the daemon as a non-privileged user, mount only required volumes (data directory) and avoid exposing sensitive host paths to the container.
Example jail command prefix (set in config.toml):
[tools.python_exec.jail]
enabled = true
command_prefix = ["firejail", "--private=/srv/minibot-sandbox", "--net=none", "--quiet"]
Note: ensure the wrapper binary (e.g. firejail) is available in your runtime image or host. The Dockerfile in this repo installs firejail by default for convenience; review its flags carefully before use.
Stage 1 targets:
- Telegram-only channel with inbound/outbound DTO validation via
pydantic. - SQLite/SQLAlchemy-backed conversation memory for context/history.
- Structured
logfmterlogs with request correlation and event bus-based dispatcher. - Pytest + pytest-asyncio tests for config, event bus, memory, and handler plumbing.
Mini Hex Architecture
MiniBot follows a lightweight hexagonal layout described in detail in ARCHITECTURE.md. The repository root keeps
minibot/ split into:
core/– Domain entities and protocols (channel DTOs, memory contracts, future job models).app/– Application services such as the daemon, dispatcher, handlers, and event bus that orchestrate domain + adapters.adapters/– Infrastructure edges (config, messaging, logging, memory, scheduler persistence) wired through the DI container.llm/– Thin wrappers around llm-async providers plusllm/tools/, which defines tool schemas/handlers that expose bot capabilities (KV memory, scheduler controls, utilities) to the model.shared/– Cross-cutting utilities.
Tests under tests/ mirror this structure so every layer has a corresponding suite. This “mini hex” keeps the domain
pure while letting adapters evolve independently.
Incoming Message Flow
flowchart TD
subgraph TCHAN[Telegram channel]
TG[Telegram Update]
AD[Telegram Adapter]
SEND[Telegram sendMessage]
end
TG --> AD
AD --> EV[EventBus MessageEvent]
EV --> DP[Dispatcher]
DP --> HD[LLMMessageHandler]
HD --> MEM[(Memory Backend)]
HD --> LLM[LLM Client + Tools]
LLM --> HD
HD --> RESP[ChannelResponse]
RESP --> DEC{should_reply?}
DEC -- yes --> OUT[EventBus OutboundEvent]
OUT --> AD
AD --> SEND[Telegram sendMessage]
DEC -- no --> SKIP[No outbound message]
Playwright (optional)
Use Playwright when you want browser navigation and extraction tools (browser_*).
Setup:
poetry install --extras playwrightpoetry run playwright install chromium- Linux only:
poetry run playwright install-deps chromium
playwright extra installs all browser-tool runtime deps: playwright, selectolax, and markdownify.
If you install packages manually, install all three.
Quick local config:
[tools.playwright]
enabled = true
Safer production baseline:
[tools.playwright]
enabled = true
browser = "chromium"
headless = true
allow_http = false
block_private_networks = true
allowed_domains = ["example.com", "docs.example.com"]
Notes:
- Prefer
headless = trueon servers. - Keep
allowed_domainsnon-empty when possible. - If you use Debian system Chromium, set
launch_channel = ""and optionallychromium_executable_path = "/usr/bin/chromium".
Tooling
Tools live under minibot/llm/tools/ and are exposed to llm-async with server-side execution controls.
- 🧠
chat_history: inspect/trim chat transcript history for the current session. - 🧮
calculate_expression+ 🕒current_datetime: quick built-in utility tools. - 📝
kv_memory: save/get/search short notes. - 🌐
http_client: guarded HTTP/HTTPS fetches via aiosonic. - ⏰
schedule_prompt,list_scheduled_prompts,cancel_scheduled_prompt,delete_scheduled_prompt: one-time and recurring reminder scheduling. - 🐍
python_execute+python_environment_info: optional host Python execution and runtime/package inspection. - 🧭
browser_*(optional): Playwright navigation and extraction with domain/network guardrails. - 🖼️ Telegram media inputs (
photo/document) are supported onopenai_responses,openai, andopenrouter.
Conversation context:
- Uses a rolling history window (
get_historydefault32messages), not full lifetime transcript. - In OpenAI Responses mode, turns are rebuilt from stored history (no
previous_response_idreuse).
Roadmap / Todos
- Add more channels: WhatsApp, Discord — implement adapters under
adapters/messaging/<channel>reusing the event bus and dispatcher. - Minimal web UI for analytics & debug — a small FastAPI control plane + lightweight SPA to inspect events, scheduled prompts, and recent logs.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file minibot-0.0.1.tar.gz.
File metadata
- Download URL: minibot-0.0.1.tar.gz
- Upload date:
- Size: 60.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e0ca689523b44b74cea8557e13b422a92b53761a21a0b7704dcda69953e6279
|
|
| MD5 |
d37c0b7324bdabf0fc9f846e87e1243b
|
|
| BLAKE2b-256 |
9eff5a2a7d65a8c3075dc675777b0a1fc5e3f5eb4ce0ad96c231b02f25abfd4b
|
File details
Details for the file minibot-0.0.1-py3-none-any.whl.
File metadata
- Download URL: minibot-0.0.1-py3-none-any.whl
- Upload date:
- Size: 70.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc9d6c0b6b5af1f59a76eca074c3d923498c6e00d30491d90b9fa2142dd6065b
|
|
| MD5 |
c0b1b19689f4dab30869a87f486c9848
|
|
| BLAKE2b-256 |
546e71a01eb726ac32241454fda3cd71f4783f2881c65c9d5cea550d1937e0c5
|