How OmniRoute Translates Requests Between OpenAI, Claude, and Gemini Formats
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, 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 and populated during module initialization by bootstrap.ts. As implemented in lines 44-46 of 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. 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. 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 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 (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 and 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.
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. 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:
// 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:
// 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/translatorpackage, withtranslateRequestandtranslateResponseserving as the central choke points for all format conversions. - Hub-and-spoke architecture uses a registry pattern (
registry.ts,bootstrap.ts) to dynamically select converters based on source and target format identifiers likeFORMATS.OPENAIorFORMATS.GEMINI. - Bidirectional conversion is supported through dedicated request translators (
openai-to-gemini.ts,openai-to-claude.ts) and response translators (gemini-to-openai.ts,claude-to-openai.ts). - Tool call preservation is handled by specialized helpers (
toolCallHelper.ts,schemaCoercion.ts) that maintain ID consistency and schema validity across provider boundaries. - Streaming translation occurs in real-time via
utils/stream.ts, which processes each chunk throughtranslateResponseto 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 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 and initialized by 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 and toolCallShim.ts utilities ensure that tool call IDs remain consistent throughout the request-response cycle, while 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 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. 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →