Plugin Integration¶
SimpleContext-Bot v1.2 has a fully dynamic plugin system. Any plugin dropped into the plugins/ folder is auto-loaded, and its app_commands are automatically registered as Telegram commands.
How It Works¶
On every start, the bot:
- Scans all
.pyfiles in~/.simplecontext-bot/plugins/ - Loads any class that inherits
BasePlugin - Reads
app_commandsfrom each loaded plugin - Registers each command as a Telegram handler
- Sets bot command menu via
set_my_commands() - Injects
app_infointo all plugins:{"platform": "telegram", "version": "1.2.0"}
No changes to bot code needed — ever.
Install a Plugin¶
Plugin Lifecycle in Bot¶
simplecontext-bot start
│
▼
_load_all_plugins()
├── scan plugins/*.py
├── load each BasePlugin subclass
├── inject config from config.json
└── sc.use(plugin_instance)
│
▼
_collect_app_commands()
└── sc._plugins.get_all_app_commands()
│
▼
For each command:
└── app.add_handler(CommandHandler(cmd_name, handler_fn))
│
▼
post_init: bot.set_my_commands([...static..., ...plugin cmds...])
│
▼
Bot running ✅
Writing a Plugin for SimpleContext-Bot¶
Any plugin that declares app_commands will have its commands registered:
from simplecontext.plugins.base import BasePlugin, AppCommandContext
class MyPlugin(BasePlugin):
name = "my_plugin"
version = "1.0.0"
description = "My plugin description."
app_commands = {
"mycommand": {
"description": "What /mycommand does",
"usage": "/mycommand <arg>",
"handler": "handle_mycommand",
}
}
def on_context_build(self, user_id, messages):
# This hook runs for every message automatically
messages[0]["content"] += "\n\nExtra context."
return messages
async def handle_mycommand(self, ctx: AppCommandContext) -> str:
# ctx.platform == "telegram"
# ctx.user_id == Telegram user ID string
# ctx.args_str == everything after /mycommand
return f"Hello from Telegram! You said: {ctx.args_str}"
Drop my_plugin.py into ~/.simplecontext-bot/plugins/ and restart. /mycommand is now live.
Accessing Platform-Specific Data¶
The ctx.raw field contains the Telegram Update object:
async def handle_mycommand(self, ctx: AppCommandContext) -> str:
# Access Telegram-specific data
update = ctx.raw
user = update.effective_user
chat = update.effective_chat
return f"Hello {user.first_name} in chat {chat.id}!"
Keep plugins platform-agnostic when possible
Use ctx.user_id, ctx.args_str, and ctx.sc for logic that should work on any platform. Only access ctx.raw for Telegram-specific features.
Checking App Info¶
def setup(self):
# Check which platform loaded this plugin
platform = self.app_info.get("platform", "unknown")
version = self.app_info.get("version", "unknown")
print(f"Loaded on {platform} v{version}")
Plugin Config in Bot¶
Plugin config is stored in ~/.simplecontext-bot/config.json under plugins.configs:
{
"plugins": {
"enabled": true,
"installed": ["vector-search"],
"configs": {
"vector-search": {
"provider": "local",
"top_k": 5,
"min_score": 0.15,
"tiers": ["semantic", "episodic"]
}
}
}
}
Edit this file to customize plugin config, then restart the bot.