Migrating Chat Completion from Gemini to Sarvam
This guide covers migrating Gemini text generation and chat calls to Sarvam. It doesn’t cover Gemini’s audio capabilities; see Migrating Text-to-Speech and Migrating Speech-to-Text for those.
In short: if your code already goes through the openai Python package pointed at Gemini’s OpenAI-compatible endpoint, this migration is a two-line change: swap the api_key and base_url, keep everything else. If you’re on the native google-genai SDK’s interactions.create(), messages replaces input + system_instruction, and the response reads back in the same choices[0].message.content shape either way.
Quick start
Base URL and auth header change the same way for every Gemini migration on the native SDK path, so they’re folded in here rather than in a separate page:
With that, replace the generation call:
Before (Gemini)
After (Sarvam)
If your code goes through the openai package instead, see the next section: it’s a separate, often simpler route for Chat Completion specifically.
If you’re using the OpenAI-compatible endpoint
Gemini exposes an OpenAI-compatible Chat Completions endpoint, and so does Sarvam. If your code already goes through the openai package, migrating is just a client config change:
Sarvam accepts the same Authorization: Bearer <key> header the openai package sends by default, on every endpoint, not just Chat Completion. See Authentication for details.
Endpoint map
The tables below aren’t a checklist to apply field-by-field: Quick Start above already shows the whole call swapped over in one go. Use these tables as a reference for what changed and why, not as a sequence of edits to make yourself.
Parameter concept map
What’s different by design
- One message list, not a split input/system_instruction. The system prompt is just another entry in
messages, so the whole conversation, including instructions, lives in one place. - No interaction ID to track. Sarvam follows the stateless, resend-the-history convention used by OpenAI-compatible tooling broadly, rather than Gemini’s
previous_interaction_idchaining; if your app already manages its own message history, it carries over as-is. - A response shape you may already know.
response.choices[0].message.contentmatches the OpenAI Chat Completions shape exactly, since Sarvam’s endpoint is OpenAI-compatible; there’s no separate native shape to learn if you’re coming from the OpenAI-compatible Gemini path. - Hybrid thinking mode built into the model.
sarvam-30bandsarvam-105bsupport both “think” and “non-think” modes viareasoning_effort, tuned for complex reasoning and coding without needing a separate reasoning-specific model. - Advanced Indic skills are Sarvam’s specific strength. Both models are post-trained on Indian languages and cultural context, with native script and romanized-language support, alongside strong English performance.
Full example
A small wrapper function, before and after, showing the complete set of changes together:
Before (Gemini)
After (Sarvam)
Common mistakes
Sending a system_instruction field instead of a system message
Sarvam (and the OpenAI-compatible shape generally) expects the system prompt as a {"role": "system", ...} entry at the start of messages, not a separate top-level field. Fold it into the message list rather than looking for a system_instruction parameter.
Reading interaction.output_text out of habit
Sarvam’s response doesn’t have an output_text shortcut. Read the reply from response.choices[0].message.content, matching the OpenAI Chat Completions shape.
Looking for a previous_interaction_id equivalent
There isn’t one, and that’s fine: resend the conversation so far as the messages list on every call, the same way OpenAI-compatible tooling generally works. There’s no separate interaction resource to reference or manage the lifecycle of.
Mixing native and OpenAI-compatible auth styles
If you’re using the openai package against Sarvam’s endpoint, pass the key as api_key on the OpenAI(...) client as usual; don’t also try to set the api-subscription-key header manually; the two aren’t meant to be combined on the same request.
Forgetting max_tokens covers reasoning output too
When reasoning_effort is used, reasoning tokens count against the same max_tokens budget as the visible reply. A limit copied over from a non-reasoning Gemini setup may cut off responses; raise it if you turn reasoning on.
See also
- Migration overview: base URL, auth, and SDK client changes
- Migrating Text-to-Speech
- Migrating Speech-to-Text
- Chat Completion Overview
- Authentication
- Errors & Troubleshooting