Bot de Matrix con Ollama
Qué cubre este artículo
- Cómo construir un bot de Matrix con Ollama como backend de IA.
- Cómo integrar el bot en salas de Matrix.
- Cómo funcionan RAG e integración de herramientas en Matrix.
- Ejemplos prácticos para bots de soporte, moderación y automatización.
- Mejores prácticas para E2EE, seguridad y privacidad.
Introducción: bot de Matrix con Ollama explicado
Matrix es un protocolo de chat descentralizado: autohospedado, cifrado, sin una empresa central. Un bot de Matrix con Ollama responde preguntas en tus salas de Matrix usando IA local: sin enviar datos a terceros, sin costos de API, control total.
Este artículo está dirigido a usuarios que quieren construir un bot de Matrix con IA local. Encontrarás información básica en Bots de Matrix y Ollama.
¿Por qué necesito un bot de Matrix con Ollama?
Los bots de Discord se ejecutan en servidores de Discord: tus datos están en Discord. Matrix es autohospedado: tu servidor, tus datos. Un bot de Matrix con Ollama es la solución más coherente para privacidad: protocolo descentralizado + IA local = nadie ve tus datos.
Bot de Matrix con Ollama en pocas palabras
Creas un bot de Matrix (matrix-nio o matrix-js-sdk) que reacciona a mensajes en salas. Cuando llega un mensaje, el bot invoca Ollama y publica la respuesta. Con E2EE, incluso los mensajes permanecen cifrados.
La idea central es: protocolo descentralizado + IA local = control máximo.
¿Para quién es este artículo?
- Usuarios de Matrix que quieren un bot con IA.
- Conscientes de privacidad que evitan Discord.
- Autohospedadores que ejecutan su propio servidor de Matrix.
- Desarrolladores que construyen bots de Matrix.
Es útil tener conocimientos previos en Python y Ollama.
Términos importantes
- Matrix - Protocolo descentralizado de chat. Cuándo es útil: el protocolo.
- Synapse - Homeserver de Matrix. Cuándo es útil: el software del servidor.
- Element - Cliente de Matrix. Cuándo es útil: la interfaz.
- matrix-nio - Librería de Python. Cuándo es útil: para el bot.
- Ollama - Servidor de modelos local. Cuándo es útil: el backend de IA.
- E2EE - Cifrado de extremo a extremo. Cuándo es útil: para mensajes privados.
- RAG - Base de datos de conocimiento. Cuándo es útil: para preguntas frecuentes.
Configuración: crear el bot de Matrix
1. Cuenta de bot en tu homeserver
# En el servidor Synapse: crear usuario bot
register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml \
-u ki-bot -p "sicheres-passwort" --no-admin
2. Bot con matrix-nio
# bot.py
import asyncio
import aiohttp
from nio import AsyncClient, RoomMessageText
OLLAMA_URL = "http://ollama:11434"
HOMESERVER = "https://matrix.deine-domain.de"
BOT_USER = "@ki-bot:deine-domain.de"
BOT_PASSWORD = "sicheres-passwort"
async def call_ollama(prompt, system=None):
"""Llamar a 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"]
async def main():
client = AsyncClient(HOMESERVER, BOT_USER)
# Login
response = await client.login(BOT_PASSWORD)
print(f"Bot conectado: {response.user_id}")
# Auto-join en invitaciones
client.add_event_callback(on_invite, InviteEvent)
async def on_message(room, event):
"""Con nuevo mensaje"""
if event.sender == BOT_USER:
return
# Reaccionar a menciones o comandos
if f"{BOT_USER}" in event.body or event.body.startswith("!"):
async with client.typing(room.room_id):
# Extraer pregunta
question = event.body.replace(f"@{BOT_USER.split(':')[0][1:]}", "").strip()
if question.startswith("!"):
question = question[1:].strip()
# Llamar a Ollama
answer = await call_ollama(
question,
system="Eres un asistente útil en un chat de Matrix. Responde brevemente y de forma útil."
)
# Enviar respuesta
await client.room_send(
room_id=room.room_id,
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": answer
}
)
client.add_event_callback(on_message, RoomMessageText)
# Bucle de sincronización
await client.sync_forever(timeout=30000)
asyncio.run(main())
3. Invitar el bot a una sala
# En Element (cliente de Matrix):
1. Crear o abrir una sala
2. /invite @ki-bot:deine-domain.de
3. El bot acepta automáticamente (callback on_invite)
Ejemplo práctico 1: bot de preguntas frecuentes con RAG
import chromadb
class MatrixFAQBot:
def __init__(self):
self.chroma = chromadb.HttpClient(host="chromadb", port=8000)
self.collection = self.chroma.get_collection("faq")
async def answer(self, question):
"""Responder pregunta con RAG"""
results = self.collection.query(
query_texts=[question],
n_results=3
)
context = "\n".join(results["documents"][0])
answer = await call_ollama(
f"Contexto:\n{context}\n\nPregunta: {question}",
system="Responde la pregunta basándote en el contexto. Proporciona fuentes."
)
return {
"answer": answer,
"sources": [m["source"] for m in results["metadatas"][0]]
}
# En on_message:
if event.body.startswith("!faq"):
question = event.body[4:].strip()
result = await faq_bot.answer(question)
await client.room_send(
room_id=room.room_id,
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": f"{result['answer']}\n\nFuentes: {', '.join(result['sources'])}"
}
)
Ejemplo práctico 2: Moderación
async def moderate_message(room, event, client):
"""Moderar mensaje"""
analysis = await call_ollama(
f"Analiza:\n{event.body}\n\n"
"Categorías: ok, spam, tóxico, nsfw\n"
"Responde: CATEGORÍA|RAZÓN",
system="Eres un asistente de moderación."
)
category, reason = analysis.split("|", 1)
if category != "ok":
# Eliminar mensaje (el bot necesita permisos de moderador)
await client.room_redact(
room_id=room.room_id,
event_id=event.event_id,
reason=reason
)
# Enviar advertencia
await client.room_send(
room_id=room.room_id,
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": f"⚠️ Mensaje eliminado: {reason}"
}
)
Caso práctico 3: Disparador de flujos de trabajo
if event.body.startswith("!workflow"):
parts = event.body.split()
workflow_name = parts[1] if len(parts) > 1 else "default"
params = " ".join(parts[2:]) if len(parts) > 2 else ""
# Llamar webhook de n8n
async with aiohttp.ClientSession() as session:
async with session.post(
f"http://n8n:5678/webhook/{workflow_name}",
json={"params": params, "user": event.sender}
) as r:
result = await r.text()
await client.room_send(
room_id=room.room_id,
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": f"Workflow {workflow_name}: {result}"
}
)
Tener en cuenta el cifrado E2EE
Los espacios de Matrix pueden estar cifrados de extremo a extremo. El bot solo puede leer mensajes sin cifrar, a menos que tenga acceso a las claves.
# Bot con E2EE usando matrix-nio
from nio import AsyncClient, MatrixRoom, RoomMessageText
from nio.crypto import OlmMachine
# Un bot con E2EE necesita:
# 1. Claves de dispositivo
# 2. Relación de confianza con otros dispositivos
# 3. Descifrado de mensajes
# Esto es complejo. Para empezar:
# - Usa el bot solo en espacios sin cifrar
# - O: utiliza una librería como pantalaimon
Consideraciones de seguridad
- Contraseña del bot: Usa una contraseña fuerte y almacénala de forma segura. Consulta Secretos.
- Permisos: El bot solo debe tener permisos de lectura y escritura, nunca de administrador.
- E2EE: En espacios cifrados, el bot solo puede leer si tiene las claves.
- Inyección de prompts: Los usuarios pueden intentar inyecciones. Consulta Inyección de prompts.
- Federación: Matrix es federado: los mensajes pueden ir a otros servidores.
Errores comunes
- Complejidad de E2EE: Los espacios cifrados requieren gestión de claves. Para empezar, usa espacios sin cifrar.
- Token vs. contraseña: Un token de acceso es mejor que una contraseña. Guárdalo después del inicio de sesión.
- Limitación de velocidad: Los servidores Matrix tienen límites. Implementa throttling.
- Respuestas demasiado largas: Matrix tiene un límite (~65 KB por mensaje). Divide las respuestas largas.
- Federación: El bot solo ve espacios en los que está. Los espacios remotos mediante federación funcionan de otra forma.
Enlaces de interés
- Bots de Matrix - Fundamentos de bots en Matrix.
- Ollama - Servidor de modelos.
- matrix-nio - Librería Python.
- Synapse - Servidor Matrix.
- RAG local - Base de conocimientos.
- Inyección de prompts - Seguridad.
Puntos clave:
- Matrix + Ollama: chat descentralizado con IA local.
- matrix-nio para bots en Python, matrix-js-sdk para JavaScript.
- El bot responde a menciones y comandos.
- RAG para preguntas frecuentes, moderación para seguridad, flujos de trabajo para automatización.
- E2EE es complejo; para empezar, usa espacios sin cifrar.
Preguntas frecuentes
¿Cómo creo un bot de Matrix?
¿Matrix o Discord para bots?
¿Funciona el bot en espacios cifrados?
¿Qué librería para bots de Matrix?
¿Necesito mi propio servidor?
¿Es seguro el bot?
¿Cuánto cuesta?
¿Para qué puedo usar el bot?
Fuentes y lecturas complementarias
- Matrix - Protocolo descentralizado.
- matrix-nio - Librería Python.
- Synapse - Servidor base.
- Ollama - Servidor de modelos local.


