Your first botΒΆ

Let’s build a minimal bot and understand what Raito does for you.

Project layoutΒΆ

Create a folder for your handlers next to your entry point:

my_bot/
β”œβ”€β”€ __main__.py
└── handlers/
    └── start.py

The entry pointΒΆ

__main__.py wires aiogram together and hands the handlers directory to Raito:

import asyncio

from aiogram import Bot, Dispatcher
from raito import Raito


async def main() -> None:
    bot = Bot(token="YOUR_TOKEN")
    dispatcher = Dispatcher()

    raito = Raito(dispatcher, "my_bot/handlers", production=False)

    raito.init_logging()
    await raito.setup()
    await dispatcher.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())

Two calls do the work:

  • raito.Raito.setup() scans my_bot/handlers and registers every router it finds β€” you never call dispatcher.include_router yourself.

  • production=False turns on the watchdog: edit a handler file and Raito reloads it without restarting the bot.

raito.Raito.init_logging() is optional β€” it installs a colored, readable log formatter.

A handlerΒΆ

Each file in handlers/ exposes a router object. Raito also accepts a router under any variable name, or the single router defined in the file β€” but router is the convention.

# my_bot/handlers/start.py
from aiogram import Router, filters, types

router = Router(name="start")


@router.message(filters.CommandStart())
async def start(message: types.Message) -> None:
    await message.answer("Hello from Raito! πŸ‘‹")

Run it:

python -m my_bot

Send /start to your bot and you’ll get a reply. Now edit the text in start.py and save β€” the change is live on the next message, no restart.

Tip

Files and folders whose names start with _ are ignored by the loader, so handlers/_utils.py won’t be treated as a router.

What just happenedΒΆ

  • Raito walked handlers/ recursively, imported each module and picked up its router.

  • It registered them with the dispatcher in a deterministic order.

  • In development mode it started watching the folder for changes.

Curious how the reload works? See Architecture. Ready to add real commands? Continue to Commands with descriptions and arguments.