Configuración de los Servicios de Agentes IA

Los servicios permiten que tu agente de IA se conecte con APIs externas para ejecutar acciones complejas como consultar bases de datos, realizar reservas, procesar pagos, o cualquier integración que necesites. El agente recolectará automáticamente la información necesaria del usuario antes de llamar a la API.

Github

Puedes descargar nuestro repositorio de ejemplo para crear tus agentes.

✅ Los servicios están en Producción Estable y han demostrado alta fiabilidad. El sistema maneja automáticamente la recolección de datos, validación y ejecución de APIs externas.

🔄 Flujo de Funcionamiento

  1. Detección de Intención: La IA identifica que el usuario quiere usar un servicio
  2. Recolección de Datos: El agente pregunta por los campos requeridos que falten
  3. Validación: Se validan los tipos de datos antes de enviar
  4. Llamada a API: Se ejecuta la llamada HTTP con los datos recolectados
  5. Procesamiento: Se mapea la respuesta según responseMapping
  6. Respuesta Final: Se envía la respuesta personalizada al usuario

📋 Estructura Completa

{
  "services": [
    {
      "intent": "schedule_appointment",
      "reference": "Servicio para agendar citas médicas en la clínica",
      "enabled": true,
      "method": "POST",
      "requiredFields": [
        {
          "name": "nombre",
          "description": "Nombre completo del paciente",
          "promptHint": "¿Podrías indicarme tu nombre completo, por favor?",
          "type": "string"
        },
        {
          "name": "email",
          "description": "Correo electrónico para confirmaciones",
          "promptHint": "¿Cuál es tu dirección de correo electrónico?",
          "type": "email"
        },
        {
          "name": "fecha",
          "description": "Fecha y hora preferida para la cita",
          "promptHint": "¿Qué día y hora te gustaría agendar? (Ejemplo: mañana a las 3pm)",
          "type": "date"
        },
        {
          "name": "telefono",
          "description": "Número de teléfono de contacto",
          "promptHint": "¿Cuál es tu número de teléfono?",
          "type": "phone"
        }
      ],
      "endpoint": "https://api.clinica.com/v1/appointments",
      "tags": ["citas", "agendamiento", "medical"],
      "headers": {
        "Authorization": "Bearer {{apiKey}}",
        "Content-Type": "application/json",
        "X-Clinic-ID": "clinic_123"
      },
      "bodyTemplate": {
        "patient_name": "{{nombre}}",
        "patient_email": "{{email}}",
        "appointment_date": "{{fecha|format('yyyy-MM-dd HH:mm')}}",
        "phone": "{{telefono}}",
        "source": "plazbot_ai"
      },
      "responseMapping": {
        "appointmentId": "$.data.appointment_id",
        "confirmedDate": "$.data.scheduled_date",
        "doctorName": "$.data.doctor.name",
        "status": "$.status",
        "errorMessage": "$.error.message"
      },
      "responseMessage": "¡Perfecto! Tu cita ha sido agendada para el {{confirmedDate}} con {{doctorName}}. ID de cita: {{appointmentId}}",
      "responseConditions": [
        {
          "condition": "$.status == 'success'",
          "message": "✅ ¡Cita confirmada! Te esperamos el {{confirmedDate}} con {{doctorName}}. Recibirás un recordatorio por email.",
          "nextService": "verify_contact_info"
        },
        {
          "condition": "$.status == 'conflict'",
          "message": "❌ Lo siento, ese horario no está disponible. ¿Te gustaría que te sugiera horarios libres?",
          "nextService": "verify_contact_info"
        },
        {
          "condition": "$.status == 'error'",
          "message": "⚠️ Hubo un problema al agendar: {{errorMessage}}. ¿Podrías intentar con otra fecha?",
          "nextService": "verify_contact_info"
        }
      ],
      "action": "notify_doctor"
    }
  ]
}

📊 Campos del Servicio

Campos Principales

CampoTipoRequeridoDescripción
intentstring✅ SíIdentificador único del servicio (ej: schedule_appointment)
referencestring✅ SíDescripción clara para que la IA entienda cuándo usar este servicio
enabledboolean✅ SíSi el servicio está activo (true) o deshabilitado (false)
methodstring✅ SíMétodo HTTP: GET, POST, PUT, DELETE
endpointstring✅ SíURL completa de la API externa
requiredFieldsarray✅ SíLista de campos que el usuario debe proporcionar
headersobject❌ NoHeaders HTTP personalizados
bodyTemplateobject❌ NoEstructura del body para requests
responseMappingobject❌ NoMapeo de la respuesta usando JSONPath
responseMessagestring❌ NoMensaje de éxito predeterminado
responseConditionsarray❌ NoRespuestas condicionales basadas en el resultado
tagsarray❌ NoEtiquetas para clasificar el servicio
actionstring❌ NoAcción a ejecutar después del servicio

