Kelova Docs

Agentes

Crear agentes, consultarlos y configurar captura de leads

Un agente (agent) combina una persona, un subconjunto de fuentes (opcional) y la configuración de canales. Cada tenant puede tener varios agentes — por ejemplo uno de soporte y uno de ventas, con fuentes distintas.

Listar agentes

curl https://api.kelova.app/agents \
  -H "Authorization: Bearer <token>"
[
  {
    "id": "a1b2c3...",
    "tenant_id": "t9f8e7...",
    "tenant_slug": "tuempresa",
    "name": "Soporte",
    "persona": "Eres el asistente de soporte de TuEmpresa...",
    "welcome_msg": "Hola, ¿en qué te puedo ayudar?",
    "status": "active",
    "allowed_origins": ["https://tuempresa.com"],
    "cite_sources": true,
    "active_channels": ["web"],
    "lead_capture_enabled": false,
    "lead_notification_email": "",
    "plan": "pro",
    "store_transcripts": false,
    "transcript_retention_days": 30,
    "created_at": "2026-06-01T09:00:00Z"
  }
]

Crear un agente

curl -X POST https://api.kelova.app/agents \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ventas",
    "persona": "Eres el asistente de ventas de TuEmpresa. Responde con precios y disponibilidad solo si están en los documentos indexados.",
    "welcome_msg": "¡Hola! Cuéntame qué buscas.",
    "cite_sources": true,
    "lead_capture_enabled": true,
    "lead_notification_email": "ventas@tuempresa.com"
  }'

Respuesta (201): el mismo shape que GET /agents (un solo objeto, no array). Requiere rol admin.

lead_notification_email es obligatorio y debe ser un email válido cuando lead_capture_enabled: true — si no, 400 INVALID_AGENT_CONFIG.

Actualizar un agente

PUT /agents/{id} acepta actualización parcial — solo los campos enviados se modifican; null/omitido deja el valor actual sin cambios (excepto strings vacíos en name/persona/welcome_msg, que también se ignoran).

curl -X PUT https://api.kelova.app/agents/{id} \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "inactive",
    "allowed_origins": ["https://tuempresa.com", "https://app.tuempresa.com"]
  }'

status acepta active o inactive. transcript_retention_days, cuando se envía, debe ser 7, 30 o 90.

Eliminar un agente

curl -X DELETE https://api.kelova.app/agents/{id} \
  -H "Authorization: Bearer <token>"

Responde 204 No Content. 404 AGENT_NOT_FOUND si el agente no existe o no es de tu tenant.

Alcance de fuentes (source scoping)

Por defecto un agente consulta todas las fuentes del tenant. Puedes limitarlo a un subconjunto:

# Ver el alcance actual
curl https://api.kelova.app/agents/{id}/sources \
  -H "Authorization: Bearer <token>"

# Reemplazar el alcance — array vacío = todas las fuentes (comportamiento por defecto)
curl -X PUT https://api.kelova.app/agents/{id}/sources \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"source_ids": ["3f2e1a...", "9c8b7a..."]}'

Ambos devuelven {"source_ids": [...]}. PUT reemplaza el conjunto completo — no es incremental.

Consultar al agente

curl -X POST https://api.kelova.app/agent/query \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "¿Cuál es el precio del plan Pro?",
    "agent_id": "a1b2c3..."
  }'

agent_id es opcional — si lo omites, Kelova usa la configuración por defecto del tenant. session_id es opcional y se usa para la captura de leads en dos turnos (ver abajo). También existe POST /agents/{id}/query, equivalente pero con el agent_id tomado de la URL en vez del body.

Respuesta (200):

{
  "answer": "El plan Pro cuesta $299/mes e incluye hasta 5000 documentos indexados y 10000 consultas mensuales.",
  "sources": [
    {
      "source_file": "Catálogo 2026.pdf",
      "page_or_row": "4",
      "section_title": "Planes y precios",
      "synced_at": "2026-07-08T10:15:00Z",
      "similarity": 0.87
    }
  ],
  "model": "anthropic"
}

El campo con las fuentes usadas en la respuesta se llama sources — no uses otro nombre en tu integración. Cada entrada trae synced_at — úsalo para mostrar qué tan fresca es la información, según las reglas de badge de frescura (verde <7 días, amarillo 7–30 días, rojo >30 días).

Si no hay chunks relevantes indexados, el agente nunca inventa una respuesta — devuelve exactamente "No encontré información sobre esto en los documentos indexados." con "sources": [].

Límites: query máximo 1000 caracteres. 402 si tu plan Free alcanzó el límite de consultas; 429 si excedes el rate limit por tenant.

Captura de leads

La captura de leads (lead_capture_enabled + lead_notification_email, configurados en el agente) no tiene endpoints propios — corre automáticamente dentro del pipeline de POST /agent/query en dos turnos: el primero detecta intención de compra y crea el lead sin datos de contacto, el segundo detecta datos de contacto en la conversación y notifica al lead_notification_email configurado (por email + notificación in-app en el dashboard). No hay POST /leads — los leads se consultan desde el dashboard, no desde esta API pública.

On this page