Contexto
Para configurar el bot, el negocio necesita declarar 5 datos relacionados: nombre, horario, direccion, telefono, descripcion. Mi primer impulso fue 5 env vars sueltas:
BUSINESS_NAME=Barberia X
BUSINESS_HOURS=Mar-Sab 10-19
BUSINESS_ADDRESS=Av. Y 123
BUSINESS_PHONE=+5215555550100
BUSINESS_DESCRIPTION=Cortes clasicos
Cinco lineas, cinco campos en Settings, cinco lugares donde cualquier typo en el nombre falla silenciosamente. La review externa apunto: "es fragil y no escala. Una sola env var con JSON y un model anidado es mas limpio". Acepte el cambio.
Lo que aprendi
pydantic-settings permite anidar models. El truco es declarar la env var como string y exponer una @property que parsea con model_validate_json:
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings
class BusinessInfo(BaseModel):
name: str = "Demo Business"
hours: str = "Lun-Vie 9-18"
address: str = "Por confirmar"
phone: str = ""
description: str = ""
class Settings(BaseSettings):
business_info_json: str = Field(
default='{"name":"Demo Business","hours":"Lun-Vie 9-18"}'
)
@property
def business_info(self) -> BusinessInfo:
return BusinessInfo.model_validate_json(self.business_info_json)
.env queda con una sola linea:
BUSINESS_INFO_JSON='{"name":"Barberia X","hours":"Mar-Sab 10-19","address":"Av. Y 123","phone":"+5215555550100","description":"Cortes clasicos"}'
En el codigo accedes a settings.business_info.name, settings.business_info.hours, etc., con autocomplete y validacion Pydantic gratis. Si el JSON es invalido, Pydantic lanza un error claro al primer acceso, no un None silencioso.
Para tests, instanciar Settings(business_info_json='{"name":"Test"}') simula cualquier configuracion sin tocar variables de entorno reales.
Por que importa
El patron es generico: cualquier grupo de 3+ env vars que en el fondo describen un solo concepto se beneficia. Ejemplos donde aplica:
META_VERIFY_TOKEN,META_APP_SECRET,META_PHONE_NUMBER_ID,META_ACCESS_TOKEN->META_CONFIG_JSONSMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASS->SMTP_CONFIG_JSON- Coordenadas geograficas, datos fiscales, credenciales de S3, etc.
Tradeoff: el JSON es menos amigable para edicion casual via export VAR=value. Si la config la escribes una vez y la dejas, gana el JSON. Si la cambias frecuente desde shell, gana N vars sueltas.
Para el caso de citas-bot-universal, BUSINESS_INFO se setea al desplegar y rara vez cambia. JSON conviene mas.