How OmniRoute Handles Format Translation Between OpenAI, Claude, and Gemini API Specifications

OmniRoute normalizes requests and responses between the three major LLM providers by converting all incoming payloads to a unified internal schema called xAI Responses, then translating the provider's xAI Completed response back to the original caller's expected format.

OmniRoute is an open-source routing layer that abstracts away structural differences between LLM APIs. By implementing bidirectional format translation between OpenAI, Claude, and Gemini API specifications, the project enables developers to use a single integration point while maintaining compatibility with each provider's native SDKs. The translation logic resides in dedicated modules under src/lib/providers/xai/translators, ensuring that system messages, tool definitions, and multimodal inputs map correctly regardless of the source API.

The xAI Responses Internal Model

All translators map external payloads to a common internal representation defined in the xAI Responses schema. This normalized structure decouples the routing logic from provider-specific JSON shapes.

interface XaiResponsesRequest {
  model?: string | null;
  input: XaiInputItem[];           // ordered list of user/assistant/tool items
  instructions?: string;           // system-prompt or Gemini systemInstruction
  tools?: XaiTool[];               // function-tool declarations
  tool_choice?: string;
  temperature?: number;
  top_p?: number;
  max_output_tokens?: number;
  stop?: string[];
  reasoning?: { effort: "low" | "medium" | "high" };
}

Conversely, an xAI Completed object contains an array of output items that the outbound translators convert back into provider-specific response formats. This bidirectional flow ensures that caching, resilience, and streaming layers operate on a single consistent data model.

OpenAI Translation Layer

The OpenAI translator bridges the Chat Completions API format and the internal xAI Responses schema. Source code is located at src/lib/providers/xai/translators/openai-chat.ts.

Inbound Conversion

The chatRequestToXaiResponses function parses OpenAI Chat requests and extracts:

  • System messages → mapped to the instructions field
  • User/assistant messages → converted to input content blocks (input_text, input_image, etc.)
  • Tool calls and results → normalized to function_call / function_call_output items
  • Tools definitions → passed through unchanged via toolsPassthrough

Outbound Conversion

The xaiCompletedToChatJson function builds an OpenAI-compatible ChatCompletion object from the xAI Completed response. It re-injects text content, tool calls, and optional refusal fields into the standard OpenAI response envelope.

Claude Translation Layer

The Anthropic translator handles the Messages API format, managing Claude-specific content blocks and tool schemas. Implementation is in src/lib/providers/xai/translators/claude.ts.

Inbound Conversion

The claudeRequestToXaiResponses function processes Anthropic payloads by:

  • Mapping the system field to instructions
  • Converting the messages array to input items with user/assistant content blocks
  • Transforming Anthropic image blocks into input_image items
  • Converting tool_use and tool_result blocks into separate function_call / function_call_output entries
  • Translating tool definitions via toolsAnthropicToXai to match the xAI function-tool shape

Outbound Conversion

The xaiCompletedToClaudeJson function reconstructs an Anthropic Messages JSON object. It populates the content array with output_text, refusal, and function_call blocks while preserving usage metadata required by Anthropic's SDK.

Gemini Translation Layer

The Google Gemini translator manages the generateContent API format, handling multimodal parts and function declarations. Code resides in src/lib/providers/xai/translators/gemini.ts.

Inbound Conversion

The geminiRequestToXaiResponses function processes Gemini requests by:

  • Mapping systemInstruction to the instructions field
  • Converting each content entry to input items, deriving roles from the role field
  • Using partsToXaiBlocks to transform Gemini parts (text, inlineData, fileData) into input_text or input_image blocks
  • Extracting embedded function calls and responses via extractFunctionItems
  • Converting functionDeclarations to xAI tools using toolsGeminiToXai

Outbound Conversion

The xaiCompletedToGeminiJson function generates a Gemini response by building a candidates array. It converts output_text to Gemini text parts and function_call entries to Gemini functionCall parts, while injecting usageMetadata for token accounting.

Request Lifecycle and Flow Overview

OmniRoute processes provider-specific requests through a standardized pipeline:

  1. API Route receives a request (e.g., /v1/chat/completions) and identifies the target provider
  2. Translator Selection activates the appropriate module (openai-chat.ts, claude.ts, or gemini.ts)
  3. Normalization converts the incoming payload to an xAI Responses request
  4. Execution sends the normalized request to the downstream service
  5. Completion receives an xAI Completed object from the provider
  6. Denormalization maps the completed object back to the original provider's response format
  7. Streaming returns the formatted response to the caller via SSE or JSON

Because each translator adheres to the same internal contract, surrounding layers for caching, rate limiting, and error handling remain provider-agnostic.

Summary

  • OmniRoute uses a unified xAI Responses schema to decouple routing logic from provider-specific formats
  • Dedicated translators in src/lib/providers/xai/translators handle bidirectional conversion for OpenAI, Claude, and Gemini
  • Inbound translators normalize system prompts, message histories, tools, and multimodal content to the internal model
  • Outbound translators reconstruct provider-native response envelopes including usage metadata and content blocks
  • The architecture allows the core executor to treat all requests uniformly while preserving compatibility with native SDKs

Frequently Asked Questions

How does OmniRoute handle tool function definitions across different API formats?

Each translator contains provider-specific logic for tool schema conversion. OpenAI tools pass through largely unchanged via toolsPassthrough, while Claude tools undergo transformation via toolsAnthropicToXai and Gemini tools convert via toolsGeminiToXai. The internal xAI representation uses a standardized function-tool shape that captures name, description, and parameters, ensuring that function calls and results map correctly regardless of the source API's JSON schema.

What happens to system messages and instructions during translation?

System-level instructions normalize to the instructions field in the xAI Responses model. For OpenAI, the translator extracts content from messages with role: "system". For Claude, it maps the top-level system field. For Gemini, it pulls from systemInstruction. During outbound translation, the system message returns to its provider-specific location, preserving the exact structure expected by each SDK.

Can OmniRoute handle image and multimodal inputs when translating between APIs?

Yes. The translators process multimodal content through specialized mapping functions. OpenAI image URLs and base64 data convert to input_image blocks. Claude's image blocks undergo similar transformation. Gemini's inlineData and fileData parts convert via partsToXaiBlocks. When generating responses, outbound translators reconstruct the appropriate provider-specific image formats, enabling seamless passthrough of visual content across all three APIs.

Why does OmniRoute use an intermediate xAI format instead of direct translation?

The xAI Responses schema acts as a least common denominator that simplifies the addition of new providers and features. By translating once to a unified model and once back to the target format, OmniRoute avoids combinatorial complexity (N×M translations) and ensures that caching, streaming, and error handling logic remains provider-agnostic. This architecture is validated by unit tests in tests/unit/xai-translators.test.ts that verify round-trip correctness for all supported providers.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →