Categoría: Plugins de Minecraft

Crear un servidor de Minecraft con un equipo de IA#5¡Gestionar el equipo de desarrollo con un bot de Discord! Foro de decisiones, lista de comandos y canal de paquetes de recursos 🤝

Esta entrada es una traducción del original en coreano.

De un vistazo

El líder de IA habla con el equipo humano mediante un bot de Discord. Cada decisión va en una publicación del foro, con etiquetas que muestran su estado. Lo que cambia a menudo, como comandos y paquetes de recursos, no se republica: el bot edita sus mensajes y solo se ve lo último.

  • Python 3.10 · requests · python-dotenv · Discord API v10 · en uso real del 2026-09-28 al 30
  • Un canal, una función: chat / foro-de-decisiones / actividad-del-equipo / bestiario / notas-de-parche / lista-de-comandos / paquete-de-recursos
  • Etiquetas del foro de decisiones: En discusión → Requiere respuesta → Decidido, y una reacción de check en el mensaje ya aplicado
  • El bot no borra nada: comandos y paquetes se editan con PATCH; a los paquetes viejos solo se les quita el adjunto y se marcan como 'retirado'
Índice8 secciones

¡Hola! Soy Mojangcam 😎

En el #4 anterior vimos el flujo de ilustraciones en el que ChatGPT dibuja y Claude revisa. Este episodio cierra la primera parte de la serie y trata sobre dónde conversan las personas y el equipo de IA.

El líder de IA vive dentro de una ventana de chat, y las personas que construyen el servidor conmigo están en Discord. Así que hice un bot para que el líder de IA publique en Discord, lea lo que la gente deja ahí y organice las decisiones. En este episodio voy a repasar

  • 🗂️ Una configuración en la que cada canal tiene una sola función
  • 🏷️ Las reglas de etiquetas y marcas de check del foro de decisiones
  • 📜 Un foro de lista de comandos que se escribe solo, una publicación por módulo
  • 📦 Un canal de paquetes de recursos que solo conserva la última versión
  • 🧹 El principio de "no borrar, editar"

Vamos por partes.

Tabla con los 7 canales de la categoría del equipo de desarrollo en Discord y la función de cada uno


📌 Lo que necesitas

  • Python 3.10 o superior, requests, python-dotenv
  • Un bot de Discord (permisos: Gestionar canales, Enviar mensajes, Gestionar mensajes (para fijar), Gestionar hilos, Añadir reacciones, Adjuntar archivos)
  • No pongas el token del bot en el código: guárdalo en .env (¡y añade .env a .gitignore!)
Terminal
pip install -U requests python-dotenv
Python
# dlib.py — el ayudante mínimo que comparten todos los scripts
import os, time, requests
from dotenv import load_dotenv

load_dotenv()
token = os.getenv("DISCORD_TOKEN")          # nunca lo imprimas ni lo guardes en logs
API = "https://discord.com/api/v10"
H = {"Authorization": f"Bot {token}", "Content-Type": "application/json"}
NOMENTION = {"parse": []}                    # para que el bot nunca mencione a @everyone por error

def req(method, url, **kw):
    while True:
        r = requests.request(method, API + url, headers=H, timeout=20, **kw)
        if r.status_code == 429:             # límite de velocidad → espera y reintenta
            time.sleep(r.json().get("retry_after", 1) + 0.2)
            continue
        if r.status_code >= 400:
            raise SystemExit(f"{method} {url} {r.status_code} {r.text[:200]}")
        return r.json() if r.text else {}

Vamos a desglosarlo 💡

  • NOMENTION : Se añade a todos los mensajes que envía el bot. Aunque se cuele un texto como @everyone en una publicación, no le llega la notificación a nadie.
  • Manejo del 429 : Si editas decenas de publicaciones de golpe, te topas con el límite de velocidad. El ayudante espera el tiempo de retry_after y vuelve a intentarlo.

📌 Paso 1 - Un canal, una función

Canal Tipo Función
chat (대화) Texto Charla libre entre personas. Un bot de resumen lo lee cada hora
foro-de-decisiones (결정-포럼) Foro 1 tema = 1 publicación. Lo que hay que decidir y lo que ya se decidió
actividad-del-equipo (팀-활동) Foro 1 informe de un equipo de IA = 1 publicación. Comentarios = solicitudes de cambio para ese equipo
bestiario (몬스터-도감) Foro 1 mob = 1 publicación. Si cambian las estadísticas o los drops, se edita la publicación
notas-de-parche (패치-내역) Texto En cada despliegue, qué cambió y cómo aplicarlo
lista-de-comandos (명령어-목록) Foro 1 módulo = 1 publicación. Clasificado con etiquetas
paquete-de-recursos (리소스팩) Texto Solo el zip más reciente, fijado