Configuración de Required Fields

CampoTipoRequeridoDescripción
namestring✅ SíNombre de la variable (sin espacios)
descriptionstring✅ SíDescripción del campo para la IA
promptHintstring✅ SíPregunta específica para obtener este dato
typestring✅ SíTipo de dato esperado

🔧 Tipos de Datos Soportados

TipoDescripciónEjemplo de Valor
stringTexto libre"Juan Pérez"
emailDirección de correo válida"usuario@email.com"
phoneNúmero de teléfono"+51987654321"
dateFecha y hora"2024-03-15 14:30"
numberNúmero entero o decimal150 o 99.99
booleanVerdadero o falsotrue / false
urlURL válida"https://ejemplo.com"

Los campos de tipo date son procesados inteligentemente por la IA. El usuario puede escribir “mañana a las 3pm” y se convertirá automáticamente al formato correcto.

🔗 Headers Comunes

Autenticación Bearer Token

{
  "headers": {
    "Authorization": "Bearer {{apiKey}}",
    "Content-Type": "application/json"
  }
}

Autenticación API Key

{
  "headers": {
    "X-API-Key": "{{apiKey}}",
    "Content-Type": "application/json"
  }
}

Headers Personalizados

{
  "headers": {
    "Authorization": "Bearer {{token}}",
    "Content-Type": "application/json",
    "X-Client-ID": "plazbot",
    "X-Version": "2.0",
    "Accept": "application/json"
  }
}

📝 Body Template con Formateo

Formateo de Fechas

{
  "bodyTemplate": {
    "appointment_date": "{{fecha|format('yyyy-MM-dd')}}",
    "appointment_time": "{{fecha|format('HH:mm')}}",
    "timestamp": "{{fecha|format('yyyy-MM-dd HH:mm:ss')}}"
  }
}

Variables Condicionales

{
  "bodyTemplate": {
    "customer_name": "{{nombre}}",
    "email": "{{email}}",
    "phone": "{{telefono|default('Sin teléfono')}}",
    "priority": "{{vip|default(false)}}"
  }
}

🗺️ Response Mapping Avanzado

Mapeo Básico

{
  "responseMapping": {
    "id": "$.data.id",
    "status": "$.status",
    "message": "$.data.message"
  }
}

Mapeo de Arrays

{
  "responseMapping": {
    "availableSlots": "$.data.available_times[*]",
    "firstSlot": "$.data.available_times[0]",
    "doctorName": "$.data.doctors[0].name"
  }
}

Mapeo Condicional

{
  "responseMapping": {
    "result": "$.success",
    "appointmentId": "$.data.appointment_id",
    "errorCode": "$.error.code",
    "errorMessage": "$.error.message"
  }
}

⚡ Respuestas Condicionales

Configuración Avanzada

{
  "responseConditions": [
    {
      "condition": "$.success == true",
      "message": "✅ ¡Éxito! Tu solicitud fue procesada. ID: {{appointmentId}}"
    },
    {
      "condition": "$.error.code == 'SLOT_UNAVAILABLE'",
      "message": "❌ Ese horario no está disponible. Horarios libres: {{availableSlots}}"
    },
    {
      "condition": "$.error.code == 'INVALID_EMAIL'",
      "message": "⚠️ El email proporcionado no es válido. ¿Podrías verificarlo?"
    },
    {
      "condition": "$.status == 'pending'",
      "message": "⏳ Tu solicitud está en revisión. Te contactaremos en 24 horas."
    }
  ]
}

Condiciones con Múltiples Valores

{
  "responseConditions": [
    {
      "condition": "$.status in ['success', 'confirmed']",
      "message": "✅ Procesado exitosamente: {{message}}"
    },
    {
      "condition": "$.status in ['error', 'failed'] && $.error.code == 'PAYMENT_FAILED'",
      "message": "💳 Error de pago: {{errorMessage}}. ¿Quieres intentar con otra tarjeta?"
    }
  ]
}

📚 Ejemplos por Casos de Uso

