Extending MiniBot¶
MiniBot is built to be customized, and most changes never touch Python. Everything below the extension layer is file- or config-driven; Python extensions exist for the parts that need real logic.
Customization ladder¶
Work top-down: use the least powerful layer that does the job.
Level |
What you can do |
Where |
Code? |
|---|---|---|---|
|
Enable/disable tools, pick providers and models, set limits and timeouts. |
|
No |
|
Rewrite the system prompt, add policy/channel prompt packs, add skills, add specialist agent definitions. |
|
No |
|
Connect any MCP server and expose its remote tools to the model. |
|
No |
|
Add your own tools, react to internal events, run background services, contribute channels. |
a Python module + |
Yes |
What you can plug in¶
Surface |
Mechanism |
Example |
|---|---|---|
LLM tool |
|
See “Your first tool” below. |
Event subscription |
|
Events; |
Background service |
|
Anything that must run for the process lifetime. |
Channel |
A channel extension module driven by a |
The bundled Telegram channel. |
Provider |
|
|
Scheduled prompt |
|
Your first tool¶
A tool is little more than a pydantic model plus a function. This one counts words in any text:
# my_tool.py — any directory on PYTHONPATH
from pydantic import BaseModel, Field
from minibot.app.extensions import ExtensionContext
from minibot.llm.tools.base import ToolContext
class WordCountArgs(BaseModel):
text: str = Field(description="Text to count words in.")
def register(mb: ExtensionContext) -> None:
@mb.tool
async def word_count(args: WordCountArgs, context: ToolContext) -> dict[str, int]:
"""Count the words in a piece of text."""
return {"words": len(args.text.split())}
Enable it and try it:
[extensions]
modules = ["my_tool"]
$ PYTHONPATH=. poetry run minibot console --once "How many words in 'lazy senior dev'?"
@mb.tool uses the function name as the tool name, the docstring as the model-facing
description, and the first argument’s pydantic model as the JSON schema. Invalid
arguments return invalid_tool_arguments to the model instead of reaching your handler.
Where extensions plug in¶
flowchart LR
subgraph INPUTS["What you add"]
direction TB
modules["[extensions].modules"]
content["prompts/ · skills/ · agents/*.md"]
servers["[[tools.mcp.servers]]"]
end
subgraph OUTPUTS["What MiniBot gains"]
direction TB
tools["LLM tools"]
events["Event subscribers"]
services["Services"]
channels["Channels"]
prompt["System prompt · skill catalog · specialists"]
remote["Remote MCP tools"]
end
modules --> tools
modules --> events
modules --> services
modules --> channels
content --> prompt
servers --> remote
Each extension is an importable module exposing register(mb); local modules only need
their directory on PYTHONPATH. Extensions are trusted in-process code — configure one
the way you would install a dependency.
Next steps¶
Write a full extension with config and an event subscriber: Writing extensions.
Define specialist agents in Markdown: Multi-Agent Orchestration.
Override the prompt packs: Prompt Packs.
Point MiniBot at an MCP server: MCP Integration.