# Flujos IA

Documento interno para definir, crear y mantener `flujo_*` dentro de `ia_prompts`.

Para ejemplos minimos listos para copiar y pegar:
- ver [PROMPTS_Y_FLUJOS_EJEMPLO.md](/c:/Apache24/htdocs/sidelink/backend/IA/PROMPTS_Y_FLUJOS_EJEMPLO.md)

Para la especificacion estricta del nuevo formato ejecutable por backend:
- ver [FLOW_STANDARD_V1.md](/c:/Apache24/htdocs/sidelink/backend/IA/FLOW_STANDARD_V1.md)

Para documentacion operativa y de generacion asistida:
- ver [GUIA_TECNICA_FLOW_STANDARD_V1.md](/c:/Apache24/htdocs/sidelink/backend/IA/GUIA_TECNICA_FLOW_STANDARD_V1.md)
- ver [GUIA_PARA_IA_GENERAR_FLUJOS_V1.md](/c:/Apache24/htdocs/sidelink/backend/IA/GUIA_PARA_IA_GENERAR_FLUJOS_V1.md)
- ver [GUIA_PARA_IA_GENERAR_PAQUETE_MODULAR.md](/c:/Apache24/htdocs/sidelink/backend/IA/GUIA_PARA_IA_GENERAR_PAQUETE_MODULAR.md)
- ver [GUIA_TECNICA_CATALOGO_RUNTIME.md](/c:/Apache24/htdocs/sidelink/backend/IA/GUIA_TECNICA_CATALOGO_RUNTIME.md)

## Que es un flujo

Un flujo es un JSON guardado en la tabla `ia_prompts` con clave `flujo_xxx`.

Ejemplos:
- `flujo_soporte`
- `flujo_ventas`
- `flujo_mudanza`

El flujo no es un motor de reglas backend. Es una guia estructurada que la IA interpreta para:
- decidir que dato pedir
- detectar que slot completar
- sugerir el siguiente paso
- detectar si ya corresponde derivar o cerrar

## Como funciona hoy

### Lo que garantiza el backend

- El backend busca `flujo_*` en la tabla `ia_prompts`.
- Solo valida que `content` sea JSON valido.
- Si el JSON parsea, lo manda al `prompt_core` dentro de `contexto.flujos_config`.
- El backend guarda `slots_detectados` en memoria por telefono.
- El backend vuelve a inyectar `slots_actuales` y `bloques_sugeridos` en el prompt del turno siguiente.
- El backend tambien expone `contexto.estado_backend` con hechos duros del runtime.
- Si ya existen flujos activos, el backend proyecta algunos hechos duros en slots reservados `_sys_*`.

### Lo que NO hace el backend hoy

- No valida schema de flujo.
- No interpreta `solo_si`.
- No interpreta `cuando`.
- No interpreta `accion`.
- No interpreta `area`.
- No decide el siguiente paso.
- No ejecuta ramas del flujo.

Todo eso lo interpreta la IA segun las reglas del `prompt_core`.

## Resumen operativo

Si vas a crear o modificar un flujo, pensa este JSON en 3 capas:

- raiz del flujo: define nombre, intencion y listas generales
- `slots`: define que datos queres capturar
- `pasos`: define en que orden pedir, decidir, derivar o cerrar

## Contrato real actual

### 1. Clave del flujo

La clave debe empezar con `flujo_`.

Ejemplo:
- `flujo_soporte`

### 2. Estructura base recomendada

No hay schema obligatorio backend. Esta es la convencion recomendada:

```json
{
  "nombre": "Flujo soporte tecnico",
  "descripcion": "Diagnostico inicial para problemas tecnicos",
  "version": 1,
  "intencion_principal": "prompt_soporte",
  "tool_permissions": {
    "buscar_cliente": true
  },
  "slots": {
    "tipo_problema": {
      "descripcion": "Tipo de inconveniente",
      "valores_validos": ["sin_servicio", "lentitud_cortes"],
      "obligatorio": true
    }
  },
  "pasos": [
    {
      "id": "pedir_tipo_problema",
      "tipo": "pregunta",
      "slot": "tipo_problema",
      "mensaje": "Preguntar si el problema es sin servicio o lentitud/cortes",
      "faltan": ["tipo_problema"]
    }
  ]
}
```

## Claves permitidas por nivel

### Claves de raiz del flujo

Estas son las claves que hoy conviene usar en el objeto principal:

- `nombre`
- `descripcion`
- `version`
- `intencion_principal`
- `tool_permissions`
- `slots`
- `pasos`

### Claves de cada slot

Estas son las claves recomendadas dentro de `slots.nombre_del_slot`:

- `descripcion`
- `valores_validos`
- `obligatorio`

### Claves de cada paso

