Las conversaciones permiten mantener contexto entre mensajes. El SDK gestiona conversationId automaticamente, o puedes controlarlo manualmente.
Auto-tracking
Por defecto, el SDK trackea la conversacion activa automaticamente:
// Primer mensaje — se crea una conversacion nueva
const stream1 = thaliq.agent.stream('Hola, necesito ayuda');
for await (const event of stream1) { /* ... */ }
// El conversationId se guarda automaticamente
console.log(stream1.conversationId); // 'abc-123-...'
Conversaciones manuales
Crea y gestiona conversaciones explicitamente:
// Crear una nueva conversacion
const conv = thaliq.conversations.create();
// Primer mensaje
const stream1 = thaliq.agent.stream('Hola', {
conversationId: conv.id,
});
const response1 = await stream1.finalResponse();
// Segundo mensaje (misma conversacion, mantiene contexto)
const stream2 = thaliq.agent.stream('Dame mas detalles', {
conversationId: conv.id,
});
const response2 = await stream2.finalResponse();
ConversationManager
El SDK expone thaliq.conversations para gestionar conversaciones:
// Crear nueva conversacion
const conv = thaliq.conversations.create();
console.log(conv.id); // UUID generado
console.log(conv.createdAt); // Date
// Ver conversacion activa
console.log(thaliq.conversations.active); // ConversationRef | null
// Cambiar conversacion activa
thaliq.conversations.setActive(conv.id);
// Historial de conversaciones (esta sesion)
console.log(thaliq.conversations.history); // ConversationRef[]
// Limpiar historial
thaliq.conversations.clear();
Nueva conversacion vs continuacion
| Escenario | Comportamiento |
|---|
stream('Hola') sin conversationId | Crea conversacion nueva |
stream('Hola', { conversationId: 'xxx' }) | Continua conversacion existente |
Despues de thaliq.reset() | Limpia conversacion activa |
No envies valores reservados como conversationId (literal "pending", "new", "null", "undefined", vacios, o ids de menos de 16 caracteres). El backend los rechaza y genera uno nuevo, pero loggea un warning de seguridad. Estos valores fueron causa de un bug previo de cross-tenant context leakage; ahora estan bloqueados explicitamente. Usa el id real de una conversacion existente o no envies el campo.
Session timeout
Las conversaciones tienen un session timeout configurable por agente (default: 30 minutos). Si la ultima interaccion fue hace mas de 30 minutos, el backend crea una conversacion nueva automaticamente.
Aislamiento por agente
Cada conversacion esta ligada al agente que la atendio. Si reusas un conversationId pero apuntas a un agente distinto, el backend detecta el mismatch y crea una conversacion nueva (no mezcla contextos). Esto evita que un cambio de agentId herede historial de otro agente.
Persistencia
Las conversaciones se persisten en el backend con TTL segun tu plan:
| Plan | Retencion |
|---|
| Starter | 7 dias |
| Growth | 30 dias |
| Enterprise | 90+ dias |
El ConversationManager del SDK solo trackea conversaciones en memoria (de la sesion actual). Los datos se persisten en el backend automaticamente.
Feedback en conversaciones
Puedes enviar feedback sobre mensajes individuales dentro de una conversacion:
const stream = thaliq.agent.stream('Analiza mis datos', {
conversationId: 'conv-123',
});
const response = await stream.finalResponse();
// El messageId viene en la metadata
if (response.metadata.messageId) {
await thaliq.agent.feedback({
conversationId: 'conv-123',
messageId: response.metadata.messageId,
feedback: 'positive',
});
}
Ver Feedback e Insights para mas detalles.
Acciones HITL inline
Cuando una instruccion dispara una accion (consent / confirm / select / form), la accion se entrega como un evento action y el stream se cierra. Para continuar la conversacion dentro del mismo turno y mensaje, mandas un nuevo request con actionResponse:
// Stream 1 — recibe la accion
const stream = thaliq.agent.stream('Quiero agendar una cita', {
conversationId: 'conv-123',
});
let pendingAction;
for await (const event of stream) {
if (event.type === 'action') {
pendingAction = event;
break; // El stream se cierra
}
}
// El usuario decide en tu UI...
const userAccepted = true;
// Stream 2 — resume con la respuesta de la accion
const resumeStream = thaliq.agent.stream('Quiero agendar una cita', {
conversationId: 'conv-123',
actionResponse: {
instructionId: pendingAction.instructionId,
accepted: userAccepted,
},
});
for await (const event of resumeStream) {
// Siguen llegando content.delta, tool.start/end, etc.
// El backend persiste todo (texto pre-accion + accion resuelta + tool calls + texto post-accion)
// como UN SOLO mensaje del asistente con multiples parts en orden cronologico.
}
Ver HITL para los formatos de actionResponse por tipo (consent, confirm, select, form).