Lamprey Provider & Model Reference
SkillAI & modelsThe multi-provider LLM domain pack for Lamprey — OpenAI-compatible streaming across 17 built-in providers (frontier labs, open-source hosts, keyless local runtimes) plus user-defined custom endpoints, per-provider quirks (reasoning field names, Anthropic's compat-layer limits, base-URL overrides), capability flags, the native-vs-fallback tool-calling contract, retry/backoff, retired-model handling, and the checklists for adding a model or a provider. Load when touching electron/services/providers/, debugging provider HTTP errors, or adding/retiring models.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Lamprey Provider & Model Reference skill
What this skill tells your AI
The instructions your AI receives, as published by uss-parks/lamprey-harness in .claude/skills/lamprey-provider-and-model-reference/SKILL.md and read by ahel’s review.
When to use / when not
- Use when working in
electron/services/providers/, adding or retiring a model/provider, debugging streaming/tool-calling/reasoning behavior, or choosing capability flags. - Don't use for general architecture (see
lamprey-architecture-contract), key storage (seelamprey-config-and-flags), or symptom triage (seelamprey-debugging-playbook).
Domain primer (terms defined once)
- OpenAI-compatible chat completions: the de-facto HTTP protocol (
POST …/chat/completions) all five providers speak. Requests carrymessages[], optionaltools[](JSON-schema function specs),stream: truefor SSE (Server-Sent Events — a long-lived HTTP response emittingdata:lines, each a JSON delta chunk). - Delta accumulation: streamed chunks carry partial content / partial
tool_calls; the client concatenates them until afinish_reasonarrives (stop,tool_calls,length). reasoning_content: a non-standard extra field some providers (DeepSeek, DashScope) stream alongsidecontent, carrying chain-of-thought. OpenRouter usesreasoning. Lamprey preserves it end-to-end (audit phase).- Context window: max input tokens the model accepts. Capability flags: per-model descriptor booleans/values that change dispatch behavior (below).
The registry (electron/services/providers/registry.ts)
Providers (17 built-in + custom) — ids are also the keychain ids
Built-ins since the Provider Expansion Phase (2026-07-11): deepseek, google,
dashscope, openrouter, zhipu, openai, anthropic, xai, mistral,
moonshot, groq, together, fireworks, cerebras, huggingface, plus
keyless local runtimes ollama and lmstudio (keyOptional: true, placeholder
key 'local', empty built-in catalogs — import live ids). User-defined custom
providers (settings.json.customProviders: {id, baseURL, label?, requiresKey?})
resolve like built-ins everywhere via resolveProviderDescriptor(id); built-in ids
cannot be shadowed. All dispatch rides the one OpenAI-compatible protocol; Google
goes through its v1beta/openai/ compat endpoint (FC-0), Anthropic through its
official OpenAI-compat layer at api.anthropic.com/v1/ (tools+streaming supported;
strict/response_format/reasoning_effort silently ignored — never set
reasoningCapOnToolUse on anthropic models). providerBaseUrlOverrides in
settings.json redirects any provider's base URL (http/https only, validated at the
registry). Per-provider wire notes: ARCHITECTURE/FUNCTION_CALLING.md §16.
MODEL_CATALOG (verified 2026-07-11, Provider Expansion Phase — re-verify command in Provenance)
39 entries. Per-id evidence status lives in PLANNING/PX_BASELINE.md §3.
| provider | ids (summary) | notes |
|---|---|---|
| deepseek | deepseek-v4-pro (default), deepseek-v4-flash | reasoners, full v0.15.5 guard |
gemma-3-27b-it, gemma-3-12b-it | ||
| openrouter | 4× gemma-4 + or-claude-sonnet-5, or-gpt-5.6-terra, or-grok-4.5, or-kimi-k2.5, or-llama-4-maverick | or- prefix avoids first-party id collisions; all live-verified on the public list |
| dashscope | qwen3-max, qwen3-coder-plus/flash, qwen3.5-plus/flash, qwen-long | qwen-long: huge context, no tools |
| zhipu | glm-5.2, glm-5.2-1m | [1m] suffix is a literal apiModelId |
| openai | gpt-5.6 (=Sol), gpt-5.6-terra, gpt-5.6-luna, gpt-5.5 | GA 2026-07-09; gpt-5.5-pro excluded (Responses-API-only) |
| anthropic | claude-opus-4-8, claude-sonnet-5, claude-haiku-4-5 | haiku is tier flash = the key-validation chat probe |
| xai | grok-4.5, grok-4.3, grok-build-0.1 | |
| mistral | mistral-large/medium/small-latest, codestral-latest | rolling aliases |
| moonshot | kimi-k2.6, kimi-k2.5, kimi-k2-thinking | thinking model carries the full reasoning guard |
| groq | llama-3.3-70b-versatile, llama-3.1-8b-instant, openai/gpt-oss-120b, openai/gpt-oss-20b | |
| together | Llama-3.3-70B-Turbo, DeepSeek-V4-Pro, gpt-oss-120b, Kimi-K2.6 (hub-style ids) | |
| fireworks | accounts/fireworks/models/gpt-oss-120b | UNVERIFIED until a key exists |
| cerebras | gpt-oss-120b, gemma-4-31b, zai-glm-4.7 | |
| huggingface | openai/gpt-oss-120b, meta-llama/Llama-3.3-70B-Instruct, zai-org/GLM-5.2 | hub ids; optional :policy/:provider suffix |
| ollama / lmstudio | (none — import) | keyless local runtimes |
Capability flags and what each changes at dispatch
| Flag | Effect |
|---|---|
supportsTools | false → native tools[] never sent; the FC-6 fallback contract is injected instead (below) |
supportsVision | gates image attachments |
isReasoner | reasoning-channel handling; native reasoners get the in-prose <think> bullet stripped from the system prompt (avoids double-emission) |
defaultMaxTokens | output budget applied when the caller omits one (v0.15.5 guard — DeepSeek V4 could exhaust its whole budget on reasoning and emit empty tool params) |
reasoningCapOnToolUse | sends reasoning_effort: 'low' when tools are offered (same v0.15.5 incident) |
tier | display/selection grouping (pro/flash/open/coder/reasoner) |
Rule: behavioral differences are expressed as flags on the descriptor, never as model-id conditionals scattered through dispatch code.
resolveModel priority chain
MODEL_CATALOGbuiltin → 2.RETIRED_MODEL_MAPremap → 3. custom models fromsettings.json.customModels(cache keyed by settings.json mtime; JM-11 fixed these being ignored) → 4. synthetic OpenAI-compatible fallback descriptor (assumes deepseek provider).
RETIRED_MODEL_MAP (v0.15.6): deepseek-chat→deepseek-v4-flash, deepseek-reasoner→deepseek-v4-pro, deepseek-v3→deepseek-v4-flash, deepseek-r1→deepseek-v4-pro. When a provider retires a model: add the mapping, delete the catalog entry, and sweep hardcoded ids across electron/ and src/ (the v0.15.6 sweep hit ChatInput, SideChatPanel, WorktreeManagerModal, AutomationsPanel, ModelSettings).
chatStream vs chatOnce
chatStream: the main path. Callbacks:onChunk(text delta),onReasoning,onVitals(~2s heartbeat feeding the "Ns since last chunk" pill),onDone(accumulated tool calls + final content),onError(partial content/reasoning preserved).onDonefires without being awaited — its body must catch its own errors (JM-8 lesson).chatOnce: one-shot completion returning{ content, reasoning? }, reading bothmessage.reasoning(OpenRouter) andmessage.reasoning_content(DeepSeek/DashScope).
Retry / stall behavior
- Up to 3 retries for HTTP 429 and connection errors without a status code, exponential backoff.
- Stream inactivity watchdog (T1): if no chunk arrives for
streamInactivityMs(default 60 000, min clamp 5 000,0disables), the attempt is aborted and retried with backoff; after retries exhaust, aStreamInactivityErrorsurfaces. - Per-attempt accumulators reset on retry (JM-9) — a retried stream must not duplicate the already-streamed prefix.
Tool calling: native vs fallback
Native path (supportsTools: true): JSON-schema tools sent with the request; streamed tool_calls deltas accumulated; arguments validated via validateToolArguments before dispatch — schema mismatches return a corrective tool result (the model is told what was wrong) rather than silently coercing to {} (JM-10).
Fallback path (supportsTools: false, or after downgrade): the model is instructed to emit
{"action": "<tool_name>", "input": { …args }}
and a brace-balanced parser (FC-6) extracts it from prose. Two hard rules:
- The fallback instruction must actually be injected into the prompt — it was dead code until JM-10; non-native models were never told the format.
- Fallback-parsed calls get
fb_-prefixed ids and skip persisted "always allow" approval policies (FC-9 trust degradation).
Capability downgrade (FC-10): 3 capability mismatches in a conversation (model claims/attempts tools it can't do natively) → session-scoped downgrade to the fallback path. Per-conversation state; cleared on conversation delete.
Checklist: adding a model
- Append a descriptor to
MODEL_CATALOGwith honest flags (testsupportsToolsempirically — send a trivial tool and see if a structuredtool_callsdelta comes back). - Confirm the provider id maps to an existing keychain entry; if the key is new, that's "adding a provider" (below).
- Set
defaultMaxTokens/reasoningCapOnToolUseif the model is a reasoner (check for the empty-params failure mode on tool turns). - Verify:
npx tsc --noEmit -p tsconfig.node.json && npx tsc --noEmit -p tsconfig.web.json, then a live smoke: stream a reply, force a tool call, confirm reasoning lands if applicable. - Route through
lamprey-change-control(trivial catalog append = small change; new behavior = plan).
Checklist: adding a provider (post-Provider-Expansion, 2026-07-11)
User-controlled OpenAI-compatible endpoint → zero code. Settings → API Keys →
Custom endpoints (persists settings.json.customProviders); the id becomes valid
across keychain, dispatch, Custom Models, verifyCatalog, and the /v1/models import.
Promoting a built-in:
- Add the id to BOTH
ProviderIdunions —providers/registry.tsandsrc/lib/types.ts(provider-parity.test.tssource-locks them; it caught a real one-sided widening the day it landed). - Add the
PROVIDERSentry: baseURL, keyEnv (= id), docsUrl,keyHint("sk-...") where the format is known,keyOptional: truefor keyless runtimes. - Add catalog models (checklist above). The Settings → API Keys card renders
automatically from
settings:listProviderKeys— no UI edit; only extend the renderer'sPROVIDER_GROUPSdisplay map inApiKeySettings.tsxif the new id should sit in a specific group (ungrouped ids show under Custom endpoints). - Validate
validateProviderKeyagainst the provider's cheapest endpoint (the chat-probe fallback uses the provider'sflash-tier catalog entry — give every key-required provider one). - Both tsc configs +
npm test+ live key test in Settings.
Provenance and maintenance
Based on direct reads of electron/services/providers/registry.ts (catalog ids, retired map, watchdog constants re-verified 2026-07-11 during the Provider Expansion Phase) plus ARCHITECTURE/FUNCTION_CALLING.md §16 and PLANNING/PX_BASELINE.md, at v0.17.0.
Re-verify:
- Catalog:
grep -n "id: '" electron/services/providers/registry.ts - Retired map:
grep -n -A8 "RETIRED_MODEL_MAP" electron/services/providers/registry.ts - Watchdog defaults:
grep -n "DEFAULT_STREAM_INACTIVITY_MS" electron/services/providers/registry.ts - Fallback contract injection:
grep -rn "FALLBACK_TOOL_INSTRUCTION\|\"action\"" electron/services/ | grep -i fallback | head - Downgrade threshold:
grep -n "MALFORMED\|MISMATCH" electron/services/tool-unlock-state.ts electron/services/capability-*.ts 2>/dev/null
Signals
- GitHub stars
- 62
- Forks
- 2
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
lamprey-provider-and-model-reference- Source
- github.com/uss-parks/lamprey-harness