Estas son las claves recomendadas dentro de cada objeto de `pasos`:

- `id`
- `tipo`
- `slot`
- `mensaje`
- `solo_si`
- `cuando`
- `accion`
- `area`
- `motivo`
- `faltan`

## Guia de la raiz del flujo

### `nombre`

Texto corto y legible para humanos.

Ejemplo:

```json
{
  "nombre": "Flujo soporte tecnico"
}
```

### `descripcion`

Resume el objetivo del flujo.

Ejemplo:

```json
{
  "descripcion": "Diagnostico inicial para soporte tecnico"
}
```

### `version`

Numero entero para control interno.

Ejemplo:

```json
{
  "version": 2
}
```

### `intencion_principal`

Debe apuntar a una clave real de prompt que el `prompt_core` pueda devolver.

Ejemplos validos:
- `prompt_soporte`
- `prompt_ventas`
- `prompt_cobranza`
- `prompt_mudanza`

Ejemplo:

```json
{
  "intencion_principal": "prompt_soporte"
}
```

### `tool_permissions`

Sirve para bloquear o habilitar tools desde el flujo, aunque el modelo se equivoque.

Claves soportadas:
- `buscar_cliente`
- `transferir_operador`
- `registrar_compromiso_pago`

Tambien se aceptan aliases legacy:
- `buscarCliente`
- `transferirOperador`
- `registrarCompromisoPago`

Valores soportados:
- `true`
- `false`

Ejemplo:

```json
{
  "tool_permissions": {
    "buscar_cliente": false
  }
}
```

Regla de merge:
- si algun flujo activo pone una tool en `false`, gana `false`
- `true` solo habilita si ningun flujo activo la nego

## Guia de `slots`

## Que es un slot

Un slot es un dato que queres capturar o reutilizar en el flujo.

Ejemplos:
- `dni`
- `localidad`
- `tipo_problema`
- `resultado_final`

### Estructura recomendada de un slot

```json
{
  "tipo_problema": {
    "descripcion": "Tipo de inconveniente tecnico",
    "valores_validos": ["sin_servicio", "lentitud_cortes", "otro"],
    "obligatorio": true
  }
}
```

### `descripcion`

Texto corto para explicarle a la IA que significa el slot.

### `valores_validos`

Lista de valores esperados para ese slot.

No es una validacion dura backend. Es una guia para el `prompt_core` y para los prompts de dominio.

Tipos de valores que conviene usar:
- valores cerrados y predecibles
- strings de negocio cortos
- marcadores especiales como `__NO_DISPONIBLE__`

Ejemplos buenos:
- `["si", "no"]`
- `["resuelto", "no_resuelto"]`
- `["sin_servicio", "lentitud_cortes", "otro"]`
- `["texto", "__NO_DISPONIBLE__"]`

Ejemplos malos:
- listas larguisimas con frases completas
- valores ambiguos como `"normal"` o `"raro"`
- textos distintos para representar lo mismo

### `obligatorio`

Booleano:
- `true`
- `false`

Sirve para documentar si el flujo idealmente necesita ese slot.
El backend no lo impone por si solo.

### Reglas practicas para nombrar slots

- usar minusculas
- usar `_` como separador
- usar nombres cortos
- usar un nombre por dato, no por pregunta

Ejemplos buenos:
- `dni`
- `nombre_apellido`
- `tipo_problema`
- `horarios_afectados`

Ejemplos malos:
- `pregunta_1`
- `dato_del_cliente_que_dice_si_tiene_luz_roja`
- `respuesta`

### Slots de sistema reservados

Si el flujo ya esta activo, `slots_actuales` puede incluir slots `_sys_*` proyectados por backend.

Hoy conviene considerar:
- `_sys_cliente_verificado`
- `_sys_dni_validado`

Ejemplo:

```json
{
  "flujo_soporte": {
    "_sys_cliente_verificado": "si",
    "_sys_dni_validado": "30111222"
  }
}
```

Reglas:
- no los declares en `slots` salvo que tengas un motivo fuerte de documentacion interna
- no los detectes desde texto del cliente
- no los inventes en el prompt
- usalos en `solo_si` o `cuando` cuando necesites condicionarte por estado real del backend

## Guia de `pasos`

## Que es un paso

Un paso es una unidad del flujo.

Cada paso deberia representar una sola cosa:
- pedir un dato
- priorizar una decision
- sugerir una derivacion
- cerrar un caso

### Estructura recomendada de un paso

```json
{
  "id": "pedir_tipo_problema",
  "tipo": "pregunta",
  "slot": "tipo_problema",
  "mensaje": "Preguntar si el problema es sin servicio o lentitud/cortes",
  "faltan": ["tipo_problema"]
}
```

### `id`

Identificador unico y estable del paso.

