# How OmniRoute Translates Requests Between OpenAI, Claude, and Gemini Formats

> Discover how OmniRoute effortlessly translates requests between OpenAI Claude and Gemini formats using its hub-and-spoke architecture and specialized converters for seamless LLM integration.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-26

---

**OmniRoute employs a hub-and-spoke translation architecture centered in the `open-sse/translator` package, where the `translateRequest` and `translateResponse` functions serve as single choke points to convert payloads between any supported LLM provider format using a registry of specialized converters.**

OmniRoute functions as a universal routing layer for large language models, enabling seamless interoperability between incompatible API specifications. The framework's ability to translate requests between different provider formats like OpenAI, Claude, and Gemini lives entirely within the `open-sse/translator` package, ensuring that a client sending requests in OpenAI format can communicate with Google's Gemini or Anthropic's Claude without modifying the original payload structure.

## The Hub-and-Spoke Translation Architecture

All inbound chat and completion requests first pass through `translateRequest`, which acts as the single outbound choke point for every request passing through the system. According to the implementation at line 306 of [`open-sse/translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/index.ts), this function discovers the source and target formats—such as `FORMATS.OPENAI`, `FORMATS.CLAUDE`, and `FORMATS.GEMINI`—and selects the appropriate converter from the registry via `getRequestTranslator`.

The response translation works analogously on the return path. The `translateResponse` function processes the raw upstream response and rewrites it back into the client-expected format before transmission.

### Registry and Bootstrap Pattern

The translation registry is defined in [`registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/registry.ts) and populated during module initialization by [`bootstrap.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/bootstrap.ts). As implemented in lines 44-46 of [`open-sse/translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/index.ts), this registry maps each source-target format pair to its specific converter functions, enabling dynamic lookup at runtime based on the route configuration.

## Converting OpenAI Requests to Gemini Format

The **OpenAI-to-Gemini** translation logic resides in [`open-sse/translator/request/openai-to-gemini.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/request/openai-to-gemini.ts). The core function `openaiToGeminiBase` constructs a `GeminiRequest` object by mapping OpenAI-specific fields—including `temperature`, `top_p`, `top_k`, `stop` sequences, and tool definitions—to Gemini's native `generationConfig` and `tools` structures.

According to the source code at lines 1-100, this converter also handles Antigravity-specific defaults and sanitizes built-in Gemini tool names to prevent naming collisions. The function ensures that parameters like `max_tokens` are correctly translated to Gemini's `maxOutputTokens` equivalent.

## Translating OpenAI to Claude Format

For **OpenAI-to-Claude** conversion, OmniRoute uses [`open-sse/translator/request/openai-to-claude.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/request/openai-to-claude.ts). The `prepareClaudeRequest` function, found at lines 8-20, restructures OpenAI's message array into Claude's expected format of "system", "user", and "assistant" roles.

This converter injects placeholder thinking configuration required by Claude's extended reasoning capabilities and normalizes tool call IDs to ensure they remain consistent throughout the request lifecycle. It also handles the hoisting of system messages into Claude's dedicated `system` parameter rather than including them in the main messages array.

## Normalizing Responses to OpenAI Format

When returning data to clients expecting OpenAI-compatible responses, OmniRoute reverses the translation process through provider-specific response converters.

### Gemini to OpenAI Conversion

The [`response/gemini-to-openai.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/response/gemini-to-openai.ts) file, specifically lines 730-740, translates Gemini's `content` array—which may contain text, image, or tool parts—into OpenAI-style message objects. This converter maps Gemini function calls to OpenAI `tool_calls` and respects Gemini's `functionCallingConfig` while injecting necessary safety settings into the response metadata.

### Claude to OpenAI Conversion

Similarly, [`response/claude-to-openai.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/response/claude-to-openai.ts) (lines 10-20) processes Claude's `assistant` messages, including `tool_result` blocks, converting them into OpenAI's `assistant` role format. This translation preserves tool call IDs and handles Claude-specific "thinking" placeholders by either stripping them or converting them to content blocks depending on the client configuration.

## Maintaining Tool Call Integrity Across Providers

Tool call consistency is managed by helper modules in `open-sse/translator/helpers/`. The [`toolCallHelper.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/toolCallHelper.ts) and [`toolCallShim.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/toolCallShim.ts) files, referenced at lines 3-5, ensure that tool call IDs survive the round-trip between formats and that function-call schemas are coerced to match the target provider's expectations via [`schemaCoercion.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/schemaCoercion.ts).

These utilities are critical when a client sends tool definitions in OpenAI format that must be reformatted for Gemini's function calling interface or Claude's tool use specification, ensuring that the schema types and required fields remain valid across different JSON schema implementations.

## Real-Time Streaming Translation

