Summary
Each bot platform adapter in the praisonai wrapper independently re-implements the same BotSessionManager setup block — session-store acquisition, reset-policy extraction, and the backward-compatible max_history resolution. The block is near-identical across 7+ adapters, so any fix or change to session-config resolution must currently be applied in every adapter by hand. This is a wrapper-health / maintenance concern, not a feature cut.
Current behaviour
The same setup sequence is copied verbatim (only the platform= string and an optional run_control= differ) in each adapter constructor:
src/praisonai/praisonai/bots/telegram.py:135-156
src/praisonai/praisonai/bots/slack.py:106-126
src/praisonai/praisonai/bots/discord.py:~95-114
src/praisonai/praisonai/bots/whatsapp.py:~139-158
src/praisonai/praisonai/bots/email.py
src/praisonai/praisonai/bots/linear.py
src/praisonai/praisonai/bots/agentmail.py
Representative block (from slack.py):
try:
from praisonaiagents.session import get_default_session_store
_store = get_default_session_store()
except Exception:
_store = None
# Extract reset policy from config
reset_policy = None
if hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'reset') and self.config.session.reset:
from ._reset_policy import SessionResetPolicy
reset_policy = SessionResetPolicy.from_dict(self.config.session.reset.model_dump())
# Support backward compatibility with max_history at channel level
max_history = 100
if hasattr(self.config, 'max_history') and self.config.max_history is not None:
max_history = self.config.max_history
elif hasattr(self.config, 'session') and self.config.session:
if hasattr(self.config.session, 'max_history') and self.config.session.max_history is not None:
max_history = self.config.session.max_history
self._session: BotSessionManager = BotSessionManager(
max_history=max_history,
store=_store,
platform="slack",
reset_policy=reset_policy,
)
The telegram.py copy additionally threads a run_control= argument, but the store/reset-policy/max_history resolution is identical.
Why it matters
- Maintenance / drift risk: the backward-compatible
max_history precedence (channel-level vs session.max_history) and the reset-policy extraction are duplicated 7+ times. A bug fix or a new config key must be replicated everywhere; one missed copy silently diverges a single platform's session behaviour.
- Duplication: ~15–20 lines × 7 adapters of identical config-resolution logic.
This is a maintenance/duplication concern only — there is no measurable import or hot-path cost.
Category
Duplicate
Capability preserved
- All bot platforms (Telegram, Discord, Slack, WhatsApp, Email, Linear, AgentMail) keep identical runtime behaviour.
BotSessionManager, reset policies, run_control, max_history backward compatibility, and session-store wiring are all unchanged.
- No CLI, YAML, or Python surface changes; bot reliability/session handling untouched.
Proposed approach
Move the shared resolution into a single helper alongside BotSessionManager in bots/_session.py, and have each adapter call it. Pure refactor — no behavioural change.
Resolution sketch
# bots/_session.py (new module-level helper, same owner as BotSessionManager)
def build_session_manager(config, platform, *, run_control=None) -> "BotSessionManager":
try:
from praisonaiagents.session import get_default_session_store
store = get_default_session_store()
except Exception:
store = None
reset_policy = None
if getattr(config, "session", None) and getattr(config.session, "reset", None):
from ._reset_policy import SessionResetPolicy
reset_policy = SessionResetPolicy.from_dict(config.session.reset.model_dump())
max_history = 100
if getattr(config, "max_history", None) is not None:
max_history = config.max_history
elif getattr(config, "session", None) and getattr(config.session, "max_history", None) is not None:
max_history = config.session.max_history
return BotSessionManager(
max_history=max_history,
store=store,
platform=platform,
reset_policy=reset_policy,
run_control=run_control,
)
# Each adapter (e.g. slack.py)
# Before: ~20 lines of store/reset/max_history boilerplate + constructor
# After:
from ._session import build_session_manager
self._session = build_session_manager(self.config, platform="slack")
# telegram.py passes run_control=run_control
Layer placement
- Primary layer: wrapper (
src/praisonai/praisonai/bots/)
- Touches core/tools/plugins: none — continues to consume
praisonaiagents.session.get_default_session_store exactly as today.
- 3-way surface (CLI + YAML + Python): preserved — yes (no surface change).
Severity
Low — maintenance/duplication only; no import or hot-path impact, but removes a real config-drift risk across 7 adapters.
Validation
- Traced: identical block confirmed in
telegram.py, slack.py, discord.py, whatsapp.py (and present in email.py, linear.py, agentmail.py); each adapter constructs BotSessionManager independently with no shared __init__.
- Not intentional robustness: the duplication adds no safety; it is copy-paste boilerplate.
- No user-facing regression: behaviour is byte-for-byte preserved; only the call site changes.
Keep unchanged
- Centralised
_session.BotSessionManager.chat() (already single source of truth) — do not touch.
- Platform-specific approval backends, rate limiters, debouncer/ack init, pairing wiring — these are platform-specific and correctly separated.
- Lazy SDK imports (
python-telegram-bot, discord.py, slack_bolt) inside start() — keep as-is.
Summary
Each bot platform adapter in the
praisonaiwrapper independently re-implements the sameBotSessionManagersetup block — session-store acquisition, reset-policy extraction, and the backward-compatiblemax_historyresolution. The block is near-identical across 7+ adapters, so any fix or change to session-config resolution must currently be applied in every adapter by hand. This is a wrapper-health / maintenance concern, not a feature cut.Current behaviour
The same setup sequence is copied verbatim (only the
platform=string and an optionalrun_control=differ) in each adapter constructor:src/praisonai/praisonai/bots/telegram.py:135-156src/praisonai/praisonai/bots/slack.py:106-126src/praisonai/praisonai/bots/discord.py:~95-114src/praisonai/praisonai/bots/whatsapp.py:~139-158src/praisonai/praisonai/bots/email.pysrc/praisonai/praisonai/bots/linear.pysrc/praisonai/praisonai/bots/agentmail.pyRepresentative block (from
slack.py):The
telegram.pycopy additionally threads arun_control=argument, but the store/reset-policy/max_historyresolution is identical.Why it matters
max_historyprecedence (channel-level vssession.max_history) and the reset-policy extraction are duplicated 7+ times. A bug fix or a new config key must be replicated everywhere; one missed copy silently diverges a single platform's session behaviour.This is a maintenance/duplication concern only — there is no measurable import or hot-path cost.
Category
Duplicate
Capability preserved
BotSessionManager, reset policies,run_control,max_historybackward compatibility, and session-store wiring are all unchanged.Proposed approach
Move the shared resolution into a single helper alongside
BotSessionManagerinbots/_session.py, and have each adapter call it. Pure refactor — no behavioural change.Resolution sketch
Layer placement
src/praisonai/praisonai/bots/)praisonaiagents.session.get_default_session_storeexactly as today.Severity
Low — maintenance/duplication only; no import or hot-path impact, but removes a real config-drift risk across 7 adapters.
Validation
telegram.py,slack.py,discord.py,whatsapp.py(and present inemail.py,linear.py,agentmail.py); each adapter constructsBotSessionManagerindependently with no shared__init__.Keep unchanged
_session.BotSessionManager.chat()(already single source of truth) — do not touch.python-telegram-bot,discord.py,slack_bolt) insidestart()— keep as-is.