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_progressfrom-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.