A registry of model adapters that never throws, with circuit breakers, retries, and cost accounting.
@alembic/adapters is the only place the engine touches an LLM. It provides adapters for local OpenAI-compatible servers, a local cliproxyapi gateway, Anthropic, CLI-based agents, and a deterministic offline stub.
Every adapter obeys the same contract: run(input) returns a Result. If the network fails, the breaker opens, or the model refuses, you get a typed failure object — never a thrown exception.
Think of it like… a universal power adapter: the wall socket changes, but your device always sees the same voltage and plug.
The canonical spine is runWithGuards: validate input → circuit breaker → retry with backoff → attempt the transport → parse usage → compute cost → return ModelRunResult. Concrete adapters only implement the transport-specific attempt function. createAdapterRegistry wires adapters into a Map; pickAdapter routes by tier with no silent fallback.
# hermetic run uses the offline adapter alembic distill ./corpus --offline # live run routes through the default registry alembic distill ./corpus
createAdapterRegistry({ offline: { asDefault: true } }) registers only the offline adapter and makes it the default. In live mode, cliproxyapi is always registered and points to http://127.0.0.1:8317. The CLI preflights the registry before running expensive commands so missing credentials fail fast.
Run a command with --offline and then without it (if your gateway is up). Compare the cost reported in the output.
pickAdapter(Tier.T3, registry) returns an error, where is the bug most likely — the registry or the caller?