Long-Running Bots
Run bots 24/7 without memory leaks or silent corruption
Run Telegram, Discord, Slack, and other bots for weeks — bounded lock caches and agent-scoped locks keep memory stable with no extra configuration.
from praisonaiagents import Agent
from praisonai.bots import Bot
agent = Agent(name="assistant", instructions="Be helpful")
bot = Bot("telegram", agent=agent)
bot.run()The user messages your bot channel; session locks stay bounded while the same agent handles concurrent chats.
How It Works
Quick Start
- Simple Usage
python from praisonaiagents import Agent from praisonai.bots import Bot agent = Agent(name="assistant", instructions="Be helpful") bot = Bot("telegram", agent=agent) bot.run() # Bounded locks are active by defaultNothing extra is required — debounce, session, and run-control paths share the same bounded per-user lock cache.
- With Configuration
python from praisonaiagents import Agent from praisonaiagents import BotConfig from praisonai.bots import Bot agent = Agent(name="assistant", instructions="Be helpful") config = BotConfig(session_ttl=86400) # Reap idle sessions after 24h bot = Bot("telegram", agent=agent, config=config) bot.run()
What’s Bounded by Default
| Resource | Default limit | When it cleans up |
|---|---|---|
| Per-user lock cache | 10,000 entries, 1 hour TTL | Idle, unlocked entries evict automatically |
| Agent locks | One per agent instance | Removed when the agent is garbage-collected |
| Session histories | Opt-in via session_ttl | See Session Persistence |
Operational Knobs
For mid-run cancellation and stale session cleanup, see Bot Run Control — SessionRunControl.cleanup_stale_sessions(max_age_seconds=3600) removes abandoned run-control state.
Multi-Agent Safety
Earlier releases keyed agent locks on id(agent). CPython may reuse that integer after garbage collection, so long-running gateways that recreated agents per request could silently mix up two users’ histories. Agent locks now follow agent lifetime via WeakKeyDictionary; per-user locks stay bounded even if you never call cleanup helpers.
Best Practices
Reuse one agent instance per bot
Create the agent once at startup — agent locks follow instance lifetime via WeakKeyDictionary, so recreating agents per request is safe but wasteful.
Set session_ttl for busy channels
Default lock caches evict after 1 hour; set BotConfig(session_ttl=…) when conversations stay idle longer than your support SLA.
Run cleanup_stale_sessions periodically
Call SessionRunControl.cleanup_stale_sessions on a schedule in long-lived gateways to drop abandoned run-control state.
Upgrade after PR #1972
Ensure you are on a release that includes bounded agent locks — earlier builds could mix histories when id(agent) was reused.
Auto-reconnect (default)
Bot(...).run() now supervises its own inbound connection — if the socket drops, ChannelSupervisor reconnects with capped exponential backoff and restarts an unhealthy channel, matching the resilience BotOS and the gateway already provide.
- Default supervision on Slack
python from praisonaiagents import Agent from praisonai_bot import Bot agent = Agent(name="Support", instructions="Answer support questions") Bot("slack", agent=agent).run() # auto-reconnects on drop - Same code, every platform
The identical pattern works for Discord, Email, Linear, and WhatsApp — no extra flags:
python from praisonaiagents import Agent from praisonai_bot import Bot agent = Agent(name="Support", instructions="Answer support questions") Bot("discord", agent=agent).run() # supervised too - Opt out under an external supervisor
Set
enable_supervision=Falsewhen embedding, testing, or running under systemd/k8s:python from praisonaiagents import Agent from praisonai_bot import Bot agent = Agent(name="Support", instructions="Answer support questions") Bot("slack", agent=agent, enable_supervision=False).run()
Which platforms are supervised by default?
| Platform | Supervised by default? | Why |
|---|---|---|
| Slack, Discord, WhatsApp, Email, Linear, AgentMail | ✅ Yes | Standard adapters — supervision wraps the inbound run loop. |
| Telegram | ❌ No — self-managed | Telegram already runs its own reconnect loop; wrapping would double-drive. |
| Relay transport | ❌ No — external | Out-of-process reconnect + scale-to-zero dormancy. |
When to opt out (enable_supervision=False)
Don't stack supervisors
If a Bot runs inside BotOS or under systemd/Kubernetes, set enable_supervision=False. Two supervisors on one connection means double reconnect attempts and double backoff — let the outer supervisor own restarts.
Email / Linear / WhatsApp / AgentMail — `Bot.run()` no longer returns immediately
Adapters whose start() returns immediately (Email IMAP poll, Linear/WhatsApp/AgentMail webhook servers) now stay supervised until they actually stop. Scripts that relied on .run() returning early should switch to await bot.start() and manage lifecycle explicitly, or spawn the run in a background task.