Saltar al contenido principal

Contrato del protocolo SSE

POST /chat/control/stream responde mediante eventos enviados por el servidor (text/event-stream): una respuesta de larga duración que entrega el texto a medida que se genera, además de eventos estructurados sobre lugares, acciones en el mapa y rutas.

Esta página define el contrato de ese flujo. Si usas kaleidr.js, el panel de chat lo interpreta por ti y no necesitas esta página. Consúltala al crear tu propio cliente. Encontrarás clientes funcionales en Node y Python en Lectura del flujo; el cuerpo de la solicitud se describe en Endpoints.

/chat/summary/stream y /chat/button/stream emplean el mismo formato de tramas, pero con menos tipos de eventos. Se describen al final de esta página.

Antes de iniciar el flujo​

Una solicitud rechazada nunca se convierte en un flujo. Los fallos de autenticación, permisos, cuota, límite de velocidad, validación o tamaño devuelven una respuesta HTTP normal con un cuerpo JSON y un estado 4xx (Errores). Comprueba primero el estado y analiza el cuerpo como SSE solo cuando sea 200.

La solicitud tiene límites de tamaño: un máximo de 400 mensajes, 64 000 caracteres por mensaje y 200 000 caracteres sumando todos los mensajes. Superar uno de estos límites devuelve un 422 con un código como conversation_too_long; un cuerpo superior a 2 MiB devuelve un 413. La lista completa está en Endpoints.

Una respuesta correcta incluye estas cabeceras:

HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Cache-Control: no-cache, no-transform

Formato de las tramas​

Una trama tiene una o dos líneas seguidas de una línea en blanco. Las líneas terminan con \n.

event: place
data: {"name": "Louvre Museum", "coordinates": {"lat": 48.8606, "lng": 2.3376}}

data: {"text": "The Louvre sits on the right bank"}

: keep-alive

  • Una trama con nombre contiene una línea event: seguida de una línea data:.
  • Una trama de texto contiene únicamente una línea data: y no tiene línea event:.
  • Un comentario comienza con dos puntos. Kaleidr envía : keep-alive como señal periódica; no contiene datos.
  • data: siempre contiene un objeto JSON completo en una sola línea. El texto está codificado en UTF-8.

Los fragmentos recibidos por la red no coinciden necesariamente con las tramas. Una lectura puede contener media trama o varias. Acumula el contenido recibido, sepáralo por saltos de línea y procesa cada trama solamente cuando llegues a su línea en blanco.

Regla de compatibilidad​

Ignora los nombres de eventos que no reconozcas y los campos que no utilices. Este contrato puede recibir eventos y campos nuevos sin cambiar de versión. Un cliente que falle ante un evento desconocido dejará de funcionar.

Eventos estables​

event:DatosSignificado
(sin nombre){ text }El siguiente fragmento de texto de la respuesta. Añádelo al texto existente. Puede contener marcadores [[Name]] alrededor de nombres de lugares.
phase{ type: "phase", phase: "thinking", session_id }Se aceptó la solicitud y comenzó el trabajo. phase siempre vale "thinking".
start{ type: "start", session_id, purpose: "control" }El texto está a punto de comenzar a transmitirse.
place{ name, coordinates?: { lat, lng }, address?, category?, icon?, source?, id?, unverified? }Un lugar de la respuesta. Combina los registros por name; las primeras coordenadas recibidas para un nombre son definitivas. source: "vendor" identifica un lugar de los datos de tu organización; source: "map" identifica uno que ya muestra el mapa publicado.
place_linkedcampos del lugar más is_update?Más detalles de un lugar enviado previamente. Incorpóralos al lugar con el mismo name; ignóralos si no lo has recibido.
early_actions{ type: "early_actions", actions: [ { type, payload } ], places_count, is_partial: true }Acciones del mapa que puedes aplicar antes de terminar la respuesta; se envían cuando al menos dos lugares tienen coordenadas.
prompt_options{ type: "prompt_options", schema_version, kind, question, allow_free_text, options: [ { label, send_text } ] }Una pregunta con opciones, enviada cuando la solicitud era ambigua. Muestra las opciones y envía el send_text elegido como siguiente mensaje del usuario.
route_clear{}Borra las rutas dibujadas. Después llegan otras nuevas.
route{ type: "route", schema_version, id?, profile, origin, destination, primary, alternatives[], comparison[], stops?, color?, label?, transit?, attribution? }Una ruta calculada. Llega antes del texto en una pregunta sobre indicaciones, para que el mapa se dibuje mientras se genera la respuesta.
end{ type: "end", full_text, places[], actions[], question_type, response_time, total_tokens?, dropped_places? }La respuesta está completa. Es el resultado definitivo.
error{ type: "error", message, code?, partial_text }La respuesta falló. Se envía en lugar de end.
quota{ type: "quota", product, meter, tier, used, limit, reset_at, period } con clave de servidor; { type: "quota", meter, reset_at } con token de sesiónConsumo de créditos de IA de tu organización después de facturar la llamada. Es el último evento del flujo, posterior a end o error. Consulta quota.
: keep-alivelínea de comentarioSeñal periódica enviada tras 10 segundos de silencio. Ignórala, pero cuenta como actividad.

