IRC Bot with Ollama
What This Article Covers
- Building an IRC bot that uses Ollama as its AI backend.
- Integrating the bot into IRC channels.
- How commands, moderation, and automation work.
- Practical examples: FAQ bots, channel support, and logging.
- Best practices for network etiquette, security, and rate limiting.
Introduction: IRC Bots with Ollama Explained
IRC is the classic chat protocol: simple, fast, and running since 1988. An IRC bot powered by Ollama brings modern AI to this timeless platform. The bot joins a channel, answers questions, executes commands, and handles moderation, all backed by a local language model.
This article is for anyone wanting to extend IRC with AI capabilities. For background on IRC bots, see IRC Bots, and for Ollama setup, see Ollama. Basic Python knowledge is helpful; you can find it at IRC-Coding.de.
Why Use an IRC Bot with Ollama?
IRC is minimal by design: text in, text out. An AI bot can answer questions in channels, run commands, and moderate conversations. Unlike Discord or Matrix, IRC is straightforward enough that a basic bot can be written in 50 lines of Python.
How It Works: IRC Bot with Ollama in Brief
The bot connects to an IRC server, joins a channel, and listens for messages. When it sees a command starting with ! or a mention of its name, it calls Ollama and posts the response back.
The core idea: IRC is simple; AI makes it intelligent.
Who Should Read This?
- IRC users wanting to add AI to their channels.
- Retro computing enthusiasts combining IRC with modern AI.
- Developers building lightweight bots.
- Community admins automating IRC channels.
Some familiarity with Python and IRC basics is helpful.
Key Terms
- IRC - Internet Relay Chat. Use case: the protocol itself.
- Channel - A chat room in IRC. Use case: where the bot lives.
- Nickname - A username. Use case: the bot’s name.
- irc / pydle - Python libraries. Use case: building the bot.
- Ollama - Local model server. Use case: the AI backend.
- PRIVMSG - A message in IRC. Use case: how the bot communicates.
- IRC Bot Basics - Core bot concepts. Use case: getting started.
Setup: Creating Your IRC Bot
Bot with pydle (Python)
# bot.py
import asyncio
import aiohttp
from pydle import Client
OLLAMA_URL = "http://ollama:11434"
IRC_SERVER = "irc.libera.chat"
IRC_PORT = 6697
IRC_CHANNEL = "#mein-channel"
BOT_NICK = "KI-Bot"
async def call_ollama(prompt, system=None):
"""Call Ollama"""
messages = []
if system:
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
async with aiohttp.ClientSession() as session:
async with session.post(
f"{OLLAMA_URL}/api/chat",
json={
"model": "llama3.1",
"messages": messages,
"stream": False
},
timeout=aiohttp.ClientTimeout(total=60)
) as response:
data = await response.json()
return data["message"]["content"]
class KIBot(Client):
async def on_connect(self):
"""Upon connection"""
await self.join(IRC_CHANNEL)
print(f"Bot online in {IRC_CHANNEL}")
async def on_message(self, target, source, message):
"""On incoming message"""
# Ignore our own messages
if source == self.nickname:
return
# Handle commands
if message.startswith("!"):
await self.handle_command(target, source, message)
# Handle mentions
elif self.nickname.lower() in message.lower():
await self.handle_mention(target, source, message)
async def handle_command(self, target, source, message):
"""Process a command"""
parts = message[1:].split()
command = parts[0].lower()
args = " ".join(parts[1:])
if command == "ask":
# !ask How does X work?
answer = await call_ollama(
args,
system="You are a helpful IRC bot. Keep answers brief."
)
await self.message(target, f"{source}: {answer}")
elif command == "summarize":
# !summarize (uses last N messages)
# Implementation: gather message history
await self.message(target, f"{source}: Summarizing...")
elif command == "help":
await self.message(target,
"Commands: !ask <question>, !summarize, !help"
)
async def handle_mention(self, target, source, message):
"""Process a mention"""
# Remove nickname from message
question = message.replace(self.nickname, "").strip()
answer = await call_ollama(
question,
system="You are a helpful IRC bot. Keep answers brief."
)
await self.message(target, f"{source}: {answer}")
# Start the bot
bot = KIBot(BOT_NICK, realname="KI Bot")
bot.run(IRC_SERVER, tls=True, tls_verify=False)
Running the Bot
pip install pydle aiohttp
export OLLAMA_URL="http://localhost:11434"
python bot.py
Implementing Commands
COMMANDS = {
"ask": "Ask the AI a question",
"summarize": "Summarize recent messages",
"translate": "Translate text",
"weather": "Get weather info",
"help": "Show help"
}
async def handle_command(self, target, source, message):
parts = message[1:].split()
command = parts[0].lower()
args = " ".join(parts[1:])
if command == "ask":
answer = await call_ollama(args, system="Keep your answer brief.")
await self.message(target, f"{source}: {answer}")
elif command == "translate":
answer = await call_ollama(
f"Translate to English: {args}",
system="Translate only."
)
await self.message(target, f"{source}: {answer}")
elif command == "weather":
# Call weather API
weather = await get_weather(args)
await self.message(target, f"{source}: {weather}")
elif command == "help":
cmds = ", ".join(f"!{k}" for k in COMMANDS)
await self.message(target, f"Commands: {cmds}")
Practical Example 1: FAQ Bot
import chromadb
class IRCFAQBot(KIBot):
def __init__(self):
super().__init__(BOT_NICK)
self.chroma = chromadb.HttpClient(host="chromadb", port=8000)
self.collection = self.chroma.get_collection("faq")
async def handle_command(self, target, source, message):
if message.startswith("!faq"):
question = message[4:].strip()
# RAG: Search for similar documents
results = self.collection.query(
query_texts=[question],
n_results=3
)
context = "\n".join(results["documents"][0])
answer = await call_ollama(
f"Context:\n{context}\n\nQuestion: {question}",
system="Answer based on context. Keep it brief."
)
await self.message(target, f"{source}: {answer}")
else:
await super().handle_command(target, source, message)
Practical Example 2: Moderation
async def on_message(self, target, source, message):
if source == self.nickname:
return
# AI analyzes message
analysis = await call_ollama(
f"Analyze: {message}\n"
"Categories: ok, spam, toxic\n"
"Reply: CATEGORY",
system="You are an IRC moderator."
)
if "spam" in analysis.lower() or "toxic" in analysis.lower():
# Remove message (bot needs op privileges)
await self.kick(target, source, "Rule violation")
await self.message(target, f"⚠️ {source} was warned")
Practical Example 3: Channel Logging with AI Summary
class LoggingBot(KIBot):
def __init__(self):
super().__init__(BOT_NICK)
self.log = []
async def on_message(self, target, source, message):
# Log message
self.log.append({
"time": asyncio.get_event_loop().time(),
"user": source,
"message": message
})
await super().on_message(target, source, message)
async def daily_summary(self):
"""Generate daily summary"""
log_text = "\n".join(
f"{e['user']}: {e['message']}" for e in self.log[-500:]
)
summary = await call_ollama(
f"Summarize the latest IRC messages:\n{log_text}",
system="Create a brief summary."
)
await self.message(IRC_CHANNEL, f"Daily summary:\n{summary}")
self.log = []
Practical Example 4: n8n Trigger
elif command == "workflow":
# !workflow name param1 param2
parts = args.split()
wf_name = parts[0] if parts else "default"
wf_params = " ".join(parts[1:])
async with aiohttp.ClientSession() as session:
async with session.post(
f"http://n8n:5678/webhook/{wf_name}",
json={"params": wf_params, "user": source}
) as r:
result = await r.text()
await self.message(target, f"{source}: {result}")
IRC Netiquette
# Rate-limiting: don't send too fast
async def message(self, target, text):
# IRC has rate limits
await asyncio.sleep(1) # 1 second between messages
await super().message(target, text)
# Split long messages
async def send_long(self, target, text, max_len=400):
for i in range(0, len(text), max_len):
await self.message(target, text[i:i+max_len])
Security Considerations
- Bot password: Set a password for registered nicks via NickServ.
- Op privileges minimal: The bot should have only the permissions it needs.
- Prompt injection: Users can send injections. See Prompt Injection.
- Flooding: Don’t send too many messages too quickly. Servers will kick bots.
- Logging: Audit bot actions. See Audit Logging.
Common Pitfalls
- Flooding: IRC servers kick bots that send too fast. Implement rate-limiting.
- Long messages: IRC has a 512-byte limit per line. Split messages into chunks.
- Nick collision: Your bot’s nickname must be available. Register with NickServ.
- SSL/TLS: Many IRC servers require TLS. Set
tls=Truein pydle. - Encoding: IRC uses Latin-1 or UTF-8. Watch out for encoding issues.
- Ollama too slow: Large models take time. Use smaller models (8B) for real-time responses.
Further Reading
- IRC Bot Basics - Bot fundamentals.
- Advanced IRC Setup - Advanced features.
- Ollama - Model server.
- pydle - Python IRC library.
- Prompt Injection - Security.
Key Takeaways:
- IRC + Ollama: Classic chat with modern AI.
- pydle for Python bots, simple and powerful.
- Commands with
!, mentions for chat. - Follow rate-limiting and netiquette.
- Local AI: no data leaves your server, no API costs.
FAQ
How do I create an IRC bot?
IRC or Discord for bots?
Which Python library for IRC?
How do I implement commands?
!: !ask, !help, !summarize. Parse the command and its arguments, then execute the action.How do I prevent flooding?
Do I need SSL/TLS?
What does it cost?
Is the bot secure?
Resources and Further Reading
- pydle - Python IRC library.
- IRC RFC - IRC protocol.
- Libera.Chat - IRC network.
- Ollama - Local model server.


