Development record
A provider adapter serves only the models it lists, under a vendor denylist no listing overrides; everything else runs on the host
Context
adr-25 makes the model host-delegated by default: the agent host owns model choice, credentials and execution, and abcd's adapters (an OpenAI-compatible API, a command-line runner, a reviewer route over MCP) are opt-in. The first aggregator to reach abcd through the API adapter is OpenRouter, brought by a new decision model (Jev, TypeSafe AI, September 2026) that is reachable only that way. An aggregator serves every vendor's models under one key, including the frontier models the person already pays for through the host and its subscription. The adapter draft as written would route any model name it was handed. The product thinker asked, on 2026-09-21, how to integrate OpenRouter and how to ensure only certain models are reached through it, so that a frontier model is never billed through the aggregator or its data routed through a third party unasked.
Decision
We will make every provider adapter default-deny by model.
- An allowlist per provider. Each provider block in the configuration lists the model identifiers it may serve. A role or a judgement configured for a model not on its provider's list is refused when the configuration is read, before any call is made, naming the list.
- A vendor denylist above the allowlist. A bundled denylist of vendor
prefixes (
anthropic/*at minimum) refuses a listed model whose prefix it matches, and no allowlist entry overrides it; the repository or the machine may extend the denylist and never shorten it below the bundled set. Superseded 2026-09-30 by adr-2609300107513982 (ruling H9 of 2026-09-29): abcd bundles no vendor denylist and the allowlist alone decides; the decision above is kept as it was taken. Decisions 1, 3, 4 and 5 are carried forward there word for word. - Everything else runs on the host. A model that is neither listed nor the host's own is not a route; the host and the person's subscription are where frontier models run.
- The key is named, never stored. The adapter reads its credential from the machine's configuration or the environment by name; nothing about a key enters the repository.
- The run record names the route. Every call through an adapter records the provider, the model identifier asked for and the model the provider reports, so a substitution by the aggregator is visible.
Alternatives Considered
- Any model the key can reach, controlled at the provider. Rejected: the aggregator's own controls are outside the record, invisible to the run, and a listing mistake on the provider's side would route a frontier model through it with nothing in abcd to say so.
- An allowlist only, no denylist. Rejected: a listing mistake in the repository's configuration would reach a frontier model; the denylist is the rule that a mistake cannot override.
- A denylist only. Rejected: default-allow leaves every newly listed aggregator model routable the day it appears.
Consequences
- The API adapter intent (itd-2609081951381895) carries the list, the denylist, the refusal and the record as criteria; the model tier (itd-2609170822093401) reads the lists when it proposes a route; the decision adapter (itd-2609221009495079) can name only a listed model.
- A person who wants a frontier model through an aggregator edits the denylist on their machine, deliberately, and the run record shows it.
- The brief's adapters chapter gains the invariant.
- Consequence added 2026-09-29: a route to a provider that holds a key is
the machine's alone. Decision 4 keeps the key's value out of the
repository; the product thinker's ruling AA(b) of 2026-09-29 keeps the
repository from spending it too. Only a route the person set up on their own
machine may use their paid key, so a role or a judgement type the
repository's configuration points at a provider whose block names a key is
skipped when the configuration is read, with a diagnostic naming
~/.abcd/config.jsonas where to set it; the rest of the configuration loads, and the machine's own route to that name applies in its place (the technical facilitator's ruling CD2 of 2026-09-29 chose the skip over refusing the whole configuration). A repository's route to a provider that holds no key (a local server) and a--routethe person types are unaffected. This reverses the route half of itd-2609081951381895 Decision 8, which said a route "may sit in either layer"; that decision is amended in the same change. The allowlist and the denylist above still apply to every route that is admitted.
Frontmatter
| id | adr-2609221009491186 |
|---|---|
| type | adr |
| status | superseded |
| date | 2026-09-22 |
.abcd/development/decisions/adrs/2609221009491186-a-provider-adapter-serves-only-the.md
open on GitHub ↗ · commit history ↗
References6
- adr-25The LLM is host-delegated by default; oracles are opt-in adaptersrelated
- adr-2609300107513982A provider adapter's allowlist alone decides which models it serves, and abcd bundles no vendor denylistrelated
- itd-6RepoPrompt over MCP is one opt-in reviewer route, beside the host's own agentsrelated
- itd-2609081951381895abcd ships an OpenAI-compatible API adapter, and a provider serves only the models it listsrelated
- itd-2609170822093401abcd proposes the model each agent deserves, and facilitates it where it canrelated
- itd-2609221009495079abcd's typed judgements can run through a decision adapter, measured in a lab before it decides anythingrelated
Referenced by6
- adr-2609221017021499Every external credential abcd holds is named in configuration and kept in one store the person chose; never the harness, never the repositoryrelated
- adr-2609300107513982A provider adapter's allowlist alone decides which models it serves, and abcd bundles no vendor denylistsuperseded by
- itd-2609201916056194A role runs through the command-line harness the operator chose, and every fall back to the host is recordedrelated
- itd-2609221656361680A managed repository reports back to abcd, and abcd says so at its next startrelated
- itd-2609221656373558Two sessions share one run, and the run measures which way of dividing the work is bestrelated
- itd-2609301918174237A remote provider takes a file-reading agent only as a fixed, blanked, capped bundlerelated
mentions9
- dcn-26092200000000012026-09-22 — Model routing, after an independent research pass (product thinker, at an interactive interview). Jev (TypeSafe AI, on OpenRouter) is a typed-decision model, not a router: it fits abcd's closed-option judgements and nothing generative. Rulings: a provider adapter serves only the models it lists under a vendor denylist no listing overrides, everything else on the host (adr-2609221009491186); the OpenAI-compatible API adapter is planned with OpenRouter as configuration, a one-time walkthrough at ahoy and the key kept out of the harness (itd-2609081951381895); a decision adapter for the typed judgements runs in shadow as an abcd lab and a research note is the evidence a ruling turns a judgement type on with (itd-2609221009495079); escalation inside a lane is a rule on a failed fix round, recorded on the model tier (itd-2609170822093401); model per role, the pick and consistency are not routing and stand as ruled; itd-17's learned router is superseded. Every external credential abcd holds goes through one store with three homes the person chooses (adr-2609221017021499, itd-2609221017023290); the API adapter and the site setup read through it. The research is filed as research/notes/2026-09-22-jev-and-model-routing-sota.md.
- dcn-26093000000000062026-09-30 — The technical facilitator's ruling H9 of 2026-09-29 is applied (recorded by lane denyRetire of autonomous run A; the answer is kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md`, dated 2026-09-29, and restated here because that file is not committed): the bundled `anthropic/*` vendor denylist is retired and a provider's allowlist alone decides which models it serves. adr-2609300107513982 supersedes adr-2609221009491186, revising its decision 2 and carrying decisions 1, 3, 4 and 5 forward word for word; itd-2609081951381895's criterion 3 and spc-2609221011153746 are amended to the allowlist-alone reading, with the old wording in the intent's Audit Notes (iss-2609300110451242). This answers the follow-up the 2026-09-29 entry above left to the technical facilitator under AA(a), whether the bundled entry stays as a backstop: it does not. Ruling Y (added 2026-09-26, from lane apiadapter: may a person remove a bundled entry on their own machine) closes as moot, since no bundled entry remains to remove. The detail H9 left to the lane, whether `oracle.denylist` survives as an optional repository or machine extension, is decided as keep: the setting already existed in both layers, and removing the bundled list leaves it working with no added code, which is the ruling's condition.
- dcn-26100200000000072026-10-02 — Ruling CD2 of the person as technical facilitator (2026-09-29, same interview and local-tier file as the DR3 entry above; recorded by lane rd2), verbatim: "repository route to a keyed provider: WARN AND SKIP that route (other commands keep working), not a hard LoadAPI refusal." Built: a repository's route to a provider that holds a key is skipped with a diagnostic and the machine's own route to that name applies in its place (`skipKeyedRoute` in `internal/core/oracle/config.go`; a repository's malformed route and malformed route name are skipped under the same ruling); decision 8 of itd-2609081951381895 and adr-2609221009491186 carry it.
- iss-2609300110451242Ruling H9 of 2026-09-29 retires the bundled anthropic/* vendor denylist, which changes the reading of itd-2609081951381895 acceptance criterion 3 (a listed model whose prefix matches the vendor denylist is refused at read, and no allowlist entry overrides it) and of adr-2609221009491186 decision 2: with no bundled list the provider's allowlist alone decides, so a listed model of any vendor is served, and only an oracle.denylist entry the repository or the machine writes refuses a listed model
- spc-2609180535002478abcd proposes the model each agent deserves, and facilitates it where it can
- spc-2609221011151661abcd-s-typed-judgements-can-run-through-a-decision-adapter
- spc-2609221011153746abcd-ships-an-openai-compatible-api-oracle-adapter-the-first
- spc-2609221533057881abcd-runs-a-delegated-agent-through-a-command-line-model-run
- spc-2609251028149555A failed fix round escalates one tier, and a provider route stays on its allowlist