# Flow Standard V1

Especificacion base del formato de flujos que el backend debera poder leer y ejecutar.

Objetivo:
- tener un formato estricto
- evitar JSON ambiguos
- separar claramente IA, runtime y actions backend
- permitir una futura UI visual que genere este formato

## Principios

1. La IA no ejecuta el flujo.
2. El runtime backend ejecuta el flujo.
3. La IA se usa para:
   - detectar intencion
   - extraer slots desde lenguaje natural
   - redactar respuestas naturales cuando haga falta
4. Las actions reales siempre salen desde backend.
5. Lo deterministico debe ser configurable en datos, no hardcodeado por cliente.

## Estructura General

```json
{
  "id": "flujo_soporte_v1",
  "version": 1,
  "nombre": "Soporte tecnico",
  "intent_principal": "prompt_soporte",
  "settings": {},
  "tool_permissions": {},
  "slots": {},
  "backend_facts": {},
  "steps": []
}
```

## Campos de Raiz

### `id`

- tipo: `string`
- obligatorio: si
- debe ser unico dentro del tenant
- recomendado: `flujo_xxx_v1`

Ejemplo:

```json
{
  "id": "flujo_soporte_v1"
}
```

### `version`

- tipo: `number`
- obligatorio: si
- en V1 debe ser `1`

### `nombre`

- tipo: `string`
- obligatorio: si
- descripcion legible para humanos

### `intent_principal`

- tipo: `string`
- obligatorio: si
- debe mapear a una intencion real del `prompt_core`

Ejemplos:
- `prompt_soporte`
- `prompt_ventas`
- `prompt_cobranza`

### `settings`

- tipo: `object`
- obligatorio: no
- configuracion general del flujo

Claves soportadas en V1:

- `entry_step`
- `allow_tool_calls`
- `on_unmatched_input`

Ejemplo:

```json
{
  "settings": {
    "entry_step": "pedir_dni",
    "allow_tool_calls": true
  }
}
```

### `tool_permissions`

- tipo: `object`
- obligatorio: no
- sirve para habilitar o bloquear tools desde el flujo activo

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

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

Valores soportados:
- `true`
- `false`

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

Ejemplo:

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

## Slots

Representan datos conversacionales que pueden venir del cliente o de una respuesta guiada.

Formato:

```json
{
  "dni_cuit": {
    "type": "text",
    "required": true,
    "label": "DNI o CUIT"
  }
}
```

### Campos permitidos en un slot

- `type`
- `required`
- `label`
- `description`
- `values`

### `type`

Valores soportados en V1:
- `text`
- `enum`
- `boolean`

### `required`

- tipo: `boolean`
- indica si idealmente el flujo necesita ese dato

### `label`

- tipo: `string`
- nombre legible para UI

### `description`

- tipo: `string`
- descripcion funcional del dato

### `values`

- tipo: `array`
- solo para `type = enum`

Ejemplo:

```json
{
  "tipo_problema": {
    "type": "enum",
    "required": true,
    "label": "Tipo de problema",
    "values": ["sin_servicio", "lentitud_cortes", "otro"]
  }
}
```

## Backend Facts

Representan hechos duros confirmados por backend.

No deben ser inventados por la IA.

Formato:

```json
{
  "cliente_verificado": {
    "type": "boolean"
  }
}
```

### Campos permitidos en un backend fact

- `type`
- `label`
- `description`
- `values`

### Tipos soportados

- `boolean`
- `text`
- `enum`

Ejemplo:

```json
{
  "estado_administrativo": {
    "type": "enum",
    "values": ["activo", "cortado_falta_pago", "suspendido", "desconocido"]
  }
}
```

## Steps

El flujo se compone de una lista de pasos.

Cada paso debe tener:

- `id`
- `type`

Tipos soportados en V1:

- `question`
- `action`
- `branch`
- `message`
- `end`

## Step: `question`

Sirve para pedir o confirmar un dato.