OmniRoute extends its translation capabilities to streaming responses through the pipeline defined in [`open-sse/utils/stream.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/stream.ts). According to lines 618-633, the stream processor invokes `translateResponse` for each chunk received from the upstream provider, assembling a client-facing SSE stream in the target format when operating in `TRANSLATE` mode.

This enables real-time translation of provider-specific streaming deltas into OpenAI-compatible stream chunks, allowing clients to consume streaming responses from Gemini or Claude using standard OpenAI SDKs without modification.

## Implementation Examples

The following example demonstrates translating an OpenAI-format request to Gemini's native structure:

```typescript
// Example: Translate an OpenAI request to Gemini
import { translateRequest } from "@/open-sse/translator";
import { FORMATS } from "@/open-sse/translator/formats";

const openaiPayload = {
  model: "gpt-4o",
  messages: [{ role: "user", content: "Explain quantum tunneling." }],
  temperature: 0.7,
  tools: [{ type: "function", function: { name: "search", parameters: {} } }],
};

const geminiPayload = translateRequest(
  FORMATS.OPENAI,          // source format
  FORMATS.GEMINI,         // target format
  openaiPayload,
  false,                  // not a streaming request
  {}                      // optional translation credentials
);
// `geminiPayload` is ready for a Gemini endpoint.

```

To translate a streamed response back to OpenAI format:

```typescript
// Example: Translate a Gemini streamed response back to OpenAI format
import { translateResponse } from "@/open-sse/translator";
import { FORMATS } from "@/open-sse/translator/formats";

const geminiChunk = {
  candidates: [{ content: [{ text: "Quantum tunneling allows particles..." }] }],
};

const openaiChunks = translateResponse(
  FORMATS.OPENAI,      // client expects OpenAI format
  FORMATS.GEMINI,     // source chunk is Gemini format
  geminiChunk,
  streamState          // state tracking accumulated content
);
// `openaiChunks` can be emitted as SSE to the original client.

```

## Summary

- **OmniRoute's translation layer** lives in the `open-sse/translator` package, with `translateRequest` and `translateResponse` serving as the central choke points for all format conversions.
- **Hub-and-spoke architecture** uses a registry pattern ([`registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/registry.ts), [`bootstrap.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/bootstrap.ts)) to dynamically select converters based on source and target format identifiers like `FORMATS.OPENAI` or `FORMATS.GEMINI`.
- **Bidirectional conversion** is supported through dedicated request translators ([`openai-to-gemini.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/openai-to-gemini.ts), [`openai-to-claude.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/openai-to-claude.ts)) and response translators ([`gemini-to-openai.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/gemini-to-openai.ts), [`claude-to-openai.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/claude-to-openai.ts)).
- **Tool call preservation** is handled by specialized helpers ([`toolCallHelper.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/toolCallHelper.ts), [`schemaCoercion.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/schemaCoercion.ts)) that maintain ID consistency and schema validity across provider boundaries.
- **Streaming translation** occurs in real-time via [`utils/stream.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/utils/stream.ts), which processes each chunk through `translateResponse` to maintain format compatibility throughout the SSE stream.

## Frequently Asked Questions

### How does OmniRoute handle format conversions between providers?

OmniRoute handles format conversions through a centralized translation layer that inspects the source and target format identifiers (such as `FORMATS.OPENAI` to `FORMATS.GEMINI`) and delegates to specialized converter functions. The `translateRequest` and `translateResponse` functions in [`open-sse/translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/index.ts) act as the single entry and exit points, ensuring consistent transformation of payloads regardless of the specific provider pair involved.

### What is the role of the translator registry in OmniRoute?

The translator registry, defined in [`open-sse/translator/registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/registry.ts) and initialized by [`bootstrap.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/bootstrap.ts), maintains a mapping of all supported source-to-target format combinations to their respective converter implementations. When a request arrives, `translateRequest` queries this registry via `getRequestTranslator` to retrieve the appropriate conversion logic, enabling OmniRoute to support new providers by simply registering additional translator functions without modifying the core routing code.

### How are tool calls preserved when translating between OpenAI and Gemini formats?

Tool calls are preserved through dedicated helper modules located in `open-sse/translator/helpers/`. The [`toolCallHelper.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/toolCallHelper.ts) and [`toolCallShim.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/toolCallShim.ts) utilities ensure that tool call IDs remain consistent throughout the request-response cycle, while [`schemaCoercion.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/schemaCoercion.ts) reformats function definitions to match the target provider's JSON schema requirements. For Gemini specifically, the `openaiToGeminiBase` function in [`request/openai-to-gemini.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/request/openai-to-gemini.ts) sanitizes built-in tool names and maps OpenAI's tool definitions to Gemini's `tools` structure.

### Does OmniRoute support real-time streaming translation?

Yes, OmniRoute supports real-time streaming translation through the stream processing pipeline in [`open-sse/utils/stream.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/stream.ts). According to lines 618-633 of the source code, the system invokes `translateResponse` for each chunk received from the upstream provider when operating in `TRANSLATE` mode. This allows the system to assemble a client-facing SSE stream in the target format on-the-fly, enabling OpenAI-compatible clients to consume streaming responses from Claude or Gemini without protocol modifications.