Providers and API keys
jangada supports several providers, each isolated in an adapter that translates
the normalized types (Message/Completion) to the native SDK.
| Provider | provider= | Environment variable | Extra to install |
|---|---|---|---|
| Anthropic | anthropic | ANTHROPIC_API_KEY | jangada-ai[anthropic] |
| OpenAI | openai | OPENAI_API_KEY | jangada-ai[openai] |
| Groq | groq | GROQ_API_KEY | jangada-ai[groq] |
| Gemini | gemini | GEMINI_API_KEY | jangada-ai[gemini] |
| Mistral | mistral | MISTRAL_API_KEY | jangada-ai[mistral] |
| OpenRouter | openrouter | OPENROUTER_API_KEY | jangada-ai[openai] |
| DeepSeek | deepseek | DEEPSEEK_API_KEY | jangada-ai[openai] |
| Ollama | ollama | OLLAMA_API_KEY (optional; not used locally) | jangada-ai[ollama] |
| AWS Bedrock | bedrock | AWS credentials (AWS_ACCESS_KEY_ID…) | jangada-ai[bedrock] |
| Azure OpenAI | azure | AZURE_OPENAI_API_KEY + AZURE_OPENAI_ENDPOINT | jangada-ai[openai] |
| Vertex AI | vertex | GOOGLE_CLOUD_PROJECT + ADC | jangada-ai[gemini] |
The last three are cloud gateways (AWS, Azure, Google Cloud): the same models, hosted in your cloud account, with the provider's IAM/billing/data residency. See AWS Bedrock, Azure OpenAI and Vertex AI.
OpenRouter (gateway to hundreds of models)
OpenRouter is a gateway compatible with OpenAI's
chat.completions dialect — so it reuses the same openai SDK (extra
jangada-ai[openai]), just pointing to a different base_url. It gives access to
hundreds of models from many providers with a single key. The model is
qualified by provider (provider/model):
LLM("openrouter", "openai/gpt-4o") # uses OPENROUTER_API_KEY
LLM("openrouter", "anthropic/claude-sonnet-4.6")
LLM("openrouter", "google/gemini-2.5-flash", api_key="sk-or-...")OpenRouter-only arguments (e.g. models for routing with fallback) go via
extra=; ranking headers via default_headers=:
LLM(
"openrouter", "openai/gpt-4o",
default_headers={"HTTP-Referer": "https://mysite.com", "X-Title": "My App"},
extra={"models": ["openai/gpt-4o", "anthropic/claude-sonnet-4.6"]},
)It supports text, streaming, structured output (json_schema with automatic
fallback to JSON Object mode), vision, tools/function calling, audio
transcription (openai/whisper-*, openai/gpt-4o-transcribe) and embeddings
(openai/text-embedding-3-*, google/gemini-embedding-001). The only unsupported
feature is server-side MCP (it relies on the Responses API, which OpenRouter
does not expose — raises UnsupportedError).
DeepSeek (reasoning + thinking mode)
DeepSeek also speaks chat.completions on its
own base_url — the same recipe as OpenRouter, reusing the openai SDK:
LLM("deepseek", "deepseek-v4-flash") # fast/cheap
LLM("deepseek", "deepseek-v4-pro") # reasoning (thinking mode)thinking mode is a field outside the OpenAI SDK's typed schema — pass it via
extra= and the adapter packs it into extra_body under the hood:
LLM("deepseek", "deepseek-v4-pro", extra={
"thinking": {"type": "enabled", "reasoning_effort": "high"}, # low/high/max
})Supports text, streaming, vision (deepseek-v4-flash-vision-exp) and
tools/function calling. Does not support strict JSON Schema (parse goes
straight to JSON Object mode), server-side MCP, or audio transcription — all
three raise UnsupportedError. See DeepSeek for
details.
Key resolution
LLM("openai", "gpt-4o-mini", api_key="sk-...") # explicit
LLM("openai", "gpt-4o-mini") # uses OPENAI_API_KEY or .envPrecedence: explicit api_key= > environment variable > .env file.
The .env is detected non-destructively at import time (disable it with
JANGADA_NO_DOTENV=1).
How each adapter handles structured output
- OpenAI:
chat.completions.parse(response_format=Modelo)→.message.parsed - Groq:
response_format={"type":"json_schema",...}+model_validate_json - Gemini:
config.response_schema=Modelo→resp.parsed - Anthropic: tool-forcing (
tool_choicefixed) → validatestool_use.input - OpenRouter: same as Groq (json_schema with fallback to JSON Object mode)
- DeepSeek: no json_schema — goes straight to JSON Object mode
See Structured output for the uniform usage.
Adding a new provider
If it speaks OpenAI's chat.completions dialect, inherit from
_OpenAICompatible and adjust sdk_module/sync_class/async_class. Otherwise,
implement the 6 methods of the Provider contract. Details in
Extending.
Generation parameters and per-model profiles
jangada accepts canonical parameter names and each adapter translates them to the SDK's native name, discarding the unsupported ones.
Per-provider capability matrix
What each provider supports in jangada. The public API features are the same (complete, parse, stream, transcribe, ...); what changes is what each provider can do under...