Construyendo un Agente para Slay the Spire 2 con LLMs Locales: Lecciones y Problemas Abiertos

Un desarrollador ha creado un agente que juega Slay the Spire 2 usando LLMs locales a través de KoboldCPP/Ollama. El juego se expone como una API REST mediante un mod de la comunidad, y el agente se sitúa en el medio: lee el estado del juego → llama al LLM con herramientas → ejecuta la acción → repite.
Configuración y Rendimiento
La configuración utiliza Qwen3.5-27B (Q4_K_M) en RTX 4090 a través de KoboldCPP. Métricas de rendimiento: ~10 segundos por acción, ~88% de tasa de éxito en acciones. Mejor resultado: vencer al jefe del Acto 1. El proyecto está disponible en GitHub en https://github.com/Alex5418/STS2-Agent.
Lo que Funciona
- Enrutamiento de herramientas basado en estado — En lugar de exponer 20+ herramientas a la vez, solo se proporcionan 1-3 herramientas relevantes al estado actual del juego. Combate obtiene
play_card,end_turn,use_potion. Pantalla del mapa obtienechoose_map_node. Esto redujo drásticamente las llamadas a herramientas alucinadas. - Modo de herramienta única — Los modelos pequeños no pueden predecir cómo cambia el estado del juego después de una acción (por ejemplo, los índices de cartas cambian después de jugar una carta). Por lo tanto, solo se ejecuta la primera llamada a herramienta por respuesta, luego se vuelve a obtener el estado del juego y se le pregunta al modelo nuevamente. Más lento pero mucho más confiable.
- Analizador de llamadas a herramientas basado en texto (respaldo) — KoboldCPP a menudo genera llamadas a herramientas como texto en lugar de JSON estructurado. Un respaldo de regex con múltiples patrones captura formatos como:
json [{"name": "play_card", "arguments": {...}}],Made a function call ... to play_card with arguments = {...},play_card({"card_index": 1, "target": "NIBBIT_0"}), y menciones simples de herramientas sin argumentos comoend_turn. Esto recupera quizás 15-20% de acciones que de otro modo se perderían. - Guardia de energía — Seguimiento en el lado del cliente de la energía restante. Si el modelo intenta jugar una carta que no puede pagar, se bloquea la llamada a la API y el turno termina automáticamente. Esto evita el bucle de error más común (el modelo reintenta la misma carta inasequible 3+ veces).
- Espera inteligente durante turnos enemigos — Durante el turno del enemigo, el estado del juego dice "Play Phase: False". En lugar de desperdiciar una llamada al LLM en esto, el agente sondea cada 1s hasta que sea el turno del jugador nuevamente.
Problemas Abiertos
- El modelo no sigue consistentemente las reglas del prompt del sistema — El prompt del sistema dice cosas como "si la intención del enemigo es Ataque, juega cartas de Defensa PRIMERO". El modelo sigue esto quizás el 30% del tiempo. El otro 70% simplemente juega ataques sin importar. Soluciones intentadas: redacción más fuerte ("DEBES bloquear primero"), ejemplos de pocos disparos en el prompt, inyección de pistas calculadas ("ADVERTENCIA: 15 de daño entrante"). Ninguna es confiable. Pregunta: ¿Hay una mejor estrategia de prompting para que modelos pequeños sigan reglas condicionales? ¿O es esta una limitación fundamental en 27B?
- Confiabilidad en llamadas a herramientas con KoboldCPP — Incluso con el analizador de texto de respaldo, alrededor del 12% de las respuestas no producen una llamada a herramienta utilizable. El modelo a veces genera bloques
<think></think>vacíos seguidos de JSON malformado. La capa de compatibilidad OpenAI de Ollama también ocasionalmente devuelveargumentscomo una cadena en lugar de un diccionario. Pregunta: ¿Alguien ha encontrado un modelo que sea particularmente confiable en llamadas a herramientas en el rango de 14-30B? El desarrollador probó brevemente Phi-4 (14B) pero no ha hecho una comparación adecuada. Considerando Mistral-Small o Command-R. - Gestión de ventana de contexto — Cada estado del juego es de ~800-1500 tokens como markdown. Con el prompt del sistema (~500 tokens) y el historial de conversación, el contexto se llena rápidamente. Actualmente mantiene solo los últimos 5 intercambios y reinicia el historial en transiciones de estado (combate → mapa, etc.). Pero el modelo no tiene memoria entre combates — no puede aprender de errores. Pregunta: ¿Funcionaría un enfoque de resumen continuo? Como condensar el último combate en "Luchaste contra Jaw Worm. Recibiste 15 de daño porque no bloqueaste en el turno 2. Ganaste en 4 turnos."
- Salida estructurada mejorada de modelos locales — El problema central es necesitar que el modelo genere una llamada a herramienta JSON, pero lo que realmente quiere hacer es pensar primero en lenguaje natural. Qwen3.5 usa bloques
<think>que se eliminan, pero a veces el pensamiento y la llamada a herramienta se enredan. Pregunta: ¿Funcionaría mejor un enfoque de dos etapas? Etapa 1: "Analiza el estado del juego y decide qué hacer" (texto libre). Etapa 2: "Ahora genera exactamente una llamada a herramienta" (restringido). Esto duplica la latencia pero podría mejorar la confiabilidad. ¿Alguien ha probado este patrón? - Pruebas A/B entre modelos — El desarrollador tiene un sistema de registro JSONL que registra acciones para comparación.
📖 Leer la fuente completa: r/LocalLLaMA
👀 Ver también

3 Barreras Reales Tras Semanas de Pruebas de OpenClaw para Automatización Empresarial
Un usuario de Reddit informa tres bloqueadores tras semanas ejecutando OpenClaw en Windows 11 con Claude Haiku 4.5 + DeepSeek: la ejecución headless oculta las acciones del agente, las integraciones CRM fallan al transferir, y el agente orquestador solicita ejecución manual en lugar de actuar sobre los datos.

Cómo un asistente personal de IA transformó la gestión de mi cuenta de Twitter.
Descubre cómo un asistente personal de IA revolucionó la gestión de una cuenta de Twitter con un mayor compromiso y eficiencia. Aprende de esta historia real de éxito proveniente de la comunidad de OpenClaw.

Usuario no técnico construye y despliega sitio web usando Claude AI desde su teléfono.
Un usuario sin experiencia en programación construyó e implementó un sitio web completo desde su teléfono en una hora usando Claude AI. Crearon una pantalla de carga falsa de Portal 3 para una broma del Día de los Inocentes describiendo los requisitos en lenguaje sencillo y haciendo que Claude generara especificaciones y código.

Optimizando la retención de contexto de Claude cargando habilidades bajo demanda.
El cambio a un sistema basado en habilidades para Claude AI resolvió problemas de contexto, permitiendo que las sesiones duren de 2 a 3 veces más y mejorando la calidad de los resultados.