Eliminado: grounding (2026-09-05). Ya no se envía.

Tarjetas y capas de datos en vivo​

Una pregunta sobre datos en vivo o medidos puede incorporar uno de estos eventos. Una tarjeta llega antes del texto; una capa puede llegar durante o después. Son elementos adicionales: representa los que admitas e ignora los demás. Los conjuntos de campos pueden ampliarse.

event:DatosSe envía para
weather_cardobjeto con lat, lng, name, temperaturas (temp_c, temp_f), conditions y forecast[] opcionalEl tiempo actual de un lugar.
weather_layerobjeto con layer, tile_path_template, tile_size, max_zoom, scope, attributionUna superposición de temperaturas para una región.
satellite_cardobjeto con name, norad_id, lat, lng, altitude_km, velocity_kms, observed_atLa posición de un satélite identificado por su nombre.
constellation_layerobjeto con group, features[] de { name, norad_id, lat, lng } y track opcionalLos satélites alrededor del indicado en la tarjeta.
building_cardobjeto con lat, lng, name opcional, height_m, num_floorsDatos sobre un edificio.
trees_cardobjeto con lat, lng, count, radius_mÁrboles inventariados alrededor de un punto.
heritage_cardobjeto con lat, lng, count, sites[]Lugares patrimoniales alrededor de un punto.
rail_cardobjeto con lat, lng, lines[], nearest_station opcionalLíneas ferroviarias cerca de un punto.
arrivals_cardobjeto con lat, lng, stop, departures[], alerts[], attributionPróximas salidas del transporte público en una parada.
vehicles_layerobjeto con operator, vehicles[], shapes[], attributionPosiciones de vehículos de transporte público en la parada o línea de la tarjeta.
streetview_cardobjeto con lat, lng, image_id, image_lat, image_lngImágenes a pie de calle cerca de un lugar.

Cuando se han enviado, end repite cinco de estos elementos con el mismo nombre, para que un cliente que haya perdido el evento aún pueda leerlos: weather_card, satellite_card, constellation_layer, weather_layer y vehicles_layer (por ejemplo, end.weather_card). Las demás tarjetas no se repiten en end. Los listados de eventos en vivo no se ofrecen mediante la API de la plataforma; consulta Licencias de datos.

Diagnóstico y experimentación (fuera del contrato)​

Pueden aparecer en el flujo de datos. No forman parte del contrato: no dependas de ellos.

event:DatosNotas
debug{ scope, … }Diagnóstico interno. No se envía en solicitudes normales.
place_name_found{ name, is_early }Aviso temprano de que se ha mencionado el nombre de un lugar. Debes utilizar el evento place que llegue después.

Orden de los eventos​

Un flujo pasa por estas etapas. Las marcadas como opcionales no aparecen en todos los flujos.

  1. Opcional. Eventos place con source: "vendor": hasta tres lugares procedentes de los datos de tu organización, cuando la clave tiene el permiso vendor. Se envían primero para que el mapa pueda mostrarlos inmediatamente.
  2. phase. Siempre es el primer evento de la propia respuesta.
  3. Opcional. Comentarios : keep-alive mientras se prepara la respuesta.
  4. Opcional. Eventos anteriores al texto: prompt_options, o route_clear seguido de route, y una tarjeta.
  5. start.
  6. Tramas de texto intercaladas con place, place_linked, early_actions y, a veces, route_clear, route y eventos de capas. Las señales de mantenimiento cubren los períodos sin actividad.
  7. Opcional. Eventos tardíos de place, place_linked, capas y rutas una vez terminado el texto.
  8. end o error.
  9. Opcional. quota.
  10. El servidor cierra la conexión.

Esto tiene dos consecuencias para el cliente:

  • end no es el último evento. Sigue leyendo hasta que se cierre el cuerpo o perderás quota.
  • Un flujo puede cerrarse sin end ni error, por ejemplo, debido a una interrupción de la red. Considera fallido cualquier flujo cerrado sin evento final.

Detalles de los datos​

Texto y marcadores​

