Evaluating Bitrouter Routes
bitrouter/bitrouter
A skill your agent uses when evaluating BitRouter route decisions or Eval Exchange subjects with task-native verifiers, human reviewers, private enterprise evaluators, agentic judges, or genuinely…
LiteLLM-RS provider system in two tiers - data-driven OpenAI-compatible catalog entries auto-routed through OpenAILikeProvider, plus code-based provider modules implementing the LLMProvider trait…
$ npx skills add majiayu000/litellm-rs --skill provider-architecture -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install majiayu000/litellm-rs provider-architecture --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/majiayu000/litellm-rs.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/provider-architecture .claude/skills/provider-architecture && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "provider-architecture" agent skill from https://github.com/majiayu000/litellm-rs/tree/main/.claude/skills/provider-architecture into .claude/skills/provider-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "provider-architecture", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/majiayu000/litellm-rs/tree/main/.claude/skills/provider-architectureType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add majiayu000/litellm-rs --skill provider-architecture -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install majiayu000/litellm-rs provider-architecture --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/majiayu000/litellm-rs.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/provider-architecture .agents/skills/provider-architecture && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "provider-architecture" agent skill from https://github.com/majiayu000/litellm-rs/tree/main/.claude/skills/provider-architecture into .agents/skills/provider-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "provider-architecture", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add majiayu000/litellm-rs --skill provider-architecture -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install majiayu000/litellm-rs provider-architecture --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/majiayu000/litellm-rs.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/provider-architecture .cursor/skills/provider-architecture && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "provider-architecture" agent skill from https://github.com/majiayu000/litellm-rs/tree/main/.claude/skills/provider-architecture into .cursor/skills/provider-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "provider-architecture", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/majiayu000/litellm-rs.git --path .claude/skills/provider-architecture--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add majiayu000/litellm-rs --skill provider-architecture -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install majiayu000/litellm-rs provider-architecture --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/majiayu000/litellm-rs.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/provider-architecture .gemini/skills/provider-architecture && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "provider-architecture" agent skill from https://github.com/majiayu000/litellm-rs/tree/main/.claude/skills/provider-architecture into .gemini/skills/provider-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "provider-architecture", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install majiayu000/litellm-rs provider-architectureInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add majiayu000/litellm-rs --skill provider-architecture -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/majiayu000/litellm-rs.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/provider-architecture .github/skills/provider-architecture && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "provider-architecture" agent skill from https://github.com/majiayu000/litellm-rs/tree/main/.claude/skills/provider-architecture into .github/skills/provider-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "provider-architecture", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add majiayu000/litellm-rs --skill provider-architecture -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install majiayu000/litellm-rs provider-architecture --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/majiayu000/litellm-rs.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/provider-architecture .opencode/skills/provider-architecture && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "provider-architecture" agent skill from https://github.com/majiayu000/litellm-rs/tree/main/.claude/skills/provider-architecture into .opencode/skills/provider-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "provider-architecture", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
provider-architectureLiteLLM-RS provider system in two tiers - data-driven OpenAI-compatible catalog entries auto-routed through OpenAILikeProvider, plus code-based provider modules implementing the LLMProvider trait…
Provider Architecture is an agent skill from majiayu000/litellm-rs. LiteLLM-RS provider system in two tiers - data-driven OpenAI-compatible catalog entries auto-routed through OpenAILikeProvider, plus code-based provider modules implementing the LLMProvider trait behind the closed Provider enum. Covers unified ProviderError handling, connection pooling, capabilities, and model metadata. Use when adding a new provider, editing registry/catalog.rs, or implementing/debugging the LLMProvider trait.
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files (for example `reference/best-practices-and-checklist.md` and `reference/migration-from-legacy-errors.md`).
It sits in Databases, covering Model routing and gateways and Database administration. It works with OpenAI and Rust. The repository describes itself as: Self-hosted Rust LLM gateway with OpenAI-compatible APIs, load balancing, failover, and a reusable Rust kernel. The licence is MIT.
6 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit ed3f4d9. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are rust and bash).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
MYPROVIDER_API_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Provider Architecture loads about 4.9k tokens when it runs. Until then it costs about 113 tokens; SKILL.md has 842 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from majiayu000/litellm-rs at commit ed3f4d9, republished under its MIT licence (© majiayu000). 842 words, ~4,870 tokens.
.claude/skills/provider-architecture/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.Providers come in two tiers behind one implementation trait:
Tier 1 — Catalog-only (zero code). An OpenAI-compatible endpoint that differs only in
base URL, auth env var, and advertised capabilities/models. It has no Rust module: one
static entry in src/core/providers/registry/catalog.rs fully describes it, and the
factory builds an OpenAILikeProvider from that data at runtime. This is the primary
path for new integrations.
Tier 2 — Code-based. A provider needing custom request/response transformation,
custom auth signing, non-standard streaming, or rich model metadata lives in
src/core/providers/<name>/, implements LLMProvider, and is wired into routing.
Routing does not use trait objects. Router deployments store the closed Provider
enum (src/core/providers/mod.rs), which dispatches to concrete provider structs.
LLMProvider (src/core/traits/provider/llm_provider/trait_definition.rs) is the
interface every variant implements — implementing the trait alone does not make a
provider routeable; enum variant, dispatch arm, and factory wiring are crate-level
changes. Trait objects appear only at the edges: the error mapper
(Box<dyn ErrorMapper<ProviderError>>) and the streaming return type
(Pin<Box<dyn Stream<Item = Result<ChatChunk, ProviderError>> + Send>>).
Do not rely on memorized counts — they change often. Count from source:
# Tier 1: one def_chat()/def_local_chat() call per entry
# (each count includes the helper fn definition itself, so subtract 1)
grep -c 'def_chat(' src/core/providers/registry/catalog.rs
grep -c 'def_local_chat(' src/core/providers/registry/catalog.rs
# Tier 2: code-based provider modules (base/factory/macros/registry are infrastructure)
ls -d src/core/providers/*/ | grep -vE '/(base|factory|macros|registry)/'Two edits, nothing else:
// src/core/providers/registry/catalog.rs
def_chat(
"myprovider",
"My Provider",
"https://api.myprovider.com/v1",
"MYPROVIDER_API_KEY",
),// src/core/providers/mod.rs — annotation comment alongside the other Tier 1 notes
// myprovider: Tier 1 -> registry/catalog.rsAt runtime create_provider (src/core/providers/factory/mod.rs) matches the selector
against the catalog, builds an OpenAILikeConfig via
ProviderDefinition::to_openai_like_config, and constructs
openai_like::OpenAILikeProvider::new_for_catalog(oai_config, def.capabilities) into the
Provider::OpenAILike variant.
Keyless local servers use def_local_chat (AuthType::None, skip_api_key = true):
def_local_chat("myrunner", "My Runner", "http://localhost:1234/v1"),Each entry is a ProviderDefinition (src/core/providers/registry/definition.rs).
Defaults from def_chat can be overridden with struct-update syntax:
alternate_auth_env_vars — env vars checked after auth_env_var (see together)model_prefix: Some("xai/") — selector/model prefix stripping (see xai)capabilities profile replacing the default
OPENAI_LIKE_CATALOG_CAPABILITIES (ChatCompletion, ChatCompletionStream,
ToolCalling, FunctionCalling)canonical_catalog_name() in catalog.rs (e.g.
"zhipuai" -> "zhipu")Registry API (src/core/providers/registry/, re-exported in registry/mod.rs):
is_tier1_provider(name), get_definition(name), canonical_catalog_name(name),
PROVIDER_CATALOG.
There are no associated types. Every fallible method returns the unified
ProviderError directly.
// src/core/traits/provider/llm_provider/trait_definition.rs
pub trait LLMProvider: Send + Sync + Debug + 'static {
// ===== Required =====
fn name(&self) -> &str;
fn capabilities(&self) -> &'static [ProviderCapability];
fn models(&self) -> &[ModelInfo];
fn get_supported_openai_params(&self, model: &str) -> &'static [&'static str];
async fn map_openai_params(
&self,
params: HashMap<String, Value>,
model: &str,
) -> Result<HashMap<String, Value>, ProviderError>;
async fn transform_request(
&self,
request: ChatRequest,
context: RequestContext,
) -> Result<Value, ProviderError>;
async fn transform_response(
&self,
raw_response: &[u8],
model: &str,
request_id: &str,
) -> Result<ChatResponse, ProviderError>;
fn get_error_mapper(&self) -> Box<dyn ErrorMapper<ProviderError>>;
async fn chat_completion(
&self,
request: ChatRequest,
context: RequestContext,
) -> Result<ChatResponse, ProviderError>;
async fn health_check(&self) -> HealthStatus;
async fn calculate_cost(
&self,
model: &str,
input_tokens: u32,
output_tokens: u32,
) -> Result<f64, ProviderError>;
// ===== Provided (default = not_supported / trivial) =====
fn error_provider_name(&self) -> &'static str { "provider" }
fn supports_capability(&self, capability: &ProviderCapability) -> bool {
self.capabilities().contains(capability)
}
fn supports_model(&self, model: &str) -> bool {
self.models().iter().any(|m| m.id == model)
}
// supports_tools / supports_streaming / supports_embeddings /
// supports_image_generation delegate to supports_capability();
// supports_vision() currently returns false.
async fn chat_completion_stream(&self, request: ChatRequest, context: RequestContext)
-> Result<Pin<Box<dyn Stream<Item = Result<ChatChunk, ProviderError>> + Send>>, ProviderError>;
async fn embeddings(&self, request: EmbeddingRequest, context: RequestContext)
-> Result<EmbeddingResponse, ProviderError>;
async fn image_generation(&self, request: ImageGenerationRequest, context: RequestContext)
-> Result<ImageGenerationResponse, ProviderError>;
async fn audio_transcription(&self, request: TranscriptionRequest, context: RequestContext)
-> Result<TranscriptionResponse, ProviderError>;
async fn audio_translation(&self, request: TranslationRequest, context: RequestContext)
-> Result<TranslationResponse, ProviderError>;
async fn text_to_speech(&self, request: SpeechRequest, context: RequestContext)
-> Result<SpeechResponse, ProviderError>;
async fn get_average_latency(&self) -> Result<std::time::Duration, ProviderError>; // default 100ms
async fn get_success_rate(&self) -> Result<f32, ProviderError>; // default 0.99
async fn estimate_tokens(&self, text: &str) -> Result<u32, ProviderError>; // len()/4
}Optional dispatch methods (streaming, embeddings, images, audio) must still be gated by
the matching ProviderCapability — route selection checks supports_capability()
before calling them.
Real examples: src/core/providers/cloudflare/ (small) and src/core/providers/openai_like/.
src/core/providers/my_provider/
├── mod.rs # Module exports, LLMProvider impl may live here too
├── config.rs # Config struct (often via define_provider_config!)
├── provider.rs # Provider struct + LLMProvider impl
├── model_info.rs # Static model metadata
├── streaming.rs # SSE parsing (optional)
└── error.rs # Error helpers/mappers (optional; legacy name = ProviderError alias)BaseConfig (src/core/providers/base/config.rs) carries api_key, api_base,
endpoint_access, timeout (secs), max_retries, headers, organization,
api_version, with env fallbacks ({PROVIDER}_API_KEY, {PROVIDER}_API_BASE, ...)
via from_env(provider) / for_provider(provider).
Implement the ProviderConfig trait (src/core/traits/provider/config.rs) — note the
accessor names differ from BaseConfig's helpers:
pub trait ProviderConfig: Send + Sync + Clone + Debug + 'static {
fn validate(&self) -> Result<(), String>;
fn api_key(&self) -> Option<&str>;
fn api_base(&self) -> Option<&str>;
fn timeout(&self) -> std::time::Duration;
fn max_retries(&self) -> u32;
fn endpoint_access(&self) -> ProviderEndpointAccess { ProviderEndpointAccess::PublicOnly }
fn use_ssrf_safe_client(&self) -> bool { false }
// validate_standard(provider_name): shared key/timeout/retries checks
}The define_provider_config! macro (exported from base/config.rs) generates the
struct, builders (with_api_key, with_base_url, with_timeout), from_env(),
get_api_key()/get_api_base(), and the ProviderConfig impl in one call.
Modeled on src/core/providers/cloudflare/provider.rs:
use std::sync::Arc;
use crate::core::providers::base::{header, BaseConfig, GlobalPoolManager, HttpMethod};
use crate::core::providers::ProviderError;
use crate::core::traits::error_mapper::trait_def::ErrorMapper;
use crate::core::traits::error_mapper::DefaultErrorMapper;
use crate::core::traits::provider::llm_provider::trait_definition::LLMProvider;
use crate::core::traits::provider::ProviderConfig;
pub struct MyProvider {
config: MyProviderConfig,
pool_manager: Arc<GlobalPoolManager>,
models: Vec<ModelInfo>,
}
impl MyProvider {
pub fn new(config: MyProviderConfig) -> Result<Self, ProviderError> {
config.validate()
.map_err(|e| ProviderError::configuration(PROVIDER_NAME, e))?;
let http_config = BaseConfig {
api_key: config.api_key().map(str::to_owned),
api_base: config.api_base().map(str::to_owned),
endpoint_access: config.endpoint_access(),
timeout: config.timeout().as_secs(),
max_retries: config.max_retries(),
..BaseConfig::default()
};
Ok(Self {
config,
pool_manager: Arc::new(GlobalPoolManager::new_for_provider(
PROVIDER_NAME,
http_config,
)?),
models: load_models(),
})
}
}
impl LLMProvider for MyProvider {
fn name(&self) -> &'static str { PROVIDER_NAME }
fn error_provider_name(&self) -> &'static str { PROVIDER_NAME }
async fn chat_completion(
&self,
request: ChatRequest,
context: RequestContext,
) -> Result<ChatResponse, ProviderError> {
let api_key = self.config.api_key()
.ok_or_else(|| ProviderError::authentication(PROVIDER_NAME, "API key required"))?;
let mut headers = vec![header("Authorization", format!("Bearer {api_key}"))];
headers.push(header("Content-Type", "application/json".to_string()));
// url/model/request_id derived from config + request (elided)
let body = self.transform_request(request, context).await?;
let response = self.pool_manager
.execute_request(&url, HttpMethod::POST, headers, Some(body))
.await?;
let status = response.status();
if !status.is_success() {
let body_text = response.text().await
.map_err(|e| ProviderError::network(PROVIDER_NAME, e.to_string()))?;
return Err(self.get_error_mapper().map_http_error(status.as_u16(), &body_text));
}
let raw = response.bytes().await
.map_err(|e| ProviderError::network(PROVIDER_NAME, e.to_string()))?;
self.transform_response(&raw, &model, &request_id).await
}
fn get_error_mapper(&self) -> Box<dyn ErrorMapper<ProviderError>> {
Box::new(DefaultErrorMapper)
}
// ... remaining required methods
}Adding a Tier 2 provider means crate-level wiring, in this order of authority:
src/core/providers/<name>/, its module declaration, and a closed Provider
enum variant under the same feature gate in src/core/providers/mod.rs.dispatch_provider! @expand arms (sync,
async_err, value, async_direct) and to Provider::name() and
provider_type().ProviderType variant and all_non_custom_provider_types() entry in
provider_type.rs.catalog_backed and the correct
ProviderDispatchKind to PROVIDER_TYPE_REGISTRY in registry/types.rs.
For a feature-gated native implementation, use or add a cfg-sensitive
dispatch-kind helper that reports the correct enabled and disabled modes;
registry entries themselves do not have a feature field.factory/builder.rs and match branch in
factory/registry.rs, with matching feature gates. Keep cfg gates synchronized
across module, Provider, dispatch and factory wiring.The recommended new_for_provider path runs requests through BaseHttpClient and
ProviderHttpClient. ProviderHttpClient keeps a process-wide client cache keyed by
endpoint policy, request timeout, and mode (ordinary, streaming, or no-redirect). Those
clients use HttpClientPoolConfig::default() (src/utils/net/http.rs): 100 maximum idle
connections per host, 90-second idle timeout, 10-second connect timeout, and 60-second
TCP keepalive.
PoolConfig in src/core/providers/base/connection_pool.rs (there is no pool.rs)
instead configures the legacy global ConnectionPool used by the unbound new() /
shared() path. These constants do not tune the policy-bound clients above:
pub struct PoolConfig;
impl PoolConfig {
pub const TIMEOUT_SECS: u64 = 600;
pub const POOL_SIZE: usize = 80; // pool_max_idle_per_host
pub const KEEPALIVE_SECS: u64 = 90; // pool_idle_timeout
}// Provider implementations use new_for_provider(provider, BaseConfig) so
// endpoint-access and timeout policy are installed. new()/shared() omit that policy.
pub async fn execute_request(
&self,
url: &str,
method: HttpMethod, // GET | POST | PUT | DELETE
headers: Vec<HeaderPair>, // (Cow<'static, str>, Cow<'static, str>)
body: Option<serde_json::Value>, // serialized as JSON; not generic
) -> Result<reqwest::Response, ProviderError>;
pub async fn execute_streaming_request(
&self,
url: &str,
headers: Vec<HeaderPair>,
body: serde_json::Value,
legacy_provider: &'static str,
) -> Result<reqwest::Response, ProviderError>;Build header pairs zero-copy where possible: header(key, value) (static key, owned
value), header_static(key, value), header_owned(key, value). Streaming callers get a
separate client without a total-body timeout via streaming_unbounded_client(); header
phase bounded by STREAMING_HEADER_TIMEOUT_SECS, error bodies by
read_streaming_error_body (10s / 64KiB caps).
ModelInfo (src/core/types/model.rs) is a plain serializable struct with Default:
pub struct ModelInfo {
pub id: String,
pub name: String,
pub provider: String,
pub max_context_length: u32,
pub max_output_length: Option<u32>,
pub supports_streaming: bool,
pub supports_tools: bool,
pub supports_multimodal: bool,
pub input_cost_per_1k_tokens: Option<f64>,
pub output_cost_per_1k_tokens: Option<f64>,
pub currency: String,
pub capabilities: Vec<ProviderCapability>,
pub created_at: Option<SystemTime>,
pub updated_at: Option<SystemTime>,
pub metadata: HashMap<String, serde_json::Value>,
}Costs are per 1K tokens (catalog pricing constants in registry/catalog.rs are per
million and divided by 1_000 when converted). Return &self.models from
LLMProvider::models(); supports_model() scans that slice.
ProviderCapability (src/core/types/model.rs) — the full current variant list:
pub enum ProviderCapability {
ChatCompletion,
ChatCompletionStream,
Embeddings,
ImageGeneration,
ImageEdit,
ImageVariation,
AudioTranscription,
AudioTranslation,
TextToSpeech,
Moderation,
Rerank,
ToolCalling,
FunctionCalling,
CodeExecution,
FileUpload,
FineTuning,
BatchProcessing,
RealtimeApi,
GeminiGenerateContent,
}Return a static slice (a temporary array literal cannot back &'static [...]):
const MY_CAPABILITIES: &[ProviderCapability] = &[
ProviderCapability::ChatCompletion,
ProviderCapability::ChatCompletionStream,
ProviderCapability::ToolCalling,
];
fn capabilities(&self) -> &'static [ProviderCapability] {
MY_CAPABILITIES
}ProviderError (src/core/providers/unified_provider_error.rs, re-exported as
crate::core::providers::ProviderError and unified_provider::ProviderError) is the
single error type across the trait. Construct with factory methods
(src/core/providers/unified_provider_methods.rs) rather than struct literals — some
variants carry extra optional fields (e.g. RateLimit rpm/tpm limits):
ProviderError::authentication(provider, msg)
ProviderError::rate_limit(provider, retry_after: Option<u64>)
ProviderError::rate_limit_with_retry(provider, msg, retry_after)
ProviderError::model_not_found(provider, model)
ProviderError::invalid_request(provider, msg)
ProviderError::network(provider, msg)
ProviderError::timeout(provider, msg)
ProviderError::api_error(provider, status: u16, msg)
ProviderError::provider_unavailable(provider, msg)
ProviderError::not_supported(provider, feature)
ProviderError::configuration(provider, msg)
ProviderError::serialization(provider, msg)ErrorMapper<E> (src/core/traits/error_mapper/trait_def.rs) converts HTTP statuses
and JSON error bodies into errors: required map_http_error(u16, &str); defaulted
map_json_error, map_network_error, map_parsing_error, map_timeout_error.
Ready-made mappers:
GenericErrorMapper — core::traits::error_mapper::types, aliased
DefaultErrorMapper at core::traits::error_mapper (what most providers return from
get_error_mapper())OpenAIErrorMapper, AnthropicErrorMapper — core::traits::error_mapper::implementationsLegacy per-provider error enums were removed; surviving names like AnthropicError or
GeminiError are pub type ... = ProviderError aliases
(see reference/migration-from-legacy-errors.md).
© majiayu000, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files in .claude/skills/provider-architecture of majiayu000/litellm-rs.
Open the folder on GitHubat commit ed3f4d9
Provider Architecture next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Provider Architecture this skillmajiayu000/litellm-rs | 118 | — | ~4.9k | Automated safety check: Pass | MIT | |
| Evaluating Bitrouter Routesbitrouter/bitrouter | 235 | — | ~1.2k | Automated safety check: Pass | Apache-2.0 | |
| Run Bitrouter Benchmarkbitrouter/bitrouter | 235 | — | ~2.2k | Automated safety check: Pass | Apache-2.0 | |
| Run Shuntpleaseai/shunt | 203 | — | ~2.6k | Automated safety check: Pass | Apache-2.0 | |
| Sea Orm 2FlyinPancake/yoink | 112 | — | ~2.9k | Automated safety check: Pass | Apache-2.0 | |
| Veloxdb Scalable Performanceveloxbase/veloxdb | 652 | — | ~1.7k | Automated safety check: Pass | MIT |
bitrouter/bitrouter
A skill your agent uses when evaluating BitRouter route decisions or Eval Exchange subjects with task-native verifiers, human reviewers, private enterprise evaluators, agentic judges, or genuinely…
bitrouter/bitrouter
A skill your agent uses when a user wants to run, compare, resume, audit, share, or submit a Harbor benchmark through BitRouter, including choosing a Harbor dataset and agent, confirming routed…
pleaseai/shunt
Build, launch, and drive shunt — the Claude Code LLM gateway (a Rust/axum Anthropic-Messages proxy).
FlyinPancake/yoink
Expert guidance for SeaORM 2.0, Rust's async ORM with strongly-typed columns, nested ActiveModels, Entity Loader API, and entity-first workflow.
veloxbase/veloxdb
Guides scalability and performance work for VeloxDB's Tauri + Rust PostgreSQL backend and React + TanStack frontend.
hex/claude-council
Adds new AI providers to claude-council, configures provider API settings, troubleshoots provider connections, and documents the provider script interface.
majiayu000/litellm-rs
LiteLLM-RS Authentication Architecture. An agent skill from majiayu000/litellm-rs.
majiayu000/litellm-rs
LiteLLM-RS response caching architecture. An agent skill from majiayu000/litellm-rs.
majiayu000/litellm-rs
LiteLLM-RS Configuration Architecture. An agent skill from majiayu000/litellm-rs.
majiayu000/litellm-rs
LiteLLM-RS Error Handling Architecture. An agent skill from majiayu000/litellm-rs.
majiayu000/litellm-rs
LiteLLM-RS Observability Architecture. An agent skill from majiayu000/litellm-rs.
majiayu000/litellm-rs
LiteLLM-RS Routing Architecture. An agent skill from majiayu000/litellm-rs.
Categories
LiteLLM-RS provider system in two tiers - data-driven OpenAI-compatible catalog entries auto-routed through OpenAILikeProvider, plus code-based provider modules implementing the LLMProvider trait…. Provider Architecture is an agent skill from majiayu000/litellm-rs. LiteLLM-RS provider system in two tiers - data-driven OpenAI-compatible catalog entries auto-routed through OpenAILikeProvider, plus code-based provider modules implementing the LLMProvider trait behind the closed Provider enum.
Provider Architecture fits situations like: adding a new provider; editing registry/catalog.rs; implementing/debugging the LLMProvider trait.
Run `npx skills add majiayu000/litellm-rs --skill provider-architecture -a claude-code`. Or copy the skill folder (.claude/skills/provider-architecture in majiayu000/litellm-rs) into .claude/skills/provider-architecture in your project. Claude Code loads it when a task matches its description.
Run `npx skills add majiayu000/litellm-rs --skill provider-architecture -a codex`. Or copy the skill folder (.claude/skills/provider-architecture in majiayu000/litellm-rs) into .agents/skills/provider-architecture in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add majiayu000/litellm-rs --skill provider-architecture -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/provider-architecture, .gemini/skills/provider-architecture, .github/skills/provider-architecture and .opencode/skills/provider-architecture in your project.
Going by SKILL.md and its folder, Provider Architecture needs credentials named MYPROVIDER_API_KEY. Our summary lists: A credential in MYPROVIDER_API_KEY.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Provider Architecture is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.9k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Provider Architecture: Evaluating Bitrouter Routes (bitrouter/bitrouter, 235 stars), Run Bitrouter Benchmark (bitrouter/bitrouter, 235 stars), Run Shunt (pleaseai/shunt, 203 stars) and Sea Orm 2 (FlyinPancake/yoink, 112 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
majiayu000 (a GitHub user) maintains it in majiayu000/litellm-rs, which has 118 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on October 11, 2026.
Source: majiayu000/litellm-rs on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.