> ## Documentation Index
> Fetch the complete documentation index at: https://vantsgg.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Documentación interna de VANTS, la plataforma de esports, escrita en español. Cubre siete repositorios de la organización de GitHub VANTSNET y dos de la cuenta feispla: el prototipo VANTSNET, que se llama igual que la organización, y vantsoport.
> Empieza por /mapa-del-codigo para saber qué repositorio y qué carpeta tocar, y consulta /glosario para los términos propios como pt_, mm_, RR, VANTS-BUS o VANTCALL.
> Cuando un componente existe en varios repositorios, estas páginas describen la versión de Vantsgames salvo que digan otra cosa. El esquema de la base de datos se versiona en VantsBasededatos.
> La web y la API pública están en https://vants.vants.workers.dev. Rutas y respuestas: /referencia/api-publica. Tablas y estados: /referencia/esquema-base-de-datos.
> No inventes rutas, tablas, comandos ni variables de entorno: si algo no aparece aquí, revisa el código del repositorio correspondiente.

# flask-agents

> Web VANTS AI, cuartel general de los agentes de VANTS: el squad, el chat Vants Soporte con GLM y el consumidor de VANTS-BUS, en Flask sobre Vercel.

flask-agents es VANTS AI ([vants-ai.vercel.app](https://vants-ai.vercel.app)), la web del cuartel general de los agentes de VANTS. Presenta el squad, sirve el chat de soporte Vants Soporte y contiene el consumidor de [VANTS-BUS](https://vantsgg.mintlify.site/conexiones-entre-repositorios.md#vants-bus), el agente más antiguo del squad. Es una app Flask para Python 3.9 o superior, con Flask 3.1 y gunicorn 23, que se despliega en Vercel.

## El squad

| Agente | Generación | Dónde vive su código | Qué hace |
| - | - | - | - |
| Agente VANTS | Nuevo | `services/agent-service/` y workflow `agente.yml` de [Vantsgames](https://vantsgg.mintlify.site/repos/vantsgames.md) | Revisa la plataforma cada 30 minutos, decide con reglas y GLM, relanza lo que falla y guarda su memoria en Neon |
| VANTCALL (ORION) | Nuevo | `bot/` de Vantsgames | El mando del dueño en Discord: comandos `/agente` y avisos por mensaje directo. En la web aparece como ORION |
| Vants Soporte | Nuevo | Este repositorio: `/soporte` y `POST /api/chat` | Chat de soporte en español con GLM y un modo reglas de respaldo |
| Consumidor de VANTS-BUS | Viejo | `vants_bus/` de este repositorio | Escucha nueve tipos de evento del bus y publica `post.generated` sobre partidos y torneos |
| Agentes de desarrollo | Nuevo | `CLAUDE.md`, `DECISIONS.md`, ramas y PR | Construyen el código. Nada llega a producción sin pasar por una persona |

Solo Vants Soporte y el consumidor del bus tienen código en este repositorio. La web presenta a los demás con los datos de `agentes/squad.py`, los mismos que devuelve `GET /api/agentes`.

## Cómo se conecta el cuartel

El squad no vive en un solo repositorio: los recuadros indican dónde está el código de cada pieza. En azul, los agentes; en verde, el resto de piezas de VANTS; en amarillo, los servicios externos.

```mermaid theme={null}
flowchart TB
  subgraph VG [Vantsgames]
    WF["agente.yml<br/>cada 30 minutos"]
    AG["Agente VANTS<br/>services/agent-service"]
    MD["Mando por Discord<br/>VANTCALL (ORION) o vantsbot"]
    WV["Worker vants<br/>la web"]
  end
  subgraph FA ["flask-agents · VANTS AI en Vercel"]
    WEB["Web VANTS AI<br/>vants-ai.vercel.app"]
    SOP["Vants Soporte<br/>/soporte y /api/chat"]
    CON["Consumidor de VANTS-BUS<br/>vants_bus/"]
  end
  subgraph EXT [Servicios externos]
    GH[GitHub Actions]
    VC["Vercel<br/>proyecto vants"]
    GLM[GLM]
  end
  FW[vants-faceit-webhook]
  HUB["VANTS HUB<br/>vants-dev-launcher"]
  DB[VantsBasededatos]
  BUS[VANTS-BUS]
  N[("Neon<br/>tablas agent_*")]

  WF -->|lanza un ciclo| AG
  AG <-->|memoria y cola de órdenes| N
  MD <-->|"órdenes, incidentes y respuestas"| N
  DB -->|migraciones 25 y 26| N
  AG -->|chequea| WV
  AG -->|"chequea /healthz"| FW
  AG -->|revisa sus releases| HUB
  AG -->|relanza lo que falla| GH
  AG -->|revisa y relanza deploys| VC
  AG -->|function calling| GLM
  SOP -->|"chat/completions"| GLM
  WV -->|enlaza a VANTS AI| WEB
  FW -->|eventos de partidos| BUS
  WV -->|"inscripciones, clips y resultados"| BUS
  BUS -->|9 tipos de evento| CON
  CON -->|"post.generated"| BUS
  BUS -->|"eventos, incluido post.generated"| HUB

  classDef azul fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
  classDef verde fill:#dcfce7,stroke:#16a34a,color:#14532d
  classDef amarillo fill:#fef9c3,stroke:#ca8a04,color:#713f12
  classDef gris fill:#f3f4f6,stroke:#9ca3af,color:#4b5563
  class AG,MD,SOP,CON azul
  class WF,WV,WEB,FW,HUB,DB verde
  class GH,VC,GLM amarillo
  class BUS,N gris
```

* **Agente VANTS.** `agente.yml` lo lanza cada 30 minutos, a mano o cuando Vercel avisa de un deploy fallido. Revisa la web, vants-faceit-webhook, las releases de VANTS HUB, los workflows de Vantsgames, Neon, el último deploy de Vercel y, si está configurado, el servicio de matchmaking. Relanza una sola vez cada workflow que falla y hace como mucho dos redeploys de Vercel por commit. Decide con reglas y, si tiene GLM configurado, con function calling.
* **Mando por Discord.** `/agente comando` deja la orden en `agent_comandos` y el agente la atiende en su siguiente ciclo. Los incidentes y las respuestas llegan al dueño por mensaje directo. Lo hacen el bot VANTCALL y la Neon Function `vantsbot`, que no necesita el bot encendido. Los comandos están en [Bot de Discord](https://vantsgg.mintlify.site/referencia/bot-de-discord.md#agente).
* **VANTS AI.** Este repositorio no usa Neon ni llama al Agente VANTS. Vants Soporte habla con GLM por `chat/completions`, sin function calling, y el consumidor solo habla con VANTS-BUS. La web de Vantsgames enlaza a VANTS AI desde su portada.
* **Memoria del agente.** Las tablas `agent_*` salen de las migraciones 25 y 26 de [VantsBasededatos](https://vantsgg.mintlify.site/repos/vants-base-de-datos.md). Sus columnas están en [Esquema de la base de datos](https://vantsgg.mintlify.site/referencia/esquema-base-de-datos.md#agente).

## Estructura

```text theme={null}
main.py                 App Flask: registra páginas y API y arranca el consumidor del bus
api/index.py            Entrada del runtime Python de Vercel
endpoints/
  web.py                Páginas
  api.py                API JSON
agentes/squad.py        Datos del squad que muestra la web
soporte/
  ia.py                 Chat con GLM y caída al modo reglas
  reglas.py             Modo reglas: respuestas en español sin dependencias
templates/              Plantillas HTML de las páginas
static/                 CSS, JavaScript e imágenes
vants_bus/
  consumer.py           Consumidor del bus y reacciones por tipo de evento
  vants_bus_client.py   Cliente del bus, solo con la biblioteca estándar
  snippet_flask.py      Ejemplo de integración con Flask
public/                 Favicon
.env.example            Variables de entorno, sin valores
requirements.txt        Dependencias para Vercel: Flask y gunicorn
pyproject.toml          Dependencias del proyecto
```

Las páginas y los estáticos se copiaron tal cual del despliegue en vivo de VANTS AI. El backend se reconstruyó para responder a las mismas rutas.

## Páginas

| Ruta | Página |
| - | - |
| `/` | Portada: el squad, cómo trabajan los agentes y con qué están hechos |
| `/agente/<id>` | Ficha de un agente: `agente-vants`, `orion`, `soporte` o `dev-agents`. Con otro `id` responde 404 |
| `/soporte` | Chat de Vants Soporte |
| `/estado` | Panel de estado del squad |
| `/creador` | Espacio oficial del creador |

> [!NOTE]
>
> En `main`, `/estado` muestra siempre la vista local ("MODO LOCAL · SIN DATOS REALES"). `.env.example` incluye `AGENT_URL` y `AGENT_TOKEN` para consultar el estado real del Agente VANTS, pero el código de este repositorio todavía no las lee.

## API

| Método | Ruta | Respuesta |
| - | - | - |
| `GET` | `/healthz` | `{"ok": true, "servicio": "web-agentes-vants"}` |
| `GET` | `/api/agentes` | Los datos del squad de `agentes/squad.py` |
| `GET` | `/api/ia` | Estado del chat: `activo` (hay clave de GLM), `modelo`, `proveedor` y `fallback` |
| `POST` | `/api/chat` | Respuesta de Vants Soporte. Ver [Chat de soporte](#chat-de-soporte) |
| `GET` | `/vants/bus` | Estado del consumidor del bus |

`/vants/bus` indica en `activo` si el consumidor arrancó dentro de Flask y, en `consumidor`, los contadores `procesados`, `publicados` y `errores`, el último evento recibido (`ultimo_evento`) y el último error (`ultimo_error`). Solo refleja el consumidor que corre dentro de Flask, no el proceso independiente.

## Chat de soporte

`POST /api/chat` recibe el mensaje y, si quieres, el historial de la conversación:

```json theme={null}
{
  "mensaje": "quiénes son los agentes",
  "historial": [{ "rol": "user", "texto": "hola" }]
}
```

Y responde:

```json theme={null}
{ "ok": true, "modo": "llm", "modelo": "glm-4.5-flash", "respuesta": "..." }
```

* Con clave de GLM, responde el modelo (`"modo": "llm"`) como Vants Soporte y en español. Del historial usa los 10 últimos turnos.
* Sin clave, o si GLM falla, responde el modo reglas (`"modo": "reglas"`, `"modelo": null`). Busca palabras clave sin tener en cuenta los acentos y solo cuenta lo que ya dice la web. El chat nunca devuelve un error 500.
* Si falta `mensaje` o supera 2000 caracteres, responde 400 con `falta_mensaje` o `mensaje_demasiado_largo` en `error`.

## Variables de entorno

`.env.example` lista todas las variables. Son opcionales: sin ellas, la web arranca con esas funciones apagadas. La app las lee del entorno; en Vercel se definen en el proyecto.

| Variable | Para qué sirve | Si falta |
| - | - | - |
| `AGENT_LLM_KEY` | Clave de GLM para el chat | El chat responde en modo reglas |
| `AGENT_LLM_URL` | Proveedor compatible con la API de OpenAI | Usa `https://api.z.ai/api/paas/v4` |
| `AGENT_LLM_MODEL` | Modelo del chat | Usa `glm-4.5-flash` |
| `VANTS_BUS_URL` | URL de VANTS-BUS | El consumidor queda apagado |
| `VANTS_BUS_SECRET` | Secreto de `flask-agents` en el bus | El consumidor queda apagado |
| `VANTS_BUS_CURSOR` | Archivo donde el consumidor guarda su posición | Usa `vants_bus/.vants-cursor.json` |
| `AGENT_URL` y `AGENT_TOKEN` | Servicio HTTP del Agente VANTS | El código todavía no las usa |

## Consumidor del bus

`vants_bus/consumer.py` es el agente viejo del squad. Se identifica en el bus como `flask-agents` y escucha nueve tipos de evento: `match.finished`, `match.scheduled`, `match.canceled`, `tournament.inscriptions_opened`, `inscription.created`, `clip.published`, `clip.highlights_ready`, `game.session_started` y `alert.detected`.

### Reacciones

| Evento | Reacción |
| - | - |
| `match.finished` | Redacta `Resultado verificado: <equipo A> <marcador> - <marcador> <equipo B>` y lo publica como `post.generated` con `kind: "match_result"` y el `matchId` |
| `tournament.inscriptions_opened` | Publica `post.generated` con `kind: "tournament_open"` y el texto `Se abrieron las inscripciones: <nombre del torneo>` |
| Resto de tipos | Solo los registra en el log |

Los `post.generated` llevan `channel: "discord"` como destino previsto. Hoy los recibe [VANTS HUB](https://vantsgg.mintlify.site/repos/vants-dev-launcher.md), que los muestra como notificación "Nueva publicación".

Para cambiar las reacciones, edita `reaccionar` en `consumer.py` o pasa tu propia función a `iniciar(handler=...)`. La función recibe el evento y el cliente del bus. Con `tipos=[...]` cambias los tipos que escucha.

Si una reacción falla, el error se cuenta y el consumidor sigue con el siguiente evento. Si el bus no responde, registra el error y vuelve a intentarlo.

### Cómo arrancarlo

El consumidor necesita `VANTS_BUS_URL` y `VANTS_BUS_SECRET` (el secreto de `flask-agents`). Sin ellas queda apagado y la app funciona igual.

| Modo | Cómo arranca | Cuándo usarlo |
| - | - | - |
| Proceso independiente | `python vants_bus/consumer.py` | Modo recomendado. Necesita un proceso que se mantenga encendido |
| Dentro de Flask | `main.py` llama a `iniciar()` al cargar la app y el consumidor corre en un hilo | Cuando la app corre como servidor persistente. No arranca en Vercel (variable `VERCEL`), porque las funciones serverless no mantienen hilos en segundo plano |

Como VANTS AI corre en Vercel, allí el consumidor no arranca dentro de Flask. Para tenerlo en marcha, lánzalo como proceso independiente:

```bash theme={null}
export VANTS_BUS_URL=https://vants-bus.vants.workers.dev
export VANTS_BUS_SECRET=<secreto de flask-agents>
python vants_bus/consumer.py
```

En los dos modos, cada lectura espera hasta 20 segundos a que lleguen eventos (long-polling). La primera vez empieza desde el momento actual, sin procesar eventos antiguos. Tras un reinicio, continúa donde lo dejó.

## Publicar eventos desde los agentes

```python theme={null}
import os
from vants_bus.vants_bus_client import VantsBus, EVENTS

bus = VantsBus(os.environ["VANTS_BUS_URL"], "flask-agents", os.environ["VANTS_BUS_SECRET"])
bus.publish(EVENTS["HIGHLIGHTS_READY"], {"clipId": "abc", "game": "cs2"})
```

`EVENTS` es un diccionario con los 12 tipos del contrato. Qué proyecto consume cada tipo y cómo se firman las peticiones está en [Cómo se conectan los repositorios](https://vantsgg.mintlify.site/conexiones-entre-repositorios.md#vants-bus).

## Ejecutar en local

```bash theme={null}
pip install -r requirements.txt
python main.py  # http://localhost:8000
```

`python main.py` arranca el servidor de desarrollo de Flask en el puerto 8000, con el modo debug activado. En un servidor persistente también puedes usar `gunicorn main:app`. Para probar el chat:

```bash theme={null}
curl -s -X POST http://localhost:8000/api/chat \
  -H "Content-Type: application/json" \
  -d '{"mensaje": "quiénes son los agentes"}'
```

## Despliegue en Vercel

El runtime Python de Vercel busca `api/index.py`, que importa la app de `main.py`, e instala las dependencias de `requirements.txt`. Las páginas, los estáticos y la API salen de la misma app.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.