Las tramas de texto solo contienen texto. Los datos estructurados nunca llegan dentro del texto. El contenido puede incluir marcadores de doble corchete alrededor de nombres de lugares, como near [[Louvre Museum]], que el panel de chat transforma en enlaces a marcadores del mapa. Para mostrar texto sin formato, elimina los corchetes y conserva el nombre.

place​

CampoTipoNotas
namestringClave utilizada para combinar los registros.
coordinatesobject { lat, lng }Grados decimales. Puede no estar presente. Si no se pudo localizar un lugar mencionado, se envía sin coordenadas y con unverified: true. No dibujes un marcador.
addressstringOpcional.
categorystringOpcional.
iconstringOpcional. Un emoji para el lugar.
sourcestringOpcional. "vendor" indica un lugar de los datos de tu organización. "map" indica un lugar que ya muestra el mapa publicado que ve el visitante: el chat no añade otro marcador porque el mapa ya lo dibuja.
idstringOpcional. Presente en los lugares de tus propios datos.
unverifiedbooleanOpcional. true si el lugar no tiene una ubicación confirmada.

Un lugar puede incluir otros campos. Ignora los que no utilices.

Un mismo nombre puede llegar varias veces: primero con coordenadas y después con más detalles. Mantén un solo registro por nombre, no muevas un marcador una vez que tenga coordenadas y permite que los eventos posteriores completen los demás campos.

Acciones​

early_actions.actions y end.actions son listas de { type, payload }.

Tipo de acciónDatosQué hacer
map.fitBounds{ coordinates: [[lng, lat], …], padding, maxZoom, duration }Ajusta la cámara para abarcar las coordenadas.
places.highlight{ places: [ { name, lat, lng } ], options }Destaca esos lugares.
map.showRoute{ id, label, profile, coordinates: [[lng, lat], …], distance_m, duration_s, turn_by_turn[], transit?, attribution? }Dibuja la línea y muestra su attribution.
route.clear{ id? }Borra la ruta con ese id, o todas las rutas si no hay id.

Pueden aparecer otros tipos de acciones; omite los que no sepas procesar. Ten presentes los dos formatos de coordenadas: un lugar lleva coordinates: { lat, lng }, mientras que una línea es una lista de pares [lng, lat].

route​

primary contiene la línea que debe dibujarse: { coordinates: [[lng, lat], …], distance_m, duration_s, turn_by_turn[] }. Cada paso de turn_by_turn tiene text y puede incluir direction_type, distance_m, duration_s, lat y lng. origin y destination tienen cada uno un label. alternatives[] contiene otras líneas con un route_id, y comparison[] indica el delta_duration_s de cada alternativa respecto de la ruta principal. Cuando existe, stops[] contiene puntos ordenados { lat, lng, name } de una ruta con varias paradas.

Una ruta por carretera incluye attribution: { text, url, license }. Muestra text con un enlace a url siempre que dibujes la ruta. En una ruta de transporte público, el crédito del operador se encuentra dentro de transit.

Cada evento route contiene un id. Si dibujas una ruta con un id ya existente, sustituyes esa ruta.

end​

CampoTipoNotas
full_textstringLa respuesta completa. Prefiérela a las tramas de texto concatenadas.
placesarrayLista definitiva de lugares, en orden. Combínala por nombre con los lugares recogidos.
actionsarrayAcciones definitivas del mapa. Aplícalas; sustituyen a early_actions.
dropped_placesarray of stringsOpcional. Nombres enviados anteriormente que ya no forman parte de la respuesta final. Elimina sus marcadores.
question_typestringEtiqueta que describe el tipo de pregunta. Solo informativa.
response_timenumberSegundos empleados para generar la respuesta.
total_tokensnumberOpcional. Número de tokens utilizados, que determina el cargo.

error​

event: error
data: {"type": "error", "code": "upstream_stall", "message": "The AI service stopped responding. Please try again.", "partial_text": "The Louvre sits"}

message puede mostrarse con seguridad al usuario. partial_text es el texto generado antes del fallo. code solo aparece en un caso:

CasocodeQué hacer
La respuesta dejó de avanzar o el flujo alcanzó su longitud máxima"upstream_stall"Ofrece volver a intentarlo.
Cualquier otro fallo durante la respuestaausenteMuestra message; un nuevo intento podría funcionar.

Después de error no hay end. Aún puede llegar un evento quota.

quota​

Los campos dependen de la credencial utilizada para abrir el flujo.

CampoTipoClave de servidor o antiguaToken de sesión
typecadena, "quota"SíSí
metercadenaSíSí
reset_atcadena, ISO 8601 con zona horariaSíSí
productcadenaSíNo
periodcadenaSíNo
tiercadenaSíNo
usednúmeroSíNo
limitnúmeroSíNo