Convenciones recomendadas:
- usar minusculas
- usar `_`
- describir la accion

Ejemplos:
- `pedir_dni`
- `verificar_cliente`
- `derivar_no_resuelto`
- `cerrar_resuelto`

### `tipo`

Valores recomendados:
- `pregunta`
- `decision`
- `accion`
- `cierre`

Regla practica:
- `pregunta`: cuando el siguiente mensaje al cliente debe pedir o guiar una respuesta
- `decision`: cuando solo queres marcar una bifurcacion logica
- `accion`: cuando queres sugerir una derivacion o una ejecucion
- `cierre`: cuando el flujo ya deberia terminar

### `slot`

Nombre del slot asociado a ese paso.

Usalo principalmente en pasos de tipo `pregunta`.

Debe coincidir con una clave existente en `slots`, salvo que sea una convencion muy puntual y documentada.

Ejemplo:

```json
{
  "slot": "tipo_problema"
}
```

### `mensaje`

Describe que deberia preguntar o indicar la IA.

No hace falta escribir el texto exacto que se enviara al cliente.
Conviene escribir la intencion del paso, no un copy final rigido.

Ejemplos buenos:
- `Preguntar si el problema ocurre en uno o todos los dispositivos`
- `Indicar reiniciar el modem y luego consultar el resultado`

Ejemplos malos:
- textos demasiado largos
- parrafos cerrados como si fueran respuesta final
- copys con detalles de tono que deberian vivir en el prompt de dominio

### `solo_si`

Condicion para considerar aplicable un paso.

Formato recomendado:

```json
{
  "solo_si": {
    "_sys_cliente_verificado": "si",
    "alcance_problema": "todos_los_dispositivos"
  }
}
```

Interpretacion esperada:
- todas las condiciones deben cumplirse
- si no se cumplen, ese paso no deberia priorizarse

Usalo para:
- bloquear pasos hasta tener cierto estado
- no pedir pruebas antes de validar al cliente
- no ofrecer ramas incorrectas

### `cuando`

Condicion que, si ya se cumple, hace que el paso deba priorizarse.

Formato recomendado:

```json
{
  "cuando": {
    "resultado_final": "no_resuelto"
  }
}
```

Usalo para:
- derivar cuando ya se detecto una condicion de corte
- cerrar cuando ya se resolvio
- avanzar al siguiente paso si ya hay un dato completado

### `accion`

Convencion de alto nivel que el `prompt_core` y el prompt de dominio pueden interpretar.

Valores recomendados:
- `buscar_cliente`
- `derivar`
- `registrar_compromiso`
- `finalizar`
- `ninguno`

Regla practica:
- si el paso es de tipo `accion`, casi siempre deberia tener `accion`
- si el paso es de tipo `cierre`, normalmente deberia tener `accion: "finalizar"`

### `area`

Se usa cuando `accion = derivar`.

Hoy la resolucion real del nombre del area ocurre despues, al ejecutar `transferirOperador`, usando `config.mjs`.

Areas reales configuradas hoy:
- `tecnico`
- `cobranza`
- `ventas`
- `baja`
- `operador`

No conviene inventar areas nuevas si no estan en `config.mjs`.

### `motivo`

Texto corto que resume por que se llega a ese paso de accion o cierre.

Ejemplos buenos:
- `Diagnostico inicial realizado sin resolucion`
- `Lead de ventas con datos minimos completos`
- `No se pudo verificar al cliente con los datos informados`

### `faltan`

Lista orientativa de slots faltantes para ese paso.

Formato:

```json
{
  "faltan": ["dni", "localidad"]
}
```

Usalo sobre todo en pasos de tipo `pregunta`.

## Valores especiales y convenciones

### `__NO_DISPONIBLE__`

Usalo cuando el cliente:
- no puede hacer una prueba
- no tiene acceso al dato
- no puede confirmar algo pero eso mismo ya es informacion util

Ejemplo:

```json
{
  "resultado_final": "__NO_DISPONIBLE__"
}
```

### `*`

Si se usa dentro de `cuando` o `solo_si`, significa:
- cualquier valor no vacio

Ejemplo:

```json
{
  "cuando": {
    "dni": "*"
  }
}
```

Importante:
- el backend no interpreta `*`
- solo funciona si el `prompt_core` fue instruido para entenderlo

### Valores booleanos de negocio

Si necesitas una respuesta simple, conviene usar:
- `si`
- `no`

No mezclar:
- `si` con `true`
- `no` con `false`
- `yes` con `si`

Elegi una sola convencion y mantenela en todo el flujo.

## Estructura recomendada de `slots_detectados`

Este es el formato mas seguro y recomendado:

```json
{
  "flujo_soporte": {
    "luces_rojas": "si",
    "resultado_final": "no_resuelto"
  }
}
```

