Providers
adhere asks TypeSafe AI’s Jev by default. A provider asks another decision model instead, and adhere exports one for each model the providers study measured:
import { defineConfig, openai } from "@drkmttr/adhere";
// Asks with OPENAI_API_KEY, or the key `adhere login --openai` saved.export default defineConfig({ provider: openai() });| Provider | Asks | Options |
|---|---|---|
jev |
TypeSafe AI’s Jev, jev-latest by default |
apiKey, model |
openai |
OpenAI’s gpt-6-luna, on its Decisions API |
apiKey, model |
cloudflare |
Cloudflare’s clef, by default, or clef-flash, on Workers AI |
accountId, apiToken, model |
- Without an
apiKey,jevandopenaiask with the key from Login. - Each provider also takes
fetch, the function that sends its requests. - Clef cuts a request too long for it short rather than refuse it, so
cloudflareskips a file whose request reaches clef’s limit: 64,000 tokens, or 24,000 for clef-flash.
Writing a provider
A provider is a model’s name, and an ask that answers adhere’s questions
about a state:
import { defineConfig, type Provider, RequestFailed } from "@drkmttr/adhere";
const mine: Provider = { model: "my-decision-model", ask: async (state, questions, { signal }) => { const response = await fetch("https://decisions.example.com/v1/decide", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ state, questions }), signal, }); if (!response.ok) { throw new RequestFailed(`My model answered HTTP ${response.status}`, response.status); } return { answers: await response.json() }; },};
export default defineConfig({ provider: mine });stateis the file’s code by section undercode, beside what adhere read for it.- Each question has an
id, thequestionas adhere phrases it, and thefieldsit names in backticks, such asrule,must, andnever. Anoulasks whether something holds. Achoiceasks for the key of one of itsoptions. Itsoptionscan hold just one entry. askreturns{ answers }: by id, anoul’s probability from 0 to 1, or achoice’s key. An id left out goes unanswered: its rule is not reported, and is asked again on the next run.- A rejection stops the run, but for three errors adhere exports:
ContextOverflowgets one retry withoutreferenceswhen that map is present; if the request still overflows, the file is skipped.RequestBlockedreports it blocked, andRequestFailedis tried again, up to three times, when itsstatusis 0, for no answer, or a 408, 429, or 5xx. - adhere paces calls with
--rpm, abortssignalafter 30 seconds, and splits requests to fit Jev’s 64,000 tokens. A model that takes less splits further in itsask. modelreplaces the config’smodel. The cache keeps answers by it, so a new model is asked again.- A provider that sets
savedKeyto"typesafe"or"openai"gets that key asapiKey. - The executable resolves no packages besides
@drkmttr/adhere, so anaskusesfetchrather than an SDK.