Scope check
Due diligence
What problem does this solve?
Using a non-default provider requires passing provider: on every call:
RubyLLM.chat(model: 'claude-sonnet-4-6', provider: :bedrock)
RubyLLM.chat(model: 'claude-haiku-4-5', provider: :bedrock)
There's no way to configure this globally, so anyone using bedrock/azure/vertexai as their primary provider ends up with a monkey patch or extra provider: keys everywhere.
This only covers chat — you'd need the same for embed, paint, transcribe, and moderate. It also bypasses the model resolution layer, so alias handling and bedrock region inference don't work correctly.
Proposed solution
default_providers: Route models to specific providers based on model ID prefix.
- More specific keys take precedence over shorter ones.
- Only applies when no explicit provider: argument is passed.
RubyLLM.configure do |config|
config.default_providers = {
'claude' => :bedrock, # all claude models route to bedrock
'claude-haiku' => :anthropic, # except haiku, which goes direct to anthropic
'gpt' => :azure, # all gpt models route to azure
'gemini' => :vertexai, # all gemini models route to vertex ai
'claude-sonnet-4-5' => :openrouter, # one specific model via openrouter
}
end
Why this belongs in RubyLLM
Specifying provider every time is a waste and unnecessary.
Right now I do this with a Monkey Patch because we always use bedrock for claude, would love to get rid of it!
module RubyLLMBedrockDefaultPatch
def chat(model:, provider: nil, **options)
provider ||= :bedrock if model.to_s.match?(/^claude-/)
super
end
end
# Prepend to RubyLLM module to default Claude models to Bedrock
RubyLLM.singleton_class.prepend(RubyLLMBedrockDefaultPatch)
Scope check
Due diligence
What problem does this solve?
Using a non-default provider requires passing
provider:on every call:There's no way to configure this globally, so anyone using bedrock/azure/vertexai as their primary provider ends up with a monkey patch or extra
provider:keys everywhere.This only covers chat — you'd need the same for embed, paint, transcribe, and moderate. It also bypasses the model resolution layer, so alias handling and bedrock region inference don't work correctly.
Proposed solution
default_providers: Route models to specific providers based on model ID prefix.Why this belongs in RubyLLM
Specifying provider every time is a waste and unnecessary.
Right now I do this with a Monkey Patch because we always use bedrock for claude, would love to get rid of it!