Skip to the content.

Context

A single LLM model identifier is referenced from many call sites across a codebase. Providers retire dated model snapshots on their own schedule, so an ID that is valid today can start returning 404 at a future date with no change to the code.

Example

Zeeguu’s reader has an on-demand “Ask AI” translation action. Its model ID, claude-sonnet-4-20250514, was hardcoded at three call sites in the translation service and two more in the multi-word-expression (MWE) detector. Anthropic retired that snapshot; every call began returning 404 not_found_error. The error was swallowed one layer down (the helper returns None on any exception), so the endpoint returned a generic 404 "LLM translation failed" and the reader silently degraded to an “Ask AI, try again” button that could never succeed.

centralized model selection try again

Nothing in the code had changed; a date had passed. The error started showing up.

The fix itself was mechanical: swap to the live snapshot the rest of the codebase already used. But finding it took a dig through production logs, and the swap had to be repeated at five sites.

To avoid this happening again in the future, Zeeguu now keeps every model identifier in one module, keyed by role, the job a model does in a feature (WORD_TRANSLATION, MWE_DETECTION, SIMPLIFICATION, …), and each resolving to a canonical vendor ID declared once; a feature asks for models.WORD_TRANSLATION and never names a snapshot, so the next retirement is a one-line edit.

Problem

How can a provider’s model retirement be survived without hunting down every hardcoded model ID scattered across the codebase?

Forces

Solution

Keep every model identifier in one central module. Declare the canonical vendor IDs once, then expose role-based aliases (one per use: translation, classification, simplification…) that resolve to them. Call sites import the role, never the raw string. Surviving a vendor retirement, or moving one feature to a cheaper or faster tier, becomes a one-line change in a file that documents the whole model landscape on one screen.

Consequences

War Story

The same commit that repaired the retirement uncovered a second casualty of the identical disease. Simplified articles were being stamped ai_model="claude-3-5-sonnet" while the simplifier had long since moved to Haiku. The provenance field named a model that was no longer even in the pipeline (see LLM Output Provenance). Same root cause as the retirement: a model identifier duplicated into a place nobody remembers to update, silently going stale. Centralizing selection lets the provenance stamp and the call-time choice read from the same constant, so they cannot disagree.

Known Uses

Notes


💬 Open an issue about this pattern