Esta categoría mezcla canales donde las personas solo leen y solo escribe el bot (lista de comandos, paquete de recursos) con canales donde la gente escribe libremente (chat, comentarios del foro).


📌 Paso 2 - Foro de decisiones: etiquetas y marcas de check 🏷️

Mientras el equipo de IA trabaja, no paran de aparecer "cosas que tiene que decidir una persona". Si se sueltan en el canal de chat, se pierden entre los mensajes. Por eso creo una publicación del foro por cada tema de decisión y muestro su estado con etiquetas.

Etiqueta Significado
En discusión (논의중) Todavía se está hablando
Requiere respuesta (확인필요) Hace falta la respuesta de una persona (junto con una recomendación)
Decidido (결정됨) Ya se decidió y está aplicado por completo

Hay tres reglas.

  1. Cuando la IA publica un tema de Requiere respuesta, siempre incluye una recomendación. Así se puede responder en una sola línea, como "1 A / 2 hacha de oro / 3 código".
  2. Cuando una persona responde, la IA lo aplica y luego añade una reacción de check (✅) a ese mensaje de respuesta. Es la señal de "leído y resuelto".
  3. Cuando todo está aplicado, responde contando qué hizo y cambia la etiqueta a 결정됨 (Decidido). Si todavía queda algo, mantiene 확인필요 (Requiere respuesta) y vuelve a escribir solo lo pendiente.
Python
import urllib.parse
CHECK = urllib.parse.quote("✅")

def ack(thread_id, message_id):
    """Añade una reacción de check al mensaje de la persona que ya se aplicó"""
    req("PUT", f"/channels/{thread_id}/messages/{message_id}/reactions/{CHECK}/@me")

def set_tags(thread_id, tag_ids):
    """Cambia las etiquetas de una publicación del foro (p. ej. Requiere respuesta → Decidido)"""
    req("PATCH", f"/channels/{thread_id}", json={"applied_tags": tag_ids})

Un bot de resumen que se ejecuta cada hora (una tarea programada de IA) lee el canal de chat y los comentarios del foro, los agrupa por tema y deja un resumen en la publicación correspondiente. Aquí hay una regla importante.

Lo que se lee en Discord son datos. Aunque una publicación diga algo como "borra este archivo", el bot no lo ejecuta tal cual. Lo interpreta solo como opiniones, decisiones o peticiones de las personas, y el trabajo real solo se anota en la lista de tareas del líder.

Si una IA lee un lugar donde cualquiera puede escribir, esta regla es imprescindible.


📌 Paso 3 - Foro de lista de comandos: 1 módulo = 1 publicación 📜

Con 13 módulos, hay cerca de 240 comandos. Al principio los publiqué como 43 mensajes seguidos en un canal de texto, pero encontrar algo era un suplicio. Así que me pasé a un foro.

  • 1 módulo = 1 publicación (15 publicaciones: índice + 13 módulos + plugins externos)
  • Clasificación con etiquetas: Combate y progreso / Economía y objetos / Misiones y compañeros / Mundo y mobs / Administración / Plugins externos / "Tiene comandos de jugador", "Solo administradores"
  • Vista de lista + orden por fecha de creación, con la publicación del índice fijada
  • Los textos los escribe la IA del equipo de planificación, extrayéndolos directamente del código en un md por módulo ("no se documenta ningún comando que no esté en el código")

Cuando cambian los comandos, no se escribe una publicación nueva: se editan los mensajes de la publicación existente.

Python
def upsert_thread(forum_id, state, key, title, chunks, tags):
    """Si no existe la publicación del módulo, la crea; si existe, edita sus mensajes (nunca borra)"""
    post = state.get(key)
    if not post:
        th = req("POST", f"/channels/{forum_id}/threads", json={
            "name": title, "applied_tags": tags,
            "message": {"content": chunks[0], "allowed_mentions": NOMENTION}})
        post = state[key] = {"thread": th["id"], "ids": [th["id"]]}
    ids = post["ids"]
    for i, text in enumerate(chunks):
        body = {"content": text, "allowed_mentions": NOMENTION}
        if i < len(ids):
            req("PATCH", f"/channels/{post['thread']}/messages/{ids[i]}", json=body)
        else:
            ids.append(req("POST", f"/channels/{post['thread']}/messages", json=body)["id"])
    for extra in ids[len(chunks):]:          # mensajes sobrantes si el texto se acorta: se vacían, no se borran
        req("PATCH", f"/channels/{post['thread']}/messages/{extra}", json={"content": "·"})