🏥 Agendar Cita Médica

{
  "intent": "agendar_cita_medica",
  "reference": "Servicio para agendar citas médicas con doctores especialistas",
  "enabled": true,
  "method": "POST",
  "requiredFields": [
    {
      "name": "paciente",
      "description": "Nombre completo del paciente",
      "promptHint": "¿Cuál es el nombre completo del paciente?",
      "type": "string"
    },
    {
      "name": "especialidad",
      "description": "Especialidad médica requerida",
      "promptHint": "¿Qué especialidad médica necesitas? (cardiología, dermatología, etc.)",
      "type": "string"
    },
    {
      "name": "fecha_preferida",
      "description": "Fecha y hora preferida",
      "promptHint": "¿Cuándo te gustaría agendar la cita?",
      "type": "date"
    }
  ],
  "endpoint": "https://api.hospital.com/v2/appointments",
  "headers": {
    "Authorization": "Bearer {{hospitalApiKey}}",
    "Content-Type": "application/json"
  },
  "bodyTemplate": {
    "patient_name": "{{paciente}}",
    "specialty": "{{especialidad}}",
    "preferred_date": "{{fecha_preferida|format('yyyy-MM-dd HH:mm')}}",
    "booking_source": "ai_assistant"
  }
}

🛒 Consulta de Productos

{
  "intent": "consultar_producto",
  "reference": "Buscar información detallada de productos en el catálogo",
  "enabled": true,
  "method": "GET",
  "requiredFields": [
    {
      "name": "producto",
      "description": "Nombre o código del producto",
      "promptHint": "¿Qué producto te interesa consultar?",
      "type": "string"
    }
  ],
  "endpoint": "https://api.tienda.com/products/search?q={{producto}}",
  "headers": {
    "X-API-Key": "{{storeApiKey}}"
  },
  "responseMapping": {
    "productName": "$.data[0].name",
    "price": "$.data[0].price",
    "stock": "$.data[0].stock",
    "description": "$.data[0].description"
  },
  "responseMessage": "📦 **{{productName}}**\n💰 Precio: ${{price}}\n📊 Stock: {{stock}} unidades\n📝 {{description}}"
}

💳 Procesar Pago

{
  "intent": "procesar_pago",
  "reference": "Procesar pagos de órdenes usando gateway de pagos",
  "enabled": true,
  "method": "POST",
  "requiredFields": [
    {
      "name": "monto",
      "description": "Monto a cobrar",
      "promptHint": "¿Cuál es el monto a cobrar?",
      "type": "number"
    },
    {
      "name": "email_cliente",
      "description": "Email del cliente",
      "promptHint": "¿Cuál es el email del cliente?",
      "type": "email"
    }
  ],
  "endpoint": "https://api.payments.com/v1/charges",
  "headers": {
    "Authorization": "Bearer {{paymentApiKey}}",
    "Content-Type": "application/json"
  },
  "bodyTemplate": {
    "amount": "{{monto}}",
    "currency": "USD",
    "customer_email": "{{email_cliente}}",
    "description": "Pago procesado por IA Assistant"
  },
  "responseConditions": [
    {
      "condition": "$.status == 'succeeded'",
      "message": "✅ ¡Pago exitoso! ID de transacción: {{transactionId}}"
    },
    {
      "condition": "$.status == 'failed'",
      "message": "❌ El pago falló: {{errorMessage}}"
    }
  ]
}

🔍 Debugging y Testing

Logs Automáticos

El sistema registra automáticamente:

  • ✅ Datos recolectados del usuario
  • ✅ Request HTTP enviado
  • ✅ Respuesta de la API
  • ✅ Mapeo aplicado
  • ✅ Mensaje final generado

Testing Manual

Puedes probar servicios usando el chat del agente:

Usuario: "Quiero agendar una cita"
Bot: "¿Podrías indicarme tu nombre completo, por favor?"
Usuario: "Juan Pérez"
Bot: "¿Cuál es tu dirección de correo electrónico?"
Usuario: "juan@email.com"
Bot: "¿Qué día y hora te gustaría agendar?"
Usuario: "Mañana a las 3pm"
Bot: "✅ ¡Cita confirmada! Te esperamos el 2024-03-16 15:00..."

⚠️ Mejores Prácticas

✅ Haz

  • Usa nombres descriptivos en intent y reference
  • Proporciona promptHint claros y amigables
  • Valida respuestas con responseConditions
  • Usa formateo de fechas apropiado
  • Maneja errores graciosamente

