Postak
Turn a Telegram channel into a personal AI chat list.
Start a chat with /new. Each post becomes a conversation title; its comment thread is the chat. Postak replies as you type and names the post after the first reply.
Features
- Channel as chat list — each
/newpost becomes an auto-titled conversation. - Rich streaming replies — rich Telegram messages: tables, checklists, ...
- Per-thread memory — each conversation keeps its own context.
- multi-channel support · Custom prompts · Commenter mentions · Scoped access · Thread tools · Pluggable models and storage
How it works
- Send
/newin your channel — or in its discussion group — to start a conversation. - Telegram forwards the post into its discussion group as a comment thread.
- Reply in the thread — Postak answers, streaming as it types.
- The first reply auto-titles the post, so your feed reads like a chat list.
Requirements
- Python 3.10+
- A Telegram bot (@BotFather) and a channel with a linked discussion group
- An OpenAI-compatible LLM endpoint
Start in five minutes
- In Telegram, create a channel and enable comments by linking a discussion group. Add your bot as an admin of both.
- Configure and run:
uv sync
cp .env.example .env # fill in BOT_TOKEN, TARGET_CHANNEL_ID, LLM_MODEL, …
uv run postak
# or, from PyPI:
# pip install postak
# postak # reads .env from the current directory
- Send
/newin your channel or discussion group, then reply in the new thread.
Configuration
Postak reads settings from the environment (via a .env file):
| Variable | Required | Default | Description |
|---|---|---|---|
BOT_TOKEN |
✔ | — | Telegram bot token from @BotFather |
TARGET_CHANNEL_ID |
— | Channel id(s) to serve, comma-separated (e.g. -1001234567890,-1009876543210). Leave empty and a Postak admin can add channels later — see Admin commands |
|
LLM_MODEL |
✔ | — | Model name, e.g. gpt-4o-mini |
LLM_ENDPOINT |
OpenAI API | Base URL of an OpenAI-compatible endpoint | |
LLM_API_KEY |
not-needed |
API key for the LLM endpoint | |
POSTAK_ADMINS |
— | Comma-separated Telegram user ids who may manage Postak. Required if TARGET_CHANNEL_ID is empty, since that's the only way to add a channel |
|
DATABASE_URL |
sqlite+aiosqlite:///postak.db |
Store URL: a SQLite path, or :memory: |
|
HISTORY_WINDOW |
20 |
Max recent messages kept as context (the system prompt is always kept) |
Library usage
from aiogram import Bot, Dispatcher
from postak import OpenAIGenerator, Postak
postak = Postak(
generator=OpenAIGenerator(model="gpt-4o-mini", api_key="..."),
store="sqlite+aiosqlite:///postak.db",
channels=[-1001234567890],
admins=[123456789],
)
bot = Bot("telegram-token")
dp = Dispatcher()
postak.attach(dp)
dp.run_polling(bot)
Admin commands
Postak admins manage everything with /postak (/postak help lists it all):
Access
admin list— show admins ·admin add|remove <user_id>— grant or revoke rightsaccess list— show all access rulesaccess allow|revoke <user_id> global|group|thread— per-user accessaccess public on|off global|group|thread— open or close a scope to everyone; a public/allowed group (or global scope) also lets non-admins run/newin an already-linked group, not just comment
Channels
add [chat_id]— link a channel, discovering its discussion group via Telegram; defaults to the chat you're in, or pass either side's idremove [chat_id]— unlink it and drop that group's access rules
A Postak admin can skip add entirely: sending /new in a group Postak doesn't know yet links its channel and starts the conversation in one step.
In a thread
digest— summarize the conversationcompress— replace history with a compact summarytitle— regenerate the post title ·settitle <text>— set it yourselfregenerate— redo the last answerdelete— delete the message you replied to
Model
model get— show the current model ·model set <model>— switch it
System prompt — targets the surrounding thread when run inside one, else the global default
sysprompt— show it ·sysprompt <text>— set it ·sysprompt delete— reset it- The global prompt applies to conversations opened after the change and is admin-only; a thread's prompt takes effect on its next reply and can also be managed by anyone allowed to chat in that thread
Development
uv sync
uv run python -m unittest discover -s tests
uv run ruff check .
uv run mypy postak
License
Metadata
Release files for postak 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| postak-0.1.0.tar.gz | 36.7 kB | Without provenance | Details for postak-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| postak-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for postak-0.1.0-py3-none-any.whl |
Total release size: 69.7 kB
Release files / postak-0.1.0.tar.gz
| Download URL | postak-0.1.0.tar.gz |
|---|---|
| Size | 36.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ec93cf804770c9c3b9fbd64b4b27da2c4d106c5912f4fe3be3b0530dd983dd3b
|
|
BLAKE2b-256 checksum How to use checksums |
c97d36f72d45a3d4eed08f104f0028fae4f0c4ad3fb000f5bce8a70b15225cd8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Release files / postak-0.1.0-py3-none-any.whl
| Download URL | postak-0.1.0-py3-none-any.whl |
|---|---|
| Size | 33.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fa0db1c08c585dea079bc3522a4d6c63d253313f7e1c37b05b762f171dc146b8
|
|
BLAKE2b-256 checksum How to use checksums |
0849afddde31717e1e233e05611dc883c8c2492f66fc7a6005aa266eed1f477b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Security for postak 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.