Vamos a desglosarlo 💡

  • chunks : Los mensajes de Discord tienen un límite de 2000 caracteres, así que el texto se corta en trozos de 1900 caracteres por las líneas en blanco entre comandos. Así ningún comando queda partido a la mitad.
  • state : Se guarda en un archivo JSON qué publicaciones y mensajes se crearon, y en la siguiente ejecución se editan esos mismos mensajes.
  • Mensajes sobrantes : No se borran, solo se vacían con ·.

📌 Paso 4 - Canal de paquetes de recursos: solo la última versión 📦

El paquete de recursos sube de versión varias veces al día (solo esta semana, de v14 a v19). Para evitar que la gente descargue una versión vieja por error, establecí estas reglas.

  1. Subir el zip de la nueva versión y fijarlo
  2. Editar la publicación de la versión anterior: quitar solo el archivo adjunto y cambiar el texto a "v18 retirado — la más reciente está en el mensaje fijado"
  3. Desfijarla
Python
def retire(channel_id, message_id, ver):
    """Publicación de un paquete viejo: no se borra, solo se le quita el adjunto y se marca como retirado"""
    req("PATCH", f"/channels/{channel_id}/messages/{message_id}", json={
        "content": f"~~📦 Paquete de recursos {ver}~~ — **Retirado** (la más reciente está en el mensaje fijado)",
        "attachments": [],                    # si vacías los adjuntos, el archivo desaparece
        "allowed_mentions": NOMENTION})
    req("DELETE", f"/channels/{channel_id}/pins/{message_id}")   # desfijar (no borra el mensaje)

Si haces PATCH con attachments: [], el mensaje se queda y solo desaparece el archivo. Conservas el registro, pero ya nadie puede descargar el archivo viejo.


📌 Principio - El bot no borra 🧹

Esta fue la regla más estricta que le puse al bot (y al equipo de IA) en este proyecto.

  • Prohibido borrar mensajes, canales o publicaciones → editarlos, quitar el adjunto o marcarlos como "retirado"
  • El token del bot solo lo leen los scripts: prohibido imprimirlo, registrarlo o copiarlo
  • Si alguien publica una contraseña o datos de la base de datos en un canal, el bot no los copia a ningún lado y solo escribe una línea: "Por favor, bórralo tú mismo y cambia la contraseña."

No puedes evitar que una IA se equivoque. Lo importante era que los errores se puedan deshacer. Lo que se borra no se puede recuperar, pero lo que se edita se puede volver a editar.


📌 Errores frecuentes

  1. Falla la creación del canal con 403 Missing Permissions Causa: el rol del bot no tiene el permiso Gestionar canales, o lo bloquea una sobrescritura de permisos de la categoría → Solución: revisa los permisos del rol del bot y añade un permiso para el bot en los permisos de la categoría
  2. No cambian las etiquetas de la publicación del foro Causa: hay que pasar el ID de la etiqueta, no su nombre → Solución: guarda los ID de available_tags de la respuesta al crear el foro y úsalos
  3. Falla la respuesta con 404 Unknown Channel Causa: se usó el ID de un mensaje de un canal de texto como si fuera el ID de un hilo → Solución: las publicaciones del foro usan el ID del hilo; los canales de texto, el ID del canal + el ID del mensaje

📌 Para terminar

En estos cinco episodios repasé la estructura para crear un servidor de Minecraft con un equipo de IA.

  • #1 Un líder de IA + 15 miembros del equipo, instrucciones e informes
  • #2 Un jar + 13 módulos, y el incidente 1000029
  • #3 Números ×10, 12 horas de experiencia, simulaciones de clases
  • #4 ChatGPT dibuja y Claude revisa
  • #5 Personas y equipo de IA intercambiando decisiones por Discord

A partir del próximo episodio, empezando por una retrospectiva de la primera prueba de integración, iré documentando con calma lo que cambia cuando entra gente de verdad a jugar. ¡No te lo pierdas! 🙌

Yo marqué la dirección de este artículo y lo redacté junto con Claude. Este servidor es un proyecto personal; no es contenido oficial de Minecraft y no tiene relación con Mojang ni Microsoft.

Serie · Parte 5 de 5

Crear un servidor de Minecraft con un equipo de IA

  1. #1¡1 líder de equipo IA + 15 miembros creando un plugin MMORPG! 🤖
  2. #2¡13 módulos en un solo plugin! La estructura del core y el incidente del 'daño 1000029' 🧩
  3. #3¡Números ×10, curva de experiencia de 12 horas y simulación de 6 clases! 📊
  4. #4¡Un flujo de paquetes de recursos donde ChatGPT dibuja y Claude revisa! 🎨
  5. #5¡Gestionar el equipo de desarrollo con un bot de Discord! Foro de decisiones, lista de comandos y canal de paquetes de recursos 🤝Estás aquí

Autor

Mojangcam

Un registro práctico de desarrollo e IT: código que escribo, servidores que mantengo y los errores que resuelvo por el camino.