Idempotency
Every call has one identity, safe to retry without double-charging.
Every underlying model invocation made through enlitt() — standard or
premium — has exactly one identity, sent as the Idempotency-Key header (and
additionally as call_id on the premium preflight). Retrying the identical
step reuses that identity; the wire deduplicates on it, so a retried call
never charges, reserves, or invokes a provider twice for the same step.
Supplying your own key
await generateText({
model: enlitt(ENLITT_STANDARD_MODEL),
prompt,
providerOptions: {
enlitt: {
idempotencyKey: "ticket-42-summary-attempt"
}
}
});idempotencyKey must be 16–200 visible ASCII characters. Supply your own key
when you already have a natural, stable identifier for the logical operation
being retried (a job ID, a request ID your own system generated). Omit it and
the SDK generates a fresh crypto.randomUUID() base per invocation.
Why a key is a base, not the final identity
The SDK never sends your key unchanged. It appends the number of items in the
call's prompt — never a hash or any other read of your content — producing
`${base}.${promptItemCount}` as the final identity. This is what makes
identity behave correctly inside a tool-calling loop: within one
generateText run, the prompt grows by at least one item before each
subsequent model invocation, so distinct steps of the same loop get distinct
identities automatically, while a genuine retry of one step — which
re-presents the identical prompt — reuses the same identity and is
deduplicated.
This means you do not need to generate a new key per retry, and should not: the point of supplying a base at all is that the same base, retried, collapses to the same call. Generating a fresh key on every attempt (for example, inside the function that performs the retry, rather than once before the retry loop begins) defeats the protection entirely and is the one mistake this mechanism exists to prevent.
Where else idempotency applies
Frontend's own dashboard mutations (creating an application, creating or rotating an API key) follow the identical pattern at the HTTP layer: a key is generated once on the client, cached against the specific thing being mutated, reused across retries of that one action until it succeeds, and only then discarded. Account closure and authorization revocation are idempotent by construction and take no key at all — retrying either one is always safe without any header.