This guide will help you quickly create and run your first Zulip bot.
pip install async-zulip-bot-sdk
Create a ~/.zuliprc file:
[api]
email=your-bot@example.com
key=your-api-key
site=https://your-zulip-server.com
The SDK includes a main.py entry point that launches a rich interactive console. This is the recommended way to develop and run bots, as it supports hot reloads and managing multiple bots.
Breaking change (since v1.0.0): Bot configuration is now read from each bot’s
bot.yaml. Class-level attributes (e.g.,command_prefixes,enable_orm) are ignored.
python main.py
The console supports:
Up/Down arrows.PageUp/PageDown.reload <bot_name> command.Create my_bot.py:
from bot_sdk import BaseBot, Message, run_bot
class EchoBot(BaseBot):
async def on_message(self, message: Message) -> None:
"""Echo received messages"""
await self.send_reply(message, f"You said: {message.content}")
if __name__ == "__main__":
run_bot(EchoBot)
Run:
python my_bot.py
from bot_sdk import BaseBot, Message, CommandSpec, CommandArgument
class CommandBot(BaseBot):
def __init__(self, client):
super().__init__(client)
# Register commands
self.command_parser.register_spec(
CommandSpec(
name="greet",
description="Greet someone",
args=[
CommandArgument(
name="name",
type=str,
required=True,
description="Name to greet"
)
],
handler=self.handle_greet
)
)
async def handle_greet(self, invocation, message, bot):
"""Handle greet command"""
name = invocation.args["name"]
await self.send_reply(message, f"Hello, {name}! 👋")
async def on_message(self, message: Message) -> None:
"""Handle non-command messages"""
await self.send_reply(message, "Use /help to see available commands")
if __name__ == "__main__":
run_bot(CommandBot)
Test your bot on a test server or in a private channel.
.zuliprc configuration is correctfrom bot_sdk import BaseBot, Message
from loguru import logger
class MyBot(BaseBot):
async def on_message(self, message: Message) -> None:
try:
# Your logic
await self.send_reply(message, "Processed successfully")
except Exception as e:
logger.error(f"Failed to process message: {e}")
await self.send_reply(message, "Sorry, an error occurred!")