El token de sesión es lo que emplean los visitantes de una página: uno obtenido mediante una clave publicable o una sesión de visitante de un mapa publicado. Su evento quota indica cuándo se reinicia el período, sin revelar el plan, el consumo ni el límite de la organización. Un cliente de navegador no debe esperar los campos used o limit. La misma regla rige para el cuerpo de respuesta 429 quota_exceeded: consulta Cuotas y límites de velocidad.

Señales de mantenimiento y tiempos de espera​

ComportamientoValorQué debe hacer el cliente
Señal periódica del flujo de chatUn comentario : keep-alive tras 10 segundos sin otra salidaReinicia el temporizador de inactividad al recibir cualquier byte, incluidos los comentarios.
Conexión inactivaUna conexión sin actividad durante aproximadamente un minuto puede cerrarse durante el transporteConfigura un tiempo de espera de inactividad (lectura) de 30 a 60 segundos. No establezcas un tiempo máximo total demasiado corto.
Tiempo hasta recibir el primer textoPuede tardar decenas de segundos si la pregunta es difícilMuestra el progreso desde phase; no interpretes la espera como un fallo.
Duración máxima del flujoAproximadamente 10 minutos, tras los cuales el servidor envía error con upstream_stallEstablece como protección adicional un tiempo máximo total algo superior a 10 minutos.

Interrupción de flujos y facturación​

Cierra la conexión para interrumpir el flujo. El servidor lo detecta en unos diez segundos y detiene la respuesta.

  • Un flujo que finaliza correctamente se factura por los tokens utilizados, indicados en end.total_tokens.
  • Si un flujo se interrumpe o falla antes de terminar, se factura una estimación. Esta equivale, como mínimo, al tamaño de la conversación incluida en la solicitud y, en otros casos, depende del texto ya transmitido. Por ello, puede superar la reserva inicial efectuada al admitir la solicitud: cerrar la conexión al recibir la primera trama no hace que una conversación larga sea gratuita.
  • Los lugares procedentes de tus propios datos (source: "vendor") no se incluyen en el cargo.

Un nuevo intento es otra solicitud y vuelve a generar un cargo. Consulta Cuotas y límites de velocidad.

Flujos de resúmenes y botones​

Estos dos endpoints respaldan la ficha de lugar de Kaleidr Chat. Utilizan el mismo formato de tramas, las mismas tramas de texto sin nombre y el mismo evento final quota. Se diferencian del flujo de chat en tres aspectos: no envían el evento phase, ni eventos de lugares o acciones, y no envían señales de mantenimiento. Usa un tiempo de espera de inactividad de 60 segundos.

Ambos rechazan antes de comenzar los campos demasiado largos con 422 field_too_long e ignoran los campos no indicados: consulta Endpoints. Si uno de estos flujos se interrumpe o falla, el cargo es una estimación del texto ya transmitido y nunca supera la reserva inicial.

POST /chat/summary/stream, para un lugar:

  1. Opcional. address con los datos { type: "address", address, source }
  2. start con los datos { type: "start", poi_type }
  3. Opcional, puede repetirse. url con los datos { type: "url", website, source }
  4. Tramas de texto con los datos { text }
  5. end con los datos { type: "end", full_text, summary, poi_type, category, city, country, sources[], website?, total_tokens? }, o error con los datos { type: "error", message, partial_text }
  6. Opcional. quota

POST /chat/summary/stream, para un edificio (type: "building"):

  1. start con los datos { type: "start", address }
  2. Tramas de texto
  3. end con los datos { type: "end", full_text, parsed, total_tokens? }, o error
  4. Opcional. quota

POST /chat/button/stream:

  1. start con los datos { type: "start", query_type }
  2. Tramas de texto
  3. end con los datos { type: "end", full_text, reply, query_type, first_token_ms, total_ms, total_tokens? }
  4. Opcional. quota

El flujo de botones no tiene evento error. Si falla después de empezar, la conexión se cierra sin end. Un fallo anterior al inicio devuelve HTTP 500 con {"detail": "Button chat stream error"}.

POST /spot/overview/stream envía las tramas del resumen de lugar descritas antes, precedidas de una trama place con los datos { type: "place", name }: el nombre completo del lugar o la región que se describe, como "Springfield, Ohio, United States of America", para etiquetarlo o copiarlo. Llega antes que cualquier otra trama y puede faltar. No es el evento place del flujo de chat y no incluye coordenadas. Si no puede describir un ref, envía una sola trama error con los datos { type: "error", message, ref } en lugar del resumen. Consulta Endpoints.

Páginas relacionadas​