Skip to main content
El SDK ofrece dos modos de comunicacion: chat (espera la respuesta completa) y stream (recibe eventos en tiempo real). Streaming es el modo recomendado para la mayoria de casos.

Chat (sin streaming)

Envia un mensaje y espera la respuesta completa:
const response = await thaliq.agent.chat('¿Cuantos usuarios activos tenemos?');

console.log(response.message);            // Texto de la respuesta
console.log(response.conversationId);     // ID de conversacion
console.log(response.insights);           // Insights extraidos (v1.1)
console.log(response.metadata.model);     // Modelo usado
console.log(response.metadata.messageId); // ID del mensaje (para feedback)

Stream (tiempo real)

Envia un mensaje y recibe eventos conforme llegan:
const stream = thaliq.agent.stream('Analiza las ventas del Q4');

for await (const event of stream) {
  switch (event.type) {
    case 'content.delta':
      // Fragmento de texto (llega caracter por caracter)
      process.stdout.write(event.delta);
      break;

    case 'status':
      // Mensaje de estado del agente
      console.log(`[Status] ${event.text}`);
      break;

    case 'tool.start':
      // El agente comienza a ejecutar una tool
      console.log(`> Ejecutando: ${event.tool}`);
      break;

    case 'tool.end':
      // La tool termino de ejecutarse
      console.log(`> ${event.tool}: ${event.success ? 'OK' : 'Error'}`);
      break;

    case 'action':
      // Se requiere una accion del usuario (HITL)
      console.log('Accion requerida:', event.action.message);
      break;

    case 'handoff':
      // La conversacion fue escalada a un agente humano
      console.log('Escalado a:', event.agentName ?? 'agente humano');
      break;
  }
}

Tipos de evento

El SDK soporta 12 tipos de eventos SSE:
TipoDescripcionCampos clave
metaMetadata inicial del streamconversationId
statusMensaje de estado del agentetext
content.deltaFragmento de texto de la respuestadelta
tool.startInicio de ejecucion de una tooltool
tool.endFin de ejecucion de una tooltool, success
actionAccion HITL requeridaaction: PendingAction
handoffConversacion escalada a humanomessage, agentName?, reason?
response.completedRespuesta completa con metadatamessage, insights[], metadata
message_stopGeneracion del modelo finalizadamodel, usage
rate_limitRate limit alcanzadomessage, retryAfter
errorError durante el streammessage
keepalivePing periodico (mantiene conexion)ts

Orden tipico de eventos

meta → status → tool.start → tool.end → content.delta (x N) → response.completed
Si se requiere HITL:
meta → content.delta (x N) → action  (stream se pausa)
Si se escala a humano:
meta → content.delta (x N) → handoff  (stream termina)

Resultado final

Despues de consumir el stream, puedes acceder al resultado completo usando uno de estos metodos:
const stream = thaliq.agent.stream('Resume los datos');

// Opcion 1: Solo el texto acumulado
const text = await stream.text();
console.log(text);

// Opcion 2: Respuesta completa con metadata
const response = await stream.finalResponse();
console.log(response.message);
console.log(response.metadata.completionTokens);
console.log(response.insights); // Insights extraidos
El stream solo puede ser consumido una vez. Tanto text() como finalResponse() iteran internamente sobre el stream. Llamar ambos metodos causara un StreamError.
// ❌ ERROR — doble consumo
const text = await stream.text();
const response = await stream.finalResponse(); // StreamError!

// ✅ CORRECTO — usa solo finalResponse() que incluye el texto
const response = await stream.finalResponse();
const text = response.message;
Esto aplica tambien a for await: si ya iteraste el stream manualmente, no puedes llamar text() ni finalResponse().

Insights

Las respuestas pueden incluir insights extraidos automaticamente del contexto de la conversacion:
const response = await stream.finalResponse();

for (const insight of response.insights) {
  console.log(`[${insight.type}] ${insight.title}`);
  console.log(insight.description);
}
interface Insight {
  type: 'warning' | 'opportunity' | 'info' | 'achievement';
  severity: 'low' | 'medium' | 'high' | 'critical';
  title: string;
  description: string;
  category?: string;
  amount?: string;
}

Estado del stream

El stream expone su estado actual:
const stream = thaliq.agent.stream('Hola');

console.log(stream.status); // 'streaming'

for await (const event of stream) { /* ... */ }

console.log(stream.status); // 'completed' | 'awaiting_action' | 'handoff' | 'error'
EstadoSignificado
streamingRecibiendo eventos
completedStream finalizo correctamente
awaiting_actionEl agente requiere una accion HITL
handoffLa conversacion fue escalada a un agente humano
errorOcurrio un error
abortedEl stream fue cancelado

Cancelar un stream

const stream = thaliq.agent.stream('Consulta larga...');

// Cancelar despues de 5 segundos
setTimeout(() => stream.abort(), 5000);

for await (const event of stream) {
  // Se detiene cuando se llama abort()
}

console.log(stream.status); // 'aborted'
Tambien puedes usar AbortSignal:
const controller = new AbortController();

const stream = thaliq.agent.stream('Consulta', {
  signal: controller.signal,
});

// Cancelar desde fuera
controller.abort();

Conversaciones

Mantiene el contexto entre mensajes usando conversationId:
// Primer mensaje
const stream1 = thaliq.agent.stream('Hola, necesito ayuda con mis facturas');
for await (const event of stream1) { /* ... */ }

// Segundo mensaje (misma conversacion, mantiene contexto)
const stream2 = thaliq.agent.stream('Dame mas detalles de la ultima', {
  conversationId: stream1.conversationId!,
});
Ver Conversaciones para mas detalles.

Callback alternativo

Si prefieres callbacks en vez de for await, puedes usar onEvent:
const stream = thaliq.agent.stream('Hola', {
  onEvent: (event) => {
    if (event.type === 'content.delta') {
      updateUI(event.delta);
    }
  },
});

// Aun necesitas consumir el stream para que empiece
await stream.text();