Ese formato se guarda luego en `slots_actuales`.

## Estructura recomendada de `bloques_sugeridos`

Formato recomendado:

```json
[
  {
    "flujo": "flujo_soporte",
    "siguiente_paso": "derivar_luz_roja",
    "faltan": []
  }
]
```

Claves recomendadas:
- `flujo`
- `siguiente_paso`
- `faltan`

## Como escribir un flujo nuevo

Checklist minima:

- definir la `intencion_principal`
- listar solo los `slots` realmente utiles
- usar nombres cortos y estables
- decidir que pasos son `pregunta`
- decidir que pasos son `accion`
- definir si hay cortes de derivacion
- definir si hay cierre
- si hace falta, agregar `tool_permissions`

Orden recomendado:

1. pedir identificacion o dato inicial si aplica
2. validar o clasificar rama
3. pedir datos tecnicos o comerciales
4. sugerir prueba o accion
5. cerrar o derivar

## Patrones utiles

### Patron: pedir un dato

```json
{
  "id": "pedir_localidad",
  "tipo": "pregunta",
  "slot": "localidad",
  "mensaje": "Preguntar la localidad",
  "faltan": ["localidad"]
}
```

### Patron: ejecutar algo cuando ya tengo un dato

```json
{
  "id": "verificar_cliente",
  "tipo": "accion",
  "cuando": {
    "dni_cuit": "*"
  },
  "accion": "buscar_cliente",
  "motivo": "Verificar que la persona sea cliente"
}
```

### Patron: derivar por condicion cumplida

```json
{
  "id": "derivar_no_resuelto",
  "tipo": "accion",
  "cuando": {
    "resultado_final": "no_resuelto"
  },
  "accion": "derivar",
  "area": "tecnico",
  "motivo": "Diagnostico inicial realizado sin resolucion"
}
```

### Patron: cerrar el flujo

```json
{
  "id": "cerrar_resuelto",
  "tipo": "cierre",
  "cuando": {
    "resultado_final": "resuelto"
  },
  "accion": "finalizar",
  "motivo": "El inconveniente fue resuelto"
}
```

## Errores comunes

- Pensar que `accion` ejecuta algo por si solo.
- Pensar que `cuando` o `solo_si` los resuelve el backend.
- Meter logica compleja tipo `and`, `or`, `not`, comparaciones numericas o anidaciones profundas.
- Duplicar reglas generales del prompt dentro del flujo.
- Crear slots que representan preguntas en vez de datos.
- Usar areas que no existen en `config.mjs`.
- Dar por validado un DNI solo porque aparecio en el texto del cliente.
- Armar flujos gigantes con demasiados slots y ramas.

## Ejemplo minimo usable

```json
{
  "nombre": "Flujo soporte tecnico",
  "descripcion": "Diagnostico inicial para problemas tecnicos",
  "version": 1,
  "intencion_principal": "prompt_soporte",
  "slots": {
    "tipo_problema": {
      "descripcion": "Tipo de inconveniente tecnico",
      "valores_validos": ["sin_servicio", "lentitud_cortes"],
      "obligatorio": true
    },
    "luces_rojas": {
      "descripcion": "Si el modem muestra luces rojas",
      "valores_validos": ["si", "no", "__NO_DISPONIBLE__"],
      "obligatorio": true
    },
    "resultado_final": {
      "descripcion": "Resultado final de la prueba",
      "valores_validos": ["resuelto", "no_resuelto"],
      "obligatorio": false
    }
  },
  "pasos": [
    {
      "id": "pedir_tipo_problema",
      "tipo": "pregunta",
      "slot": "tipo_problema",
      "mensaje": "Preguntar si el problema es sin servicio o lentitud/cortes",
      "faltan": ["tipo_problema"]
    },
    {
      "id": "pedir_luces_rojas",
      "tipo": "pregunta",
      "slot": "luces_rojas",
      "mensaje": "Preguntar si observa una luz roja en el modem",
      "faltan": ["luces_rojas"]
    },
    {
      "id": "derivar_luz_roja",
      "tipo": "accion",
      "cuando": {
        "luces_rojas": "si"
      },
      "accion": "derivar",
      "area": "tecnico",
      "motivo": "Posible falla fisica o corte detectado por luz roja"
    },
    {
      "id": "pedir_resultado",
      "tipo": "pregunta",
      "slot": "resultado_final",
      "mensaje": "Preguntar si el problema se resolvio o sigue igual",
      "faltan": ["resultado_final"]
    },
    {
      "id": "derivar_no_resuelto",
      "tipo": "accion",
      "cuando": {
        "resultado_final": "no_resuelto"
      },
      "accion": "derivar",
      "area": "tecnico",
      "motivo": "Diagnostico inicial realizado sin resolucion"
    }
  ]
}
```