Formato:

```json
{
  "id": "pedir_dni",
  "type": "question",
  "slot": "dni_cuit",
  "message": "Pedir DNI o CUIT para validar la cuenta",
  "next_step": "validar_cliente"
}
```

Campos permitidos:

- `id`
- `type`
- `slot`
- `message`
- `next_step`
- `conditions`

Reglas:
- `slot` debe existir en `slots`
- `message` describe la intencion interna del paso
- la redaccion final al cliente siempre la formula GPT a partir de esta instruccion
- `next_step` indica a donde ir una vez completado el slot

## Step: `action`

Sirve para ejecutar una action backend.

Formato:

```json
{
  "id": "validar_cliente",
  "type": "action",
  "action": "buscar_cliente",
  "requires": ["dni_cuit"],
  "on_success": "evaluar_estado_admin",
  "on_failure": "cliente_no_encontrado"
}
```

Campos permitidos:

- `id`
- `type`
- `action`
- `requires`
- `params`
- `on_success`
- `on_failure`
- `conditions`

### Actions soportadas en V1

- `buscar_cliente`
- `transferir_operador`
- `registrar_compromiso_pago`

### `requires`

- tipo: `array`
- lista de `slots` o `backend_facts` requeridos antes de ejecutar

### `params`

- tipo: `object`
- parametros extra configurables para la action

Ejemplo:

```json
{
  "params": {
    "area": "cobranza"
  }
}
```

### `on_success`

- tipo: `string`
- id del siguiente paso si la action fue exitosa

### `on_failure`

- tipo: `string`
- id del siguiente paso si la action fallo

## Step: `branch`

Sirve para evaluar condiciones y saltar a otro paso.

Formato:

```json
{
  "id": "evaluar_estado_admin",
  "type": "branch",
  "branches": [
    {
      "when": {
        "fact": "estado_administrativo",
        "equals": "cortado_falta_pago"
      },
      "go_to": "derivar_cobranza"
    },
    {
      "when": {
        "fact": "estado_administrativo",
        "equals": "activo"
      },
      "go_to": "pedir_tipo_problema"
    }
  ],
  "default_next": "pedir_tipo_problema"
}
```

Campos permitidos:

- `id`
- `type`
- `branches`
- `default_next`

### Estructura de `branches`

Cada branch debe tener:

- `when`
- `go_to`

### `when`

Formato soportado en V1:

```json
{
  "slot": "tipo_problema",
  "equals": "sin_servicio"
}
```

o

```json
{
  "fact": "estado_administrativo",
  "equals": "activo"
}
```

Campos soportados en `when`:

- `slot`
- `fact`
- `equals`
- `not_equals`
- `exists`

Reglas:
- debe existir solo uno entre `slot` o `fact`
- `equals` compara igualdad exacta
- `not_equals` compara desigualdad exacta
- `exists` acepta `true` o `false`

No soportado en V1:
- `and`
- `or`
- expresiones anidadas
- comparadores numericos

## Step: `message`

Sirve para enviar un mensaje fijo o backend-controlado sin ejecutar una action.

Formato:

```json
{
  "id": "cliente_no_encontrado",
  "type": "message",
  "message": "No pude encontrar tu cuenta con ese DNI. Pasame otro DNI o CUIT.",
  "next_step": "pedir_dni"
}
```

Campos permitidos:

- `id`
- `type`
- `message`
- `next_step`
- `conditions`

Reglas:
- `message` describe el objetivo exacto del paso
- el runtime decide este paso, pero GPT siempre redacta el texto final al cliente

## Step: `end`

Marca el fin del flujo.

Formato:

```json
{
  "id": "fin",
  "type": "end"
}
```

Campos permitidos:

- `id`
- `type`

## Conditions

Algunos pasos pueden incluir `conditions`.

Formato:

```json
{
  "conditions": [
    {
      "fact": "cliente_verificado",
      "equals": true
    }
  ]
}
```

