API REST
Los agentes de Sherlock se exponen con una API compatible con la de OpenAI (/v1/chat/completions). Cualquier SDK o herramienta que hable con OpenAI funciona cambiando la dirección base y usando el slug del agente como modelo.
https://app.sherlock.posselab.net/v1Cada llamada pasa por el mismo motor que el resto de los canales: guardrails, búsqueda en el conocimiento, herramientas, trazas, costos y presupuesto.
Autenticación
Sección titulada «Autenticación»Mandá la API key en el encabezado Authorization:
Authorization: Bearer sk-sherlock-...También se acepta X-API-Key: sk-sherlock-.... Hay dos tipos de key:
| Key | Dónde se crea | Alcance |
|---|---|---|
| Del workspace | Configuración → API keys | Todos los agentes del workspace (elegís el agente con model) o uno solo. |
| De un canal API | Estudio → Canales → API | Un solo agente. |
El ambiente lo define la key: una key de «Producción» usa la versión publicada de cada agente; una de «Borrador», el borrador actual. Agregar @draft al modelo no cambia el ambiente.
Enviar un mensaje
Sección titulada «Enviar un mensaje»POST /v1/chat/completions
En los ejemplos, API_KEY es una variable de entorno con tu key.
curl https://app.sherlock.posselab.net/v1/chat/completions \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "asistente-seguros", "messages": [{"role": "user", "content": "¿Qué cubre la póliza de auto contra todo riesgo?"}] }'| Campo | Tipo | Notas |
|---|---|---|
model |
string | Slug del agente (o su ID). Obligatorio con keys de workspace; se ignora con keys de un solo agente. El slug figura en la lista de la API key («Nombre (slug)») y en GET /v1/models. |
messages |
array | Mensajes en formato OpenAI. Sherlock responde al último mensaje del usuario. |
stream |
boolean | true para recibir la respuesta en streaming (SSE). Por defecto false. |
conversation_id |
string | Para continuar una conversación (ver abajo). También se puede mandar en el encabezado X-Sherlock-Conversation. |
user |
string | Identificador de la persona en tu sistema. Aparece en Conversaciones. No mandes datos personales acá: usá un ID interno. |
Otros campos de OpenAI (temperature, max_tokens…) se aceptan y se ignoran: el comportamiento lo define la configuración del agente.
Respuesta
Sección titulada «Respuesta»{ "id": "chatcmpl-3f9a1c0e8b7d4a2e9c6b5d10", "object": "chat.completion", "created": 1759680000, "model": "asistente-seguros", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "La póliza contra todo riesgo cubre los daños propios del vehículo… [1]" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 1830, "completion_tokens": 142, "total_tokens": 1972 }, "sherlock": { "conversation_id": "8d2f5b1e-6a1c-4f0e-9b7a-2c3d4e5f6a7b", "run_id": "c41e9a77-0b2d-4c8e-a1f3-5d6e7f809a1b", "status": "ok", "citations": [ { "n": 1, "document_id": "…", "document": "Condiciones generales auto.pdf", "url": null, "page": 12, "heading": "Cláusula 4 · Cobertura todo riesgo", "snippet": "El Asegurador indemnizará los daños materiales…", "score": 0.83 } ], "cost_usd": 0.00041, "version": 3, "handoff": false }}El campo sherlock agrega lo que la API de OpenAI no tiene:
| Campo | Qué es |
|---|---|
conversation_id |
La conversación en Sherlock. Mandalo en el próximo mensaje para continuarla. |
run_id |
La ejecución: es el identificador de la traza en Conversaciones. |
status |
ok, blocked (un guardrail frenó el mensaje; content trae la respuesta configurada), handoff (la conversación está derivada a una persona), budget_exceeded (se agotó el presupuesto) o error. |
citations |
Las fuentes citadas: número (el [1] del texto), documento, página, sección, fragmento y puntaje. |
cost_usd |
Costo de la respuesta en modelos. |
version |
Versión del agente que respondió (en borrador, null). |
handoff |
true si la conversación quedó derivada a una persona. |
Con los SDK de OpenAI, sherlock llega como un campo adicional de la respuesta. Por ejemplo, con el SDK de Node.js:
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://app.sherlock.posselab.net/v1", apiKey: process.env.API_KEY });
const r = await client.chat.completions.create({ model: "asistente-seguros", messages: [{ role: "user", content: "¿Cómo denuncio un siniestro?" }],});console.log(r.choices[0].message.content);console.log(r.sherlock.citations);Conversaciones
Sección titulada «Conversaciones»Para que el agente recuerde el contexto, mandá el conversation_id que devolvió la primera respuesta:
curl https://app.sherlock.posselab.net/v1/chat/completions \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "X-Sherlock-Conversation: 8d2f5b1e-6a1c-4f0e-9b7a-2c3d4e5f6a7b" \ -d '{"model": "asistente-seguros", "messages": [{"role": "user", "content": "¿Y si el auto es 0 km?"}]}'- Si mandás
conversation_idy un solo mensaje, Sherlock usa el historial que tiene guardado. Es lo más simple: no hace falta reenviar la conversación. - Si mandás varios mensajes, usa el historial que mandaste.
- Sin
conversation_id, cada llamada empieza una conversación nueva.
El agente recuerda tantos intercambios como indique su «Memoria (turnos de historial)».
Streaming
Sección titulada «Streaming»Con "stream": true, la respuesta llega como Server-Sent Events con el formato estándar de OpenAI:
curl -N https://app.sherlock.posselab.net/v1/chat/completions \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "asistente-seguros", "stream": true, "messages": [{"role": "user", "content": "¿Qué es la franquicia?"}]}'data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"La franquicia es el monto que "},"finish_reason":null}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{…},"sherlock":{"conversation_id":"…","run_id":"…","status":"ok","citations":[…],"version":3}}
data: [DONE]El texto llega por frases (Sherlock revisa cada tramo con la salida segura antes de enviarlo). El último fragmento trae usage y sherlock con la conversación y las citas.
Con el mismo SDK:
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://app.sherlock.posselab.net/v1", apiKey: process.env.API_KEY });
const stream = await client.chat.completions.create({ model: "asistente-seguros", stream: true, messages: [{ role: "user", content: "¿Qué documentación necesito para un reintegro?" }],});for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? "");Listar agentes
Sección titulada «Listar agentes»GET /v1/models devuelve los agentes a los que puede hablar la key (uno, si la key es de un solo agente):
curl https://app.sherlock.posselab.net/v1/models -H "Authorization: Bearer $API_KEY"{ "object": "list", "data": [ { "id": "asistente-seguros", "object": "model", "created": 1759600000, "owned_by": "sherlock", "name": "Asistente de seguros" } ]}Errores
Sección titulada «Errores»Los errores tienen el formato {"detail": "…"}:
| Código | Mensaje | Qué hacer |
|---|---|---|
| 400 | «Indicá el agente en el campo ‘model’ (slug o id)» | Con keys de workspace, mandá model. |
| 401 | «Falta la API key (Authorization: Bearer sk-sherlock-…)» | Agregá el encabezado. |
| 401 | «API key inválida o revocada» | Revisá la key o creá una nueva. |
| 404 | «Agente no encontrado para esta API key» | El slug no existe en el workspace de la key, o el agente está archivado. |
| 409 | «El agente todavía no tiene una versión publicada en producción.» | Publicá el agente o usá una key de «Borrador». |
| 422 | «Dato inválido en …» | El cuerpo no tiene el formato esperado (por ejemplo, falta messages). |
| 429 | «Demasiadas solicitudes. Probá de nuevo en un minuto.» | Superaste el límite por minuto de la key. Reintentá con espera. |
Algunas situaciones responden 200 con un status especial, porque el agente sí contestó:
blocked: un guardrail frenó el mensaje (prompt injection, tema bloqueado, mensaje demasiado largo).contenttrae la respuesta configurada.budget_exceeded: el workspace llegó a su presupuesto con la acción «Pausar los agentes».contenttrae «El servicio alcanzó su límite de uso mensual. Contactá al administrador.»handoff: la conversación está derivada a una persona y el agente no responde (contentvacío). Las respuestas del operador quedan en el historial de la conversación en Sherlock.
Límites
Sección titulada «Límites»- Pedidos por minuto: los de cada key (60 por defecto en las del workspace, configurable hasta 10.000; 600 en las de un canal API). Al superarlo, 429.
- Largo del mensaje: el que defina el guardrail del agente (4.000 caracteres por defecto).
- Presupuesto: el del workspace.
Promptfoo y otras herramientas
Sección titulada «Promptfoo y otras herramientas»Como la API es compatible con OpenAI, también funciona con herramientas de evaluación como Promptfoo. La vista Evaluación de cada agente exporta su configuración lista: ver Exportar a Promptfoo.