VitrinaAPI

Dejar que la IA conteste, agende y avise cuando se salga del libreto

El agente responde y agenda solo; lo interesante es el traspaso a una persona.

Un agente de IA publicado contesta, agenda una hora y, cuando corresponde, pasa la conversación a una persona.

Hay una capa extra de seguridad para el traspaso. Un segundo modelo revisa cada respuesta del agente. Si el agente le dijo al cliente que una persona lo iba a contactar, pero no llamó a la herramienta de traspaso, la plataforma lo detecta y hace el traspaso ella misma. El paso 3 muestra cómo se ve.

Antes de empezar

  • Un agente publicado. ai_agents:write para configurarlo; ver Configurar el agente que conversa.
  • Un canal conectado, con el agente asignado desde la aplicación.
  • Una política horaria guardada, si el objetivo es que agende solo (paso 1).
  • conversations:write, para traspasar o devolver una conversación a mano.

1. Confirmar si el agente puede agendar solo

Reservar una hora por la API funciona sin configurar nada. Sin política guardada, la agenda usa el horario general del workspace por defecto. Eso no equivale a dejar que el agente reserve por su cuenta: esa decisión tiene su propio interruptor, de solo lectura desde la API pública.

curl https://api.vitrinadev.com/api/v1/appointments/config \
  -H "Authorization: Bearer $VITRINA_KEY"
{
  "data": {
    "configured": true,
    "timezone": "America/Santiago",
    "business_hours": {
      "mon": [["09:00", "13:00"], ["14:30", "18:00"]],
      "tue": [["09:00", "13:00"], ["14:30", "18:00"]]
    }
  }
}

configured decide si la herramienta de agendar se ofrece al modelo. Mientras valga false, una persona o tu propio servidor pueden reservar por Agenda y citas, pero el agente no. Guardar la política es un PUT /appointments/config con al menos un campo, documentado en esa misma receta.

2. Dejar que conteste, y que pida ayuda cuando corresponda

El agente llama a su herramienta de traspaso cuando no puede resolver algo: una decisión reservada a una persona, un dato que no tiene, un cliente que pide hablar con alguien. La misma operación está publicada para uso manual, por ejemplo para tomar una conversación que el agente sigue atendiendo:

curl -X POST https://api.vitrinadev.com/api/v1/conversations/01a0ce15-c122-7148-98b3-4dfefe93756e/handoff \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Pide precio con descuento por pago al contado, decisión que no puedo tomar" }'
{
  "data": {
    "id": "01a0ce15-c122-7148-98b3-4dfefe93756e",
    "handler": "human",
    "ticket_id": null,
    "assignee_user_id": null,
    "awaiting_human_since": "2026-09-23T11:45:44.101Z"
  }
}

handoff funciona distinto de assign. Aquí no eliges quién se queda con la conversación: las reglas de asignación del workspace deciden (Conversaciones y tickets las documenta). En esta captura ninguna regla coincidió. La conversación queda en la cola humana sin dueño (assignee_user_id en null), pero ya fuera de manos de la IA. reason es obligatorio: es lo primero que lee quien recoja el hilo.

El mismo endpoint que responde «por qué está en silencio la IA» confirma el efecto:

curl https://api.vitrinadev.com/api/v1/conversations/01a0ce15-c122-7148-98b3-4dfefe93756e/ai-status \
  -H "Authorization: Bearer $VITRINA_KEY"
{
  "data": {
    "silence_reason": "handler_is_human",
    "explanation": "A teammate replied, so this conversation is handled by a human. The AI stays silent until it is explicitly returned to the AI."
  }
}

La explicación llega en inglés. La bandeja la traduce al mostrarla; esta llamada no. POST /conversations/{id}/return-to-ai deshace el traspaso cuando corresponde.

3. Leer lo que queda escrito cuando el traspaso lo aplicó el sistema

Todo traspaso deja un mensaje de evento en el mismo hilo que ya se está leyendo. Da igual quién lo pidió: tú a mano, el agente con su herramienta, o la revisión automática descrita al inicio.

curl "https://api.vitrinadev.com/api/v1/conversations/01a0ce15-c122-7148-98b3-4dfefe93756e/messages?limit=2" \
  -H "Authorization: Bearer $VITRINA_KEY"
{
  "data": [
    {
      "id": "61ea125e-e3cb-4468-8f68-0db340a07d28",
      "sender_type": "system",
      "content": "Un asesor tomó la conversación · Motivo: Pide precio con descuento por pago al contado, decisión que no puedo tomar",
      "metadata": { "reason": "Pide precio con descuento por pago al contado, decisión que no puedo tomar", "source": "operator", "event_kind": "handoff" }
    }
  ]
}

Esa es la forma de un traspaso pedido a mano, con source: "operator". Cuando lo aplica la revisión automática, el mismo mecanismo deja un mensaje con un texto fijo, siempre igual, pensado para reconocerse sin adivinar:

Traspaso aplicado automáticamente: la IA le dijo al cliente que un ejecutivo
se pondría en contacto, pero no completó el traspaso. El sistema lo hizo por ella.

Esa frase exacta, en un hilo, indica que el traspaso lo hizo la plataforma. GET /conversations/{id}/messages lo muestra igual que cualquier otro mensaje, con el mismo sender_type: "system".

4. Entender por qué el agente no despierta solo al abrir la ventana

Un canal puede tener una ventana de disponibilidad para la IA: siempre, fuera de horario, o personalizada. Eso se configura en la aplicación, no por la API pública. La IA solo responde a un mensaje entrante. Nada se envía al abrirse la ventana, y la bandeja no se revisa buscando hilos sin responder. Para escribirle a un cliente que no ha escrito primero, usa una plantilla saliente.

En la aplicación: el agente por canal, la ventana de disponibilidad y el destino del traspaso se configuran desde Configuración → Agentes de IA. Guía completa en Manual de plataforma → Decidir cuándo contesta la IA y en → Elegir qué agente atiende cada canal.

Cuando falla

Un traspaso sobre una conversación que ya es humana funciona igual. La operación es idempotente sobre el estado: repetirla dos veces en el mismo turno no crea dos dueños distintos. Vale la pena vigilar un ticket_id que vuelve null después de un traspaso, como en el paso 2. Significa que ninguna regla de asignación coincidió. El hilo espera en la cola general hasta que alguien lo reclame a mano, con POST /conversations/{id}/claim.

Si el agente parece no contestar nunca, y la causa no es un traspaso, Enterarse de por qué la IA se quedó callada recorre las quince razones posibles.

En esta página