Reglas:
- todas las condiciones deben cumplirse
- si no se cumplen, el runtime no debe ejecutar ese paso todavia

Campos soportados:
- `slot`
- `fact`
- `equals`
- `not_equals`
- `exists`

## Runtime esperado

El runtime V1 debera poder:

1. Resolver `entry_step`
2. Guardar y actualizar `slots`
3. Guardar y actualizar `backend_facts`
4. Validar `requires` antes de una `action`
5. Ejecutar `on_success` y `on_failure`
6. Evaluar `branch`
7. Resolver `next_step`
8. Finalizar en `end`

## Lo que NO hace V1

- no ejecuta expresiones complejas
- no evalua reglas anidadas
- no mezcla condiciones libres con semantica ambigua
- no depende de prompts para decidir una transicion deterministica

## Ejemplo Completo

```json
{
  "id": "flujo_soporte_v1",
  "version": 1,
  "nombre": "Soporte tecnico",
  "intent_principal": "prompt_soporte",
  "settings": {
    "entry_step": "pedir_dni"
  },
  "slots": {
    "dni_cuit": {
      "type": "text",
      "required": true,
      "label": "DNI o CUIT"
    },
    "tipo_problema": {
      "type": "enum",
      "required": true,
      "label": "Tipo de problema",
      "values": ["sin_servicio", "lentitud_cortes", "otro"]
    }
  },
  "backend_facts": {
    "cliente_verificado": {
      "type": "boolean"
    },
    "estado_administrativo": {
      "type": "enum",
      "values": ["activo", "cortado_falta_pago", "suspendido", "desconocido"]
    }
  },
  "steps": [
    {
      "id": "pedir_dni",
      "type": "question",
      "slot": "dni_cuit",
      "message": "Pedir DNI o CUIT para validar la cuenta",
      "next_step": "validar_cliente"
    },
    {
      "id": "validar_cliente",
      "type": "action",
      "action": "buscar_cliente",
      "requires": ["dni_cuit"],
      "on_success": "evaluar_estado_admin",
      "on_failure": "cliente_no_encontrado"
    },
    {
      "id": "cliente_no_encontrado",
      "type": "message",
      "message": "No pude encontrar tu cuenta con ese DNI. Pasame otro DNI o CUIT.",
      "next_step": "pedir_dni"
    },
    {
      "id": "evaluar_estado_admin",
      "type": "branch",
      "branches": [
        {
          "when": {
            "fact": "estado_administrativo",
            "equals": "cortado_falta_pago"
          },
          "go_to": "derivar_cobranza"
        },
        {
          "when": {
            "fact": "estado_administrativo",
            "equals": "activo"
          },
          "go_to": "pedir_tipo_problema"
        }
      ],
      "default_next": "pedir_tipo_problema"
    },
    {
      "id": "pedir_tipo_problema",
      "type": "question",
      "slot": "tipo_problema",
      "message": "Preguntar si el problema es sin servicio, lentitud/cortes u otro.",
      "next_step": "fin"
    },
    {
      "id": "derivar_cobranza",
      "type": "action",
      "action": "transferir_operador",
      "params": {
        "area": "cobranza"
      },
      "on_success": "fin",
      "on_failure": "fin"
    },
    {
      "id": "fin",
      "type": "end"
    }
  ]
}
```

## Criterio de UI futura

La UI visual no deberia dejar crear JSON arbitrario.

La UI deberia forzar:
- tipos de paso validos
- fields permitidos por tipo
- referencias validas entre pasos
- referencias validas a slots y backend_facts
- un `entry_step`
- ids unicos

La UI idealmente debera generar exactamente este formato.

## Ejemplo real de migracion

Como referencia de conversion desde un flujo legacy de soporte:
- ver [flujo_soporte_v1.json](/c:/Apache24/htdocs/sidelink/backend/IA/flujo_soporte_v1.json)
