pi-telegram-service
v1.0.1
Published
24/7 Telegram bot powered by the Pi coding agent SDK — per-user sessions, persistent memory, multi-LLM support
Maintainers
Readme
Pi Telegram Service
A 24/7 Telegram bot that wraps the Pi coding agent SDK. Each user gets their own isolated agent instance with persistent memory.
User (Telegram mobile) ──► Bot ──► Pi Agent (your VPS) ──► LLM APIRequirements
- Node.js 20+
- A VPS or cloud server (Hetzner, Railway, Fly.io, DigitalOcean, etc.)
- A Telegram bot token (from @BotFather)
- An API key de Minimax, Anthropic, OpenAI, or Google
Quick start (local dev)
# 1. Clone / copy this project
cd pi-telegram-service
# 2. Install dependencies
npm install
# 3. Configure
cp .env.example .env
# Edit .env — fill in TELEGRAM_BOT_TOKEN and MINIMAX_API_KEY
# 4. Run in dev mode (hot reload)
npm run devProduction deploy (VPS with PM2)
# On your server:
# Install Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
# Install PM2 globally
npm install -g pm2
# Clone your project
git clone https://github.com/youruser/pi-telegram-service.git
cd pi-telegram-service
npm install
cp .env.example .env
nano .env # Fill in your tokens
npm run build # Compile TypeScript → dist/
# Start with PM2
pm2 start ecosystem.config.cjs --env production
# Save PM2 process list (survives server reboots)
pm2 save
pm2 startup # Follow the printed command to enable autostartUseful PM2 commands
pm2 status # See if the bot is running
pm2 logs pi-telegram # Tail live logs
pm2 restart pi-telegram # Restart after config change
pm2 stop pi-telegram # Stop
pm2 monit # Live dashboardConfiguration
All config lives in .env. Key settings:
| Variable | Description | Default |
|---|---|---|
| TELEGRAM_BOT_TOKEN | From @BotFather | required |
| MINIMAX_API_KEY | Minimax API key | required (if using Minimax) |
| ANTHROPIC_API_KEY | Anthropic API key | optional |
| OPENAI_API_KEY | OpenAI API key | optional |
| GOOGLE_API_KEY | Google Gemini API key | optional |
| AGENT_MODEL_PROVIDER | minimax, anthropic, openai, google | minimax |
| AGENT_MODEL_ID | Model name | MiniMax-M2.7 |
| AGENT_SYSTEM_PROMPT | What role/personality the agent has | generic assistant |
| SESSIONS_DIR | Where per-user sessions are stored | ./sessions |
| SESSION_IDLE_TIMEOUT_MINUTES | Minutes before evicting from RAM | 30 |
Project structure
src/
index.ts ← Entry point, graceful shutdown
config.ts ← Env var validation
logger.ts ← Winston logger
bot.ts ← Telegram bot, commands, message handler
agent-bridge.ts ← Converts Pi SDK events → single response string
session-manager.ts← Per-user Pi agent instances, idle eviction
formatter.ts ← Splits long messages, tool activity summary
sessions/ ← Per-user JSONL session files (auto-created)
logs/ ← Application and PM2 logs
ecosystem.config.cjs ← PM2 production configCustomizing the agent
Change the system prompt
Edit AGENT_SYSTEM_PROMPT in .env. Examples:
# Customer support bot
AGENT_SYSTEM_PROMPT=You are a support agent for Acme Corp. Be professional and helpful. Only answer questions related to our products.
# Personal assistant
AGENT_SYSTEM_PROMPT=You are my personal assistant. Help me stay organized, draft messages, and answer questions. Be concise.
# Code reviewer
AGENT_SYSTEM_PROMPT=You are a senior engineer. When shown code, review it for bugs, style issues, and improvements. Be specific.Add custom tools
In src/session-manager.ts, add a customTools array to createAgentSession():
import { Type } from "@sinclair/typebox";
import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
const weatherTool: ToolDefinition = {
name: "get_weather",
label: "Weather",
description: "Get current weather for a city",
parameters: Type.Object({
city: Type.String({ description: "City name" }),
}),
execute: async (_id, params) => {
const data = await fetchWeather(params.city); // your implementation
return {
content: [{ type: "text", text: JSON.stringify(data) }],
details: {},
};
},
};
// In createAgentSession():
const { session } = await createAgentSession({
// ...existing options...
customTools: [weatherTool],
});Restrict which built-in tools are available
import { readOnlyTools } from "@mariozechner/pi-coding-agent";
const { session } = await createAgentSession({
tools: readOnlyTools, // read, grep, find, ls — no bash, no write
});How sessions work
- Each Telegram
chat_idgets its own Pi agent instance. - Sessions persist to
sessions/<chat_id>/as JSONL files. - If the server restarts, sessions reload from disk automatically (
continueRecent). - After
SESSION_IDLE_TIMEOUT_MINUTESof inactivity, the session is evicted from RAM but stays on disk. /newcommand starts a fresh conversation (old history is not deleted, just a new session file is created).
Persistent memory (SQLite)
The bot has a semantic memory system backed by SQLite (sessions/memory.db). Memories survive /new and server restarts.
Schema
memories (id, chat_id, content, created_at)How it works
- On each session start, the user's memories are injected into the system prompt automatically.
- The agent has two built-in tools:
save_memory(content)— saves a fact about the userdelete_memory(id)— removes an outdated or incorrect memory
Example
Tell the bot:
"Remember that my company is called Heskala and my main stack is TypeScript"
The agent will call save_memory and those facts will appear in every future session:
## Recuerdos del usuario
- [1] Company: Heskala
- [2] Main stack: TypeScriptEstimated costs (Anthropic Claude Sonnet)
| Users | Messages/day | LLM cost/month | |---|---|---| | 10 | 20 each | ~$6 | | 50 | 20 each | ~$30 | | 200 | 20 each | ~$120 |
VPS cost (Hetzner CX21, 4GB RAM): ~€5/month.
macOS menu bar widget (xbar)
Para controlar el bot desde la barra de menú del Mac sin abrir la terminal:
Requisitos
- xbar —
brew install --cask xbar
Instalación del plugin
# Copia el plugin a la carpeta de xbar
cp scripts/pi-telegram.5s.sh "$HOME/Library/Application Support/xbar/plugins/"
chmod +x "$HOME/Library/Application Support/xbar/plugins/pi-telegram.5s.sh"Luego haz clic en xbar → Refresh all.
Qué muestra
🟢 Pi Bot ▾
├── Estado: online
├── RAM: 176 MB
├── Reinicios: 0
├── 🔄 Reiniciar
├── ⏹ Detener
├── ▶️ Iniciar
└── 📋 Ver logsSe actualiza automáticamente cada 5 segundos.