❌ Evita

  • Endpoints que no sean HTTPS
  • Hardcodear credenciales en headers
  • Campos requeridos innecesarios
  • Respuestas genéricas sin información útil
  • Ignorar validación de tipos de datos

🚨 Seguridad

Variables de Entorno

# .env
HOSPITAL_API_KEY=your_secure_api_key_here
STORE_API_KEY=your_store_api_key_here
PAYMENT_API_KEY=your_payment_api_key_here

Headers Seguros

{
  "headers": {
    "Authorization": "Bearer {{hospitalApiKey}}",
    "Content-Type": "application/json",
    "X-Request-ID": "{{sessionId}}"
  }
}

Nunca hardcodees API keys en la configuración. Usa siempre variables como {{apiKey}} que se configuran de forma segura en el panel de Plazbot.

📋 Casos de Uso Adicionales

📊 Consulta de Inventario

{
  "intent": "consultar_inventario",
  "reference": "Verificar disponibilidad y stock de productos",
  "enabled": true,
  "method": "GET",
  "requiredFields": [
    {
      "name": "producto_codigo",
      "description": "Código SKU del producto",
      "promptHint": "¿Cuál es el código SKU del producto?",
      "type": "string"
    }
  ],
  "endpoint": "https://api.inventario.com/v1/products/{{producto_codigo}}",
  "headers": {
    "Authorization": "Bearer {{inventoryApiKey}}"
  },
  "responseMapping": {
    "nombreProducto": "$.product.name",
    "stockActual": "$.product.stock",
    "precio": "$.product.price",
    "categoria": "$.product.category"
  },
  "responseConditions": [
    {
      "condition": "$.product.stock > 0",
      "message": "✅ **{{nombreProducto}}** está disponible\n📦 Stock: {{stockActual}} unidades\n💰 Precio: ${{precio}}"
    },
    {
      "condition": "$.product.stock == 0",
      "message": "❌ **{{nombreProducto}}** está agotado. ¿Te gustaría que te notifique cuando esté disponible?"
    }
  ]
}

🎫 Sistema de Tickets

{
  "intent": "crear_ticket_soporte",
  "reference": "Crear ticket de soporte técnico para problemas reportados",
  "enabled": true,
  "method": "POST",
  "requiredFields": [
    {
      "name": "asunto",
      "description": "Título del problema",
      "promptHint": "¿Cuál es el problema que estás experimentando?",
      "type": "string"
    },
    {
      "name": "descripcion",
      "description": "Descripción detallada del problema",
      "promptHint": "¿Puedes describir el problema con más detalle?",
      "type": "string"
    },
    {
      "name": "prioridad",
      "description": "Nivel de urgencia",
      "promptHint": "¿Es esto urgente? (alta/media/baja)",
      "type": "string"
    }
  ],
  "endpoint": "https://api.tickets.com/v1/tickets",
  "headers": {
    "Authorization": "Bearer {{supportApiKey}}",
    "Content-Type": "application/json"
  },
  "bodyTemplate": {
    "subject": "{{asunto}}",
    "description": "{{descripcion}}",
    "priority": "{{prioridad}}",
    "source": "ai_chat",
    "customer_id": "{{sessionId}}"
  },
  "responseMessage": "🎫 Ticket creado: **#{{ticketId}}**\n⏱️ Tiempo estimado de respuesta: {{estimatedTime}}\nTe contactaremos pronto."
}

🌤️ Consulta del Clima

{
  "intent": "consultar_clima",
  "reference": "Obtener información meteorológica de cualquier ciudad",
  "enabled": true,
  "method": "GET",
  "requiredFields": [
    {
      "name": "ciudad",
      "description": "Nombre de la ciudad",
      "promptHint": "¿De qué ciudad quieres saber el clima?",
      "type": "string"
    }
  ],
  "endpoint": "https://api.openweathermap.org/data/2.5/weather?q={{ciudad}}&appid={{weatherApiKey}}&units=metric&lang=es",
  "responseMapping": {
    "temperatura": "$.main.temp",
    "descripcion": "$.weather[0].description",
    "humedad": "$.main.humidity",
    "ciudad": "$.name",
    "pais": "$.sys.country"
  },
  "responseMessage": "🌤️ **Clima en {{ciudad}}, {{pais}}**\n🌡️ Temperatura: {{temperatura}}°C\n☁️ Condición: {{descripcion}}\n💧 Humedad: {{humedad}}%"
}

