Endpoint principal para interactuar con el agente. Usa Server-Sent Events (SSE) para enviar la respuesta en tiempo real, token por token.
Request
GET https://api.thaliq.com/api/agent/stream?q={mensaje}
Query Parameters
| Parametro | Requerido | Descripcion |
|---|
q | Si | El mensaje del usuario (URL-encoded) |
conversationId | No | ID de conversacion existente |
actionResponse | No | Respuesta a una accion interactiva (JSON URL-encoded) |
| Header | Requerido | Descripcion |
|---|
X-API-Key | Si | Tu API Key |
X-Integration-Type | No | widget o sdk |
X-User-Id | No | ID del usuario final |
X-MCP-Tokens | No | Tokens para MCP Servers (JSON) |
Eventos SSE
La respuesta es un stream de eventos SSE. Cada evento tiene un event type y data JSON:
event: meta
data: {"conversationId":"conv_abc123"}
event: status
data: {"message":"Pensando..."}
event: content.delta
data: {"delta":"Nuestro "}
event: content.delta
data: {"delta":"horario es "}
event: content.delta
data: {"delta":"de 9am a 6pm."}
event: response.completed
data: {"conversationId":"conv_abc123"}
Tipos de eventos
| Evento | Descripcion | Data |
|---|
meta | Metadata de la conversacion | { conversationId } |
status | Estado del agente | { message } |
content.delta | Fragmento de texto de la respuesta | { delta } |
tool.start | El agente comenzo a ejecutar una tool | { tool } |
tool.end | La tool termino de ejecutarse | { tool, success } |
action | Accion interactiva (Human-in-the-Loop) | { type, instructionId, message, options?, fields? } |
response.completed | Stream completado | { conversationId } |
error | Error durante el procesamiento | { message } |
Ejemplo con curl
curl -N -H "X-API-Key: tq_live_xxx" \
"https://api.thaliq.com/api/agent/stream?q=Hola%20necesito%20ayuda"
Ejemplo con JavaScript
const params = new URLSearchParams({ q: 'Hola, necesito ayuda' });
const response = await fetch(
`https://api.thaliq.com/api/agent/stream?${params}`,
{
headers: {
'X-API-Key': 'tq_live_xxx',
},
}
);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
// Procesar eventos separados por doble newline
let idx;
while ((idx = buffer.indexOf('\n\n')) !== -1) {
const rawEvent = buffer.slice(0, idx);
buffer = buffer.slice(idx + 2);
let eventType = 'message';
const dataLines = [];
for (const line of rawEvent.split('\n')) {
if (line.startsWith('event:')) eventType = line.slice(6).trim();
else if (line.startsWith('data:')) dataLines.push(line.slice(5).trim());
}
const data = JSON.parse(dataLines.join('\n'));
switch (eventType) {
case 'content.delta':
process.stdout.write(data.delta); // Mostrar texto progresivamente
break;
case 'tool.start':
console.log(`\n[Tool: ${data.tool}]`);
break;
case 'response.completed':
console.log('\n--- Fin ---');
break;
}
}
}
Ejemplo con EventSource (alternativa)
const params = new URLSearchParams({ q: 'Hola' });
const es = new EventSource(
`https://api.thaliq.com/api/agent/stream?${params}&apiKey=tq_live_xxx`
);
es.addEventListener('content.delta', (e) => {
const data = JSON.parse(e.data);
document.getElementById('response').textContent += data.delta;
});
es.addEventListener('response.completed', () => {
es.close();
});
es.addEventListener('error', () => {
es.close();
});
EventSource no soporta custom headers. Para enviar la API Key como header (recomendado), usa fetch con ReadableStream como en el ejemplo anterior.
Respondiendo a acciones interactivas
Cuando recibes un evento action, el stream se cierra. Para responder, envias un nuevo request con el parametro actionResponse:
// Respuesta a un confirm
const actionResponse = JSON.stringify({
instructionId: 'inst_abc123',
accepted: true,
});
const params = new URLSearchParams({
q: 'Quiero agendar una cita', // El mensaje original
actionResponse,
});
const response = await fetch(
`https://api.thaliq.com/api/agent/stream?${params}`,
{ headers: { 'X-API-Key': 'tq_live_xxx' } }
);
Tipos de actionResponse
Consent / Confirm:
{ "instructionId": "inst_xxx", "accepted": true }
Select:
{ "instructionId": "inst_xxx", "selectedValue": "opcion_1" }
Form:
{ "instructionId": "inst_xxx", "formValues": { "nombre": "Juan", "email": "juan@email.com" } }