Saltar al contenido principal

Idempotencia

Reintentar un POST /pipelines/from-intent sin coordinarte con el servidor crea dos pipelines. Para evitarlo, cada call mutativo del Agent API acepta un campo idempotency_key en el body (16–128 caracteres).

Repetir con la misma key devuelve el mismo run_id / pipeline_id / artifact — nunca uno nuevo.

Dónde vive la key​

EndpointCampo
POST /pipelines/from-intentbody idempotency_key
POST /posts/{id}/draftbody idempotency_key
POST /artifacts/{id}/publishbody idempotency_key
POST /x-accounts/connectbody idempotency_key
POST /scrapebody idempotency_key (opcional — repetir pares (url, intent) pega al response cache igual)

Los endpoints read-only (GET /pipelines/{id}, GET /pipelines/{id}/inbox, etc.) ignoran el campo.

Las tools MCP espejan el mismo parámetro — cada tool mutativa expone idempotency_key con la misma semántica. Ver MCP · tools.

Formato​

PropiedadDetalle
Longitud16–128 caracteres. Más corto o más largo devuelve validation_failed.
CharsetASCII libre. Hex de UUIDv4 (32 chars después de quitar dashes) es el shape recomendado.
Scope(organization_id, endpoint, key). Dos orgs distintas pueden usar la misma key sin colisionar.
TTLEl servidor guarda la respuesta original durante la vida del recurso subyacente — replays después de borrar el recurso devuelven 404 not_found, no un body cacheado.

Estados de replay​

SituaciónResultado
Misma key + mismo body + original completadoDevuelve el mismo run_id / id de recurso que el primer call. Los side effects no se repiten.
Misma key + body distintoEl endpoint devuelve su error normal (típicamente validation_failed) — las keys no están atadas al shape del body, pero las invariantes subyacentes siguen aplicando.
Misma key + original todavía corriendoEl call devuelve el run_id del original. Polleá ese run; no generes una key nueva.

Hoy no hay HTTP 409 idempotency_request_in_progress — from-intent devuelve inmediatamente con el pipeline existente + el run id original.

Patrón recomendado en el cliente​

  1. Generá un UUIDv4 al inicio del intento lógico.
  2. Reusalo en cada retry de ese mismo intento.
  3. Generá uno nuevo solo cuando el usuario vuelva a accionar con intención (es acción nueva, no retry).
const idempotencyKey = crypto.randomUUID().replaceAll("-", "");
// hex de 32 chars — holgadamente dentro del rango 16–128.

await fetch(`${WHET_BASE_URL}/pipelines/from-intent`, {
method: "POST",
headers: {
"Authorization": `Bearer ${WHET_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
handle: "growth_dr",
intent: "Track for analytical drafts, daily.",
idempotency_key: idempotencyKey,
}),
});

Lo que no es​

  • No es un cache de aplicación. No lo uses para "saltarte" requests porque ya sabés la respuesta — el servidor sigue validando invariantes.
  • No sobrevive para siempre. Una vez borrado el recurso subyacente, los replays devuelven 404 not_found.
  • No aplica a GET, PATCH ni DELETE. Asegurate de que esos reintentos sean idempotentes del lado tuyo.

Ver también: Autenticación, Taxonomía de errores.