🔧 Funciones Avanzadas

Variables Dinámicas en Endpoints

{
  "endpoint": "https://api.empresa.com/{{departamento}}/users/{{userId}}/reports",
  "requiredFields": [
    {
      "name": "departamento",
      "description": "Departamento del usuario",
      "promptHint": "¿A qué departamento perteneces? (ventas, marketing, soporte)",
      "type": "string"
    },
    {
      "name": "userId",
      "description": "ID del usuario",
      "promptHint": "¿Cuál es tu ID de empleado?",
      "type": "string"
    }
  ]
}

Autenticación Múltiple

{
  "headers": {
    "Authorization": "Bearer {{userToken}}",
    "X-API-Key": "{{companyApiKey}}",
    "X-User-Role": "{{userRole}}",
    "X-Session-ID": "{{sessionId}}"
  }
}

🧪 Testing y Debugging

Testing Manual

Puedes probar servicios directamente desde el chat del agente:

👤 Usuario: "Quiero agendar una cita"
🤖 Bot: "¿Podrías indicarme tu nombre completo, por favor?"
👤 Usuario: "Juan Pérez"
🤖 Bot: "¿Cuál es tu dirección de correo electrónico?"
👤 Usuario: "juan@email.com"
🤖 Bot: "¿Qué día y hora te gustaría agendar?"
👤 Usuario: "Mañana a las 3pm"
🤖 Bot: "✅ ¡Cita confirmada! Te esperamos el 2024-03-16 15:00..."

Validación de Tipos Automática

El sistema valida automáticamente los tipos de datos:

  • email: Verifica formato válido de correo
  • phone: Acepta números de teléfono internacionales
  • date: Procesa fechas en lenguaje natural (“mañana a las 3pm”)
  • number: Valida números enteros y decimales

📈 Monitoreo Básico

Logs del Sistema

El sistema registra automáticamente en la consola:

  • ✅ Datos recolectados del usuario
  • ✅ Request HTTP enviado a la API externa
  • ✅ Respuesta recibida de la API
  • ✅ Mapeo de respuesta aplicado
  • ✅ Mensaje final enviado al usuario
  • ❌ Errores de conectividad o API

Información Disponible

Puedes revisar los logs del sistema para:

  • Estado de las llamadas a APIs externas (éxito/fallo)
  • Tiempo de respuesta básico
  • Errores de conectividad
  • Datos recolectados vs campos requeridos

🚨 Manejo de Errores

Errores Comunes

El sistema maneja automáticamente varios tipos de errores:

Errores de API Externa:

  • Status 4xx/5xx: Muestra mensaje de serviceError del agente
  • Timeout de red: Fallo después de timeout del cliente HTTP
  • JSON inválido: Error al parsear respuesta de la API

Errores de Datos:

  • Campos faltantes: El agente pregunta automáticamente por datos faltantes
  • Tipos incorrectos: Valida email, teléfono, fecha, etc.
  • Endpoint inválido: Error si la URL del servicio es incorrecta

Configuración de Fallbacks

{
  "fallbacks": {
    "serviceError": "Hubo un problema al procesar tu solicitud. Inténtalo más tarde.",
    "noAnswer": "No pude obtener una respuesta del servicio."
  }
}

🚧 Funcionalidades en Desarrollo

Las siguientes funcionalidades están planificadas para futuras versiones pero NO están disponibles actualmente:

En Roadmap

  • Timeout y Reintentos Configurables: Configuración de timeout por servicio
  • 🧪 Mock Responses: Respuestas simuladas para testing
  • 🔒 Encriptación Automática: Cifrado de campos sensibles
  • 📊 Métricas Avanzadas: Analytics detallados de performance
  • Caché de Respuestas: Cache con TTL configurable
  • 🔄 Llamadas Paralelas: Ejecución simultánea de múltiples APIs
  • Validación Regex: Patrones personalizados para campos
  • 🛡️ Validación de Permisos: Control de acceso por roles

📋 Importante: Si necesitas alguna de estas funcionalidades, puedes implementarlas en tu API externa o contactar al equipo de Plazbot para priorización en el roadmap.


Los servicios son una funcionalidad poderosa que transforma tu agente de IA en un asistente capaz de ejecutar acciones reales. Con la configuración correcta, puedes integrar cualquier API REST y proporcionar una experiencia conversacional fluida a tus usuarios.