LLM plugin¶
The LLM plugin is VibeBot's main AI surface. It provides natural-language chat, code and image generation, illustrated stories, persistent memory, and reminders. It also runs scheduled agentic tasks, hosts a persistent roleplay world (the verse), and carries a curated bridge that lets the model call other Limnoria plugins as tools.
Command families¶
| Family | Commands | Notes |
|---|---|---|
| Core AI | @ask, @code, @draw, @meme, @story |
Chat with vision, code with HTTP links, images, captioned memes, illustrated pages. |
| Memory | @forget, @memories, @instruct |
Volatile context, durable facts, persistent instructions. |
| Reminders | @remind, @tz |
Natural-language reminders with recurring support, read in your time zone. |
| Accounting | @usage |
Per-account and per-channel API usage. |
| Verse (user) | @verseopt, @rp, @verse, @look, @who, @avatar |
Opt in, roleplay, inspect the scene, set a persona. |
| Verse (editor) | @canon, @versedit |
Curate durable canon. Requires llm.verse.edit. |
| Verse (GM) | @versedump, @versepurge, @versecompact |
Inspect, wipe, and compact a channel's verse. Requires llm.verse.gm. |
See the command reference for full syntax and capability requirements, and the configuration guide for every registry key.
@ask, @code and @draw also work through plain language: mention
the bot by name or send it a PM. @story does not — an illustrated page
comes from the command, or from an explicit illustrate cue in a verse
channel with verseStorybookEnabled on. Memory, Reminders and Accounting are
command-only, with two exceptions — the model can save a memory, and
where pendingTasksEnabled is on it can set a reminder or schedule a
task. Listing and cancelling go through @remind list, del and
clear, which cover your reminders and your scheduled tasks alike.
Bridge tools lists the tool surface each
route sees.
Capabilities¶
Limnoria capabilities gate the AI and verse commands: llm.ask (@ask,
@forget), llm.code, llm.draw (also covers @story), llm.animate
(@animate, @video, @renders), llm.verse
(@rp, @verseopt, @verse, @look, @who), llm.verse.edit
(@canon, @versedit), and llm.verse.gm (@versedump,
@versepurge, @versecompact).
@remind also needs llm.ask, since it manages persisted reminders and
scheduled tasks. @memories, @instruct, @tz, @usage, and @avatar carry
no capability of their own. The paths that reach past your own data check
inline instead: owner for @memories <nick> and @remind admin,
admin for a bare @usage by PM. Owner and admin accounts bypass rate limits.
Internal layout¶
plugins/llm/src/llm/
├── plugin.py # IRC command surface + Limnoria glue
├── service.py # LiteLLM calls, sanitisation, output shaping
├── assistant.py # Tool schemas and per-route visibility (function calling)
├── profile.py # Route profiles: model, prompt, overlay, and caps per mode
├── prompts.py # Shared system-prompt fragments
├── executor.py # LLMExecutor: global concurrency cap
├── persistence.py # SQLite store (memories, reminders, schedules, usage)
├── limnoria_bridge.py # Allowlisted "Limnoria as tools" surface
├── statuspage.py # Statuspage v2 polling, parsing, and rendering
├── context.py # Conversation history with TTL
├── config.py # Limnoria registry options
├── apikeys.py # Provider-scoped API keys and secret redaction
├── tracing.py # Per-request IDs threaded through the logs
└── verse/ # Verse store, avatar engine, compaction, taste tools
Concurrency model¶
Every blocking LLM call goes through LLMExecutor (in executor.py),
which combines a BoundedSemaphore and a ThreadPoolExecutor. This
design:
- caps total in-flight LLM I/O with
supybot.plugins.LLM.maxConcurrentLLMCalls(default 16), - keeps the IRC main thread responsive, because no
litellm.*call can block it directly, and - shares one shutdown gate, so plugin reloads drain in-flight work cleanly.
The global @usage report — a bare @usage by PM, admin only —
appends an executor: running/queued/max field for tuning.
Storage¶
Persistent state lives in a single SQLite database managed by
persistence.py. All writes go through the _write_txn context
manager, so a failure mid-update rolls back rather than leaving partial
state. Tables cover memories, reminders, scheduled tasks, conversation
snapshots, and per-account usage. Each verse-enabled channel gets its
own SQLite store under data/verse/.