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

> OmniRoute seamlessly translates API formats between OpenAI, Claude, and Gemini. Discover how it normalizes requests and responses for unified LLM provider integration.

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

---

**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.

```typescript
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/openai-chat.ts), [`claude.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/claude.ts), or [`gemini.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/tests/unit/xai-translators.test.ts) that verify round-trip correctness for all supported providers.