Skip to main content

Google exposes Gemini through three different surfaces. Rolter has a provider kind for each:

KindUpstream surfaceWhen to use it
geminiThe hosted OpenAI-compatible shimSimplest option; no translation at all
gemini_native:generateContent / :streamGenerateContentNative features the shim does not expose
gemini_interactionsPOST {api_base}/interactionsStateful, agentic threads with server-side history

This page covers gemini_interactions.


Configuration#

api_base points at the API version root — no /openai suffix and no /interactions suffix, Rolter appends that itself. The key is read from the environment (inline keys are rejected) and sent as x-goog-api-key, exactly as for gemini_native.


What Rolter translates#

Clients keep speaking their usual dialect. POST /v1/chat/completions, POST /v1/responses and POST /v1/messages are all mapped onto the single interactions endpoint.

Request

Client fieldInteractions field
messages / input turnsinput items with role user / model and typed content parts
system / developer messages, instructionssystem_instruction
assistant tool_callsfunction_call input items (call_id, name, arguments)
tool messages / function_call_outputfunction_result input items
temperature, top_p, max_tokens, stop, tool_choicegeneration_config
toolsflat tools entries (type: "function", name, description, parameters)
streamstream

Response

The interaction’s steps[] are folded back into the client’s shape: model_output steps become assistant text, function_call steps become tool calls, and thought steps are dropped — reasoning traces are never surfaced as output. usage maps to the client’s token counters.

Streaming works the same way: interaction.created, step.start, step.delta and interaction.completed events are converted into OpenAI chunks, Anthropic message events, or Responses events depending on the endpoint the client called.


Threading a conversation#

The Interactions API keeps conversation history server-side. Rolter does not store interaction ids — the thread is client-driven, which keeps the gateway stateless and lets any replica serve the next turn.

The interaction id comes back as the response id. Send it on the next request as:

  • previous_response_id — OpenAI Responses clients, where this field already exists
  • previous_interaction_id — any dialect, passed through verbatim

store is forwarded when set, so a client that opts out of retention keeps that control.

Note

Because the thread lives upstream, a route that load-balances a gemini_interactions provider against providers of other kinds will lose the thread on failover. Keep interaction-threaded traffic on a route whose members are all gemini_interactions.


Unsupported endpoints#

The Interactions API only serves chat-shaped traffic. Requests to endpoints with no interactions equivalent — embeddings, audio — are rejected with a 400 gemini_interactions_unsupported error rather than being forwarded to an endpoint that cannot answer them. Route those models to a gemini or gemini_native provider instead.


Unsupported content parts#

Interactions carries a typed union of content parts. Rolter translates text / input_text and image_url / input_image; there is no opaque carrier for anything else.

A message containing a part rolter cannot translate — input_audio, a file or document part, or any new part type your client SDK starts sending — is rejected with 400 unsupported_content_part naming the part:

Note

This is deliberate. Dropping the part would send Gemini a request missing content you supplied, and both Gemini and rolter would answer 200 — you would get a confident answer that ignored your attachment, with nothing in the logs to say so. The same rule applies to the gemini_native (generateContent) dialect.

To send a modality Interactions cannot carry, route that model to a provider whose dialect supports it.