Taxonomía de errores
Cada error del Agent API tiene el mismo shape:
{
"error": {
"code": "validation_failed",
"message": "handle is required.",
"suggested_action": "fetch_pipeline",
"suggested_endpoint": "GET /pipelines/{id}"
}
}
| Campo | Detalle |
|---|---|
error.code | Siempre presente. Identificador estable (lista cerrada abajo). |
error.message | Siempre presente. Legible; informativo, no programático — programá contra code. |
error.suggested_action | Opcional. Próximo paso accionable por el agente cuando hay uno inequívoco (ej. connect_x_account, fetch_artifact). |
error.suggested_endpoint | Opcional. El endpoint a llamar para ejecutar suggested_action. |
X-Request-Idvive en el header de respuesta, no en el body. Correlacioná por ese header cuando reportes incidentes.
Lista cerrada de códigos
| HTTP | code | Cuándo |
|---|---|---|
400 | bad_request | JSON malformado, cursor inválido, campos requeridos ausentes fuera del set de validación. |
401 | unauthorized | Header Authorization ausente, token incorrecto, o AGENT_API_TOKEN no seteado en el server. |
403 | forbidden | El token es válido pero el estado del workspace prohíbe la acción (ej. publicar mientras sigue en draft). |
404 | not_found | El recurso no existe en el workspace asociado a este token. |
409 | state_conflict | El recurso no está en un estado válido para la operación (ej. publish_artifact sobre un artifact discarded). |
422 | validation_failed | El shape del body falló validación. message nombra el campo. |
424 | credential_missing | Falta una credencial de adapter que la operación necesita. suggested_action: connect_x_account para X. |
424 | credential_dead | La credencial guardada existe pero el probe falló (cookie expirada, token revocado). |
429 | rate_limited | Cuota por token excedida. Retry-After lleva el wait. |
503 | backend_unavailable | El canal interno whet-app ↔ backend no llega al backend. Chequeá BACKEND_BASE_URL y que el container backend esté sano. |
5xx | internal_error | Excepción no manejada. Siempre lleva X-Request-Id. |
Mapa de suggested-action
Cuando un error es recuperable sin un humano en el loop, la respuesta embebe un suggested_action. El agente puede actuar sobre él directamente:
suggested_action | Significado | Call recomendado |
|---|---|---|
connect_x_account | El scraper no tiene una cookie de X usable. | POST /x-accounts/connect |
fetch_artifact | El artifact puede haber cambiado de estado. | GET /artifacts/{id} |
fetch_pipeline | El pipeline puede haber cambiado de estado. | GET /pipelines/{id} |
diagnose_pipeline | El pipeline no está sano. | GET /pipelines/{id}/diagnose |
Si ves un suggested_action que no está en esta lista, es un valor forward-compatible — logueá y mostralo al operador.
Rate limits
El Agent API hace rate-limit por token. Defaults:
- Soft limit: 600 requests / minuto por token.
- Ventana burst: 1 minuto rolling.
Headers emitidos en toda respuesta autenticada (no solo en 429):
| Header | Valor |
|---|---|
RateLimit-Limit | 600 |
RateLimit-Remaining | entero |
RateLimit-Reset | segundos hasta el reset |
En 429:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
RateLimit-Limit: 600
RateLimit-Remaining: 0
RateLimit-Reset: 60
Patrón de manejo recomendado
async function call(method: string, path: string, body?: object) {
const res = await fetch(`${WHET_BASE_URL}${path}`, {
method,
headers: {
"Authorization": `Bearer ${WHET_TOKEN}`,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
if (res.ok) return res.json();
const { error } = await res.json();
const requestId = res.headers.get("X-Request-Id");
switch (error.code) {
case "rate_limited": {
const retryAfter = Number(res.headers.get("Retry-After") ?? "5");
await sleep(retryAfter * 1000);
return call(method, path, body);
}
case "credential_dead":
case "credential_missing":
throw new CredentialError(error, requestId);
case "validation_failed":
throw new ValidationError(error, requestId);
case "unauthorized":
throw new AuthError(error, requestId);
default:
throw new ApiError(error, requestId);
}
}
Correlación con logs
Cada respuesta incluye X-Request-Id. Copiá ese header cuando reportes un incidente. En deployments self-hosted los logs del workbench están indexados por el mismo id.
Ver también: Autenticación, Idempotencia, Webhooks.