byokit
Get a model list, let the user choose, and call that model with their API key. BYOKit provides offline catalog queries and text-generation adapters for JavaScript/TypeScript and Python.
Website and playground · Model explorer · Verify a model · SDK reference
Install
npm install byokit
# Or, for Python:
pip install byokit
Call a model
These examples run in Node.js or Python. Run JavaScript as an ES module (.mjs, or "type": "module" in package.json); TypeScript uses your usual compiler or runner. Set DEEPSEEK_API_KEY in the process environment first. The key must belong to the selected provider; BYOKit does not supply credentials.
JavaScript / TypeScript
import * as byokit from 'byokit';
const key = process.env.DEEPSEEK_API_KEY;
if (!key) throw new Error('Set DEEPSEEK_API_KEY');
const [model] = byokit.getModels(byokit.DEFAULT, {
providerIds: [byokit.ProviderId.DeepSeek],
local: false,
limit: 1,
filters: { callable: true },
});
if (!model?.connection) throw new Error('No matching callable model');
const response = await byokit.call(model, 'Hello!', key);
console.log(response.choices[0].message.content);
Python
import os
import byokit
key = os.environ["DEEPSEEK_API_KEY"]
models = byokit.get_models(byokit.DEFAULT, {
"providerIds": [byokit.ProviderId.DEEP_SEEK],
"local": False,
"limit": 1,
"filters": {"callable": True},
})
if not models or not models[0]["connection"]:
raise ValueError("No matching callable model")
model = models[0]
response = byokit.call(model, "Hello!", key)
print(response["choices"][0]["message"]["content"])
getModels() / get_models() is synchronous and sends no requests. call() sends one request to the selected model's configured endpoint. JavaScript calls return a Promise; Python calls are synchronous. The direct helper chooses the wire protocol from model.connection.protocol and returns an OpenAI-compatible completion, including for supported Claude, Gemini, and Ollama adapters.
Integration contract for developers and AI coding agents
- Choose an offering, not a model name guessed from memory.
DEFAULTis a maintained recommendation list. UseCOMPLETEfor full discovery, then apply filters. Always handle an empty result. - Use the correct identifier. Pass the complete returned model object to
byokit.call(). When using a client, passmodel.apiModelIdas the request'smodelstring.model.ididentifies a provider offering and is not necessarily an API model ID. - Match the key to
model.providerId. A reseller offering needs that reseller's key, not the model creator's key. For multiple providers, keep a separate key for each provider. Never send one key across a model list containing different providers. - Check call support.
model.callSupport.textGenerationdescribes adapter compatibility. It does not prove availability, account access, credits, or a successful call. Newly discovered providers can be listed without a call adapter. - Keep the protocol.
byokit.call()reads it automatically. With BYOKit'sOpenAIorAnthropicclients, copy bothconnection.baseUrlandconnection.protocol. These clients implement a subset of familiar SDK interfaces; they are not the official SDKs. - Local requires configuration. The generic Local setup entry is not callable. Supply a URL, protocol, and exact served model ID; configuration sends no request. Do not infer installed models or scan local ports.
- Execution supports non-streaming text and tool-call responses. Image/audio/video models are discoverable, but media generation and streaming execution are not implemented. Returned tool calls are never executed automatically.
- Keep credentials outside model metadata and source code. Use environment variables on servers. In browser apps, collect the user's key in memory and send it directly to its endpoint; provider CORS policies may prevent browser calls.
A returned model uses the same field names in JavaScript objects and Python dictionaries:
| Field | Meaning |
|---|---|
id |
Provider-offering identity; use for selection and records |
providerId |
Provider whose endpoint and account key are used |
apiModelId |
Exact model ID sent to that provider |
connection |
{ baseUrl, protocol }, or null if no reviewed connection exists |
callSupport |
{ textGeneration, reason } |
local |
Present on Local entries: { endpoint, api, configured } |
modalities |
Declared input / output arrays; unknown values can be null |
limits, price, features |
Provider-specific facts; unknown values must stay unknown |
lifecycle, verification |
Separate provider evidence and community observations |
JavaScript and Python function/enum names differ; model field names do not:
| JavaScript | Python |
|---|---|
getModels, getModelsByProvider |
get_models, get_models_by_provider |
ProviderId.OpenAI, ProviderId.DeepSeek |
ProviderId.OPEN_AI, ProviderId.DEEP_SEEK |
ProviderId.Google, ProviderId.Anthropic |
ProviderId.GOOGLE, ProviderId.ANTHROPIC |
ProviderId.OpenRouter, ProviderId.ZhipuAI |
ProviderId.OPEN_ROUTER, ProviderId.ZHIPU_AI |
ProviderId.SiliconFlow, ProviderId.Mistral, ProviderId.Groq |
ProviderId.SILICON_FLOW, ProviderId.MISTRAL, ProviderId.GROQ |
LocalApi.OpenAI, LocalApi.Ollama |
LocalApi.OPEN_AI, LocalApi.OLLAMA |
ApiProtocol.OpenAI, ApiProtocol.Gemini, ApiProtocol.Claude |
ApiProtocol.OPEN_AI, ApiProtocol.GEMINI, ApiProtocol.CLAUDE |
and, or, not, xor |
and_, or_, not_, xor_ |
callClaude, checkFit |
call_claude, check_fit |
Local models
Replace my-installed-model with the exact model ID served by your server. No discovery, verification, or model download is needed to construct the entry. The call itself requires a running server with that model available.
import * as byokit from 'byokit';
const [model] = byokit.getModels({
providerIds: [], // Return only the configured Local entry.
local: [
{
endpoint: 'http://localhost:11434',
api: byokit.LocalApi.Ollama,
modelId: 'my-installed-model',
},
],
});
const response = await byokit.call(model, 'Hello!', '');
console.log(response.choices[0].message.content);
import byokit
model = byokit.get_models({
"providerIds": [],
"local": [{
"endpoint": "http://localhost:11434",
"api": byokit.LocalApi.OLLAMA,
"modelId": "my-installed-model",
}],
})[0]
response = byokit.call(model, "Hello!", "")
print(response["choices"][0]["message"]["content"])
For an OpenAI-compatible local server, use LocalApi.OpenAI / LocalApi.OPEN_AI and its base URL, such as http://localhost:8000/v1. The empty key means no authentication; pass the server's own key separately when required. connection.baseUrl and connection.protocol are resolved on the returned entry. Local IDs stay stable across list reordering and distinguish endpoint, protocol, and model.
The website's Set up a local server action offers URL, protocol, model ID, and Use this model. Saving sends no request. Find models and Verify model are separate, explicit actions; local results stay private.
Reusable SDK clients
Use these when your app prefers chat.completions.create() or messages.create(). They reuse a key at a fixed endpoint. After selecting model and key as in the hosted examples:
const client = new byokit.OpenAI({
baseURL: model.connection.baseUrl,
protocol: model.connection.protocol,
apiKey: key,
models: [model], // Optional metadata; also preserves the offering's call-support checks.
});
const response = await client.chat.completions.create({
model: model.apiModelId,
max_tokens: 128,
messages: [{ role: byokit.Role.User, content: 'Hello!' }],
});
console.log(response.choices[0].message.content);
client = byokit.OpenAI(
base_url=model["connection"]["baseUrl"],
protocol=model["connection"]["protocol"],
api_key=key,
models=[model],
)
response = client.chat.completions.create(
model=model["apiModelId"],
max_tokens=128,
messages=[{"role": byokit.Role.USER, "content": "Hello!"}],
)
print(response.choices[0].message.content)
For Claude-style responses, use byokit.Anthropic and client.messages.create(...), with the same endpoint/protocol fields and an explicit max_tokens. In JavaScript the result is message.content; in Python use message.content or message["content"]. callClaude() / call_claude() is the stateless equivalent. See complete Claude examples and official SDK integration.
A request's model string is sent unchanged. Without catalog metadata in models, a reusable client can send arbitrary API model IDs with unknown capabilities; it does not automatically select or verify those IDs.
Discovery and filters
| List | Behavior |
|---|---|
DEFAULT / no arguments |
Maintained offering recommendations plus a Local setup entry |
COMPLETE |
Every imported offering, including deprecated, uncertain, unsupported, and media entries |
GLOBAL, CHINA |
Editorial provider collections with default call-support/lifecycle filtering |
OFFICIAL / OFFICIAL_FLAGSHIP |
First-party creator offerings; excludes aggregators and the generic Local entry |
Pass local: false (Python: "local": False) to exclude Local setup entries. DEFAULT is the way to request curated current choices; do not approximate it by picking the newest release. Full coverage means the upstream catalog plus reviewed manual additions, not every model that exists.
import * as byokit from 'byokit';
const textModels = byokit.getModels(byokit.COMPLETE, {
local: false,
filters: {
callable: true,
lifecycle: byokit.any(byokit.Lifecycle.Live, byokit.Lifecycle.Uncertain),
speciality: byokit.Speciality.General,
tier: byokit.any(byokit.Tier.Workhorse, byokit.Tier.Flash),
},
});
console.log(textModels.map((model) => model.apiModelId));
// Catalog discovery only; this does not enable image generation calls.
const imageModels = byokit.getModels(byokit.COMPLETE, {
local: false,
filters: { output: byokit.contain(byokit.Modality.Image) },
});
console.log(imageModels.map((model) => model.apiModelId));
Python accepts the same configuration dictionary using True / False and Python enum names, such as byokit.Lifecycle.LIVE, byokit.Speciality.GENERAL, and byokit.Tier.FLASH.
exact(...)matches the exact set;contain(...)requires all requested values and permits extras;any(...)requires at least one;exclude(...)rejects matches. Boolean matchers compose them. Input arrays require all requested modalities; output arrays match the exact output set. Usecontain(Modality.Image)to include image output alongside other outputs.providerIdsis a top-level option. Other filters are insidefilters. Catalog provider ID strings such as"fireworks-ai"are supported without enum membership; an unknown provider ID is rejected at runtime.filters.callablenarrows adapter compatibility.filters.lifecyclenarrows provider-backed lifecycle evidence and takes precedence overincludeDeprecated.Lifecyclevalues areLive,Outdated, andUncertainin JavaScript; there is noRetiredenum member.specialityandtierare editorial classifications, not model IDs or availability checks. Both may beUnknown; tier also includesEdge. Do not invent enum members based on a model name.- Price fields are token prices per million tokens; media pricing may be unknown. Unknown capabilities, limits, and prices are not zero or unsupported.
- Supported sorts include
ModelSort.PriceAscend,PriceDescend,AlphabeticalAscend,AlphabeticalDescend, andProviderOrder. Speed sort enum values are reserved and currently throwNotImplementedError.
See filter types and enum definitions for the full API surface.
Errors and execution defaults
A failed attempt does not establish that a model is retired or unavailable for everyone. CallError exposes code, optional HTTP status, and normalized attempt metadata such as reason, scope, and retry guidance. Examples include quota exhaustion, invalid credentials, access restrictions, rate limits, network errors, and timeouts. No automatic retry occurs; honor provider retry guidance when implementing manual retries.
Execution defaults: non-streaming text, an output limit of 1,024 tokens capped by a known model limit, a 90-second timeout, and zero automatic retries. Use max_tokens in the request to set output length. JavaScript execution options are the fourth argument to call() or the second argument to client .create(); Python uses the fourth call() argument or client options={...}. JavaScript supports signal and timeoutMs; Python supports cancel_event and timeout_ms.
Budget/capability enforcement is optional. Use checkBudget: true / check_budget=True and supply token counts when needed. Offline checkFit(model, { inputTokens, outputTokens }) (Python: check_fit) returns status, certainty, and diagnostics; status is fits, exceeds, or unknown. It does not return a fits boolean, and unknown metadata does not establish a fit.
Custom endpoints
Use appendModel(models, custom) / append_model(models, custom) to append an explicitly configured endpoint. Required custom fields are providerId, modelId, baseUrl, and protocol; JavaScript custom provider IDs can use customProviderId('acme'). Pass the appended model to call() with that endpoint's own key. Appending runs offline and does not verify the endpoint or its capabilities. See custom catalog integration.
Build a smaller model list
Dynamic discovery loads the bundled catalog. For a fixed query, generate a smaller static list so the app does not need the full catalog at runtime. Sizes depend on the query; generation itself does not call providers.
Create byok.config.json:
{
"list": "default",
"local": false,
"filters": { "callable": true }
}
# JavaScript / TypeScript:
npx byokit build byok.config.json --out src/generated/models.js
# Python:
python -m byokit build byok.config.json --out app/generated_models.py
The JavaScript output exports getModels() and generated ID constants; the Python output exports get_models() and generated enums. Use a returned model directly with call(); do not assume an enum member or model ID will exist in every generated query. For JavaScript, import execution helpers from byokit/client to avoid including the bundled catalog.
Credential safety
- Built-in execution keeps keys in memory and sends them directly to the configured endpoint, with redirects disabled. It does not persist keys or send telemetry. Never include keys in model metadata, URLs, reports, prompts, or source code.
- Authenticated remote calls require HTTPS. HTTP authentication is allowed on
localhost, IPv4 loopback, and::1. Trusted development networks can explicitly opt in usingallowInsecureHttp: true/allow_insecure_http=True; this exposes credentials to that network. The website has no such bypass. - The website persists sanitized verification records in browser storage, not keys, prompts, or generated text. Sharing on GitHub is an explicit action. Keys do leave the browser for the selected provider's endpoint.
- The DOM picker's default credential store is in memory. A custom
credentialStorereceives raw keys and controls persistence.credentialRefis a namespace scoped by provider and known connection; changing connections clears the key field. - Python clients block pickling and generic JSON attribute dumps of their credential holders. Serialize non-secret settings and recreate clients instead. Application callbacks, custom transports, debugging tools, and process-memory inspection remain the application's responsibility.
Highlights and further documentation
BYOKit combines maintained recommendations, full catalog discovery, optional DOM/React pickers, reusable protocol clients, build-time query generation, and separate community verification evidence. Catalog snapshots are refreshed by the repository's scheduled workflow; installed packages use their bundled snapshot until updated. A fresh catalog is not proof of a successful call.
| Import / guide | Purpose |
|---|---|
byokit |
Public helpers, enums, queries, and calls |
byokit/catalog |
Same helpers plus the default catalog data export |
byokit/client |
Execution/core helpers without the bundled catalog |
byokit/enums |
Enum constants |
byokit/dom, byokit/react |
Optional model/key pickers |
| SDK guide | Client interfaces, protocol adapters, official SDKs |
| Integration guide | UI callbacks, credential stores, local discovery |
| Verification guide | Attempts, community evidence, speed measurements, sharing |
Maintainers: edit this root README, then run npm run readme:sync to update the npm and PyPI READMEs. npm run readme:check and executable documentation tests catch drift.
MIT license. Built on the open Models.dev catalog. Contribute · License
Metadata
Release files for byokit 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| byokit-0.2.0.tar.gz | 807.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| byokit-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.6 MB
Release files / byokit-0.2.0.tar.gz
| Download URL | byokit-0.2.0.tar.gz |
|---|---|
| Size | 807.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b97b56b9bca405ad705c913430a1a79ea926a5cec058495bb83f4e4c6d99ff83
|
|
BLAKE2b-256 checksum How to use checksums |
0e22ce4c5af784ac1b3401c22dff339f4884c5aca1ca30cbcfad9b6fd1900cb0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / byokit-0.2.0-py3-none-any.whl
| Download URL | byokit-0.2.0-py3-none-any.whl |
|---|---|
| Size | 831.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
84de5f7a568327f94d0ce39b3e646419bd38386d18da4cd5144bf75dc8c539d3
|
|
BLAKE2b-256 checksum How to use checksums |
170a4456a57d4015ae6fa6c47cb9bca4e64e7694883de7c67e2122a0590c9c53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logSecurity for byokit 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for byokit-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.