# How WorkWeave Router Handles Translation Between Different API Formats

> Discover how WorkWeave Router translates API formats using its internal translate package. Get unified OpenAI-style responses from any LLM service.

- Repository: [Weave/router](https://github.com/workweave/router)
- Tags: how-to-guide
- Published: 2026-08-30

---

**WorkWeave Router uses a dedicated `internal/translate` package to convert OpenAI-compatible chat requests into provider-specific formats and back, ensuring clients always receive a unified OpenAI-style response regardless of the upstream LLM service.**

The WorkWeave Router acts as an intelligent gateway that normalizes heterogeneous LLM provider APIs behind a single OpenAI-compatible interface. Understanding its **translation between different API formats** requires examining the `internal/translate` package, which encapsulates all provider-specific conversion logic without performing any I/O operations.

## The Translation Architecture

The router positions itself between clients speaking the OpenAI `/v1/chat/completions` protocol and diverse upstream providers including Anthropic, Google Gemini, and OpenAI-compatible services. The `internal/translate` package serves as the **inner-ring translation layer**, converting inbound requests to native provider formats and transforming responses back to the canonical OpenAI schema.

This architecture ensures that **streaming deltas**, **tool calls**, **usage headers**, and **finish reasons** appear consistent to clients even when upstream services use incompatible data structures or Server-Sent Events (SSE) formats.

## Core Translation Pipeline

The translation process follows a strict pipeline that sanitizes, validates, and converts data before it reaches the proxy layer.

### Request Normalization with Strictify

Before any provider-specific logic executes, the **[`strictify_openai.go`](https://github.com/workweave/router/blob/main/strictify_openai.go)** module enforces the OpenAI schema on incoming payloads. This sanitization step validates required fields, restricts enum values, and prevents malformed JSON from propagating downstream to provider adapters.

```go
// internal/translate/strictify_openai.go
// Enforces strict OpenAI schema compliance on inbound requests
func StrictifyRequest(req *OpenAIChatRequest) error {
    // Validation logic ensures schema compliance
}

```

### Tool Call Validation

The **[`toolcheck/toolcheck.go`](https://github.com/workweave/router/blob/main/toolcheck/toolcheck.go)** subsystem validates function signatures and JSON argument schemas before translation. This provider-agnostic validation layer ensures that tool specifications will execute correctly on the target platform, rewriting them into normalized representations that individual provider adapters can consume safely.

```go
// internal/translate/toolcheck/toolcheck.go
func ValidateTools(tools []openai.Tool) error {
    // Ensure each tool's JSON schema is well-formed,
    // rewrite into a provider-agnostic representation.
}

```

### Provider-Specific Adapters

The central dispatcher in **[`translate.go`](https://github.com/workweave/router/blob/main/translate.go)** routes normalized requests to provider-specific implementations. Each adapter implements the **`Translator`** interface and handles the final shape adjustments required by the target service.

```go
// internal/translate/translate.go – core entry point
func TranslateRequest(req openai.ChatRequest, p providers.Provider) (
    any,               // provider-specific request payload
    Translator,        // object that knows how to decode responses
    error,
) {
    switch p {
    case providers.ProviderAnthropic:
        return translateAnthropic(req)
    case providers.ProviderGoogle:
        return translateGemini(req)
    // …other providers…
    default:
        return nil, nil, fmt.Errorf("unsupported provider %s", p)
    }
}

```

Specialized files like **[`anthropic_marker.go`](https://github.com/workweave/router/blob/main/anthropic_marker.go)** and **[`anthropic_footer.go`](https://github.com/workweave/router/blob/main/anthropic_footer.go)** handle provider-specific quirks such as Anthropic's SSE marker lines or Gemini response footers, ensuring these implementation details never leak into the client-facing API.

### Response Stream Conversion

For streaming completions, **[`stream.go`](https://github.com/workweave/router/blob/main/stream.go)** rewrites provider-specific delta formats into OpenAI-compatible "choices" arrays. The implementation preserves ordering, index values, and finish reasons while abstracting away differences in how Anthropic, Google, or other services chunk their SSE data.

```go
// internal/translate/stream.go – converts provider stream chunks
func (t *anthropicTranslator) StreamChunk(chunk []byte) (openai.StreamDelta, error) {
    // Decode Anthropic-style chunk, map fields to OpenAI delta format
    // – e.g., content → delta.content, role → delta.role, etc.
}

```

### Billing and Metadata Translation

The **[`billing_header.go`](https://github.com/workweave/router/blob/main/billing_header.go)** and **[`available_tools.go`](https://github.com/workweave/router/blob/main/available_tools.go)** modules translate provider-specific usage metrics and cost information into the OpenAI-style `usage` block. This ensures that client applications can monitor token consumption and tool availability through a consistent interface regardless of the upstream provider's native headers.

## Implementing the Translation Layer

Integration occurs at the HTTP handler level, where the router unmarshals client JSON and invokes the translation pipeline before proxying requests.

### Handler Integration

In [`internal/api/openai/handler.go`](https://github.com/workweave/router/blob/main/internal/api/openai/handler.go), the router binds incoming JSON to an `OpenAIChatRequest` struct, selects the appropriate provider based on routing logic, and delegates conversion to the translate package:

```go
// internal/api/openai/handler.go (simplified)
func handleChatCompletion(c *gin.Context) {
    var openaiReq openai.ChatRequest
    if err := c.BindJSON(&openaiReq); err != nil {
        // …handle error…
    }

    // Choose provider (e.g. Anthropic) based on routing logic
    provider := providers.ProviderAnthropic

    // Translate request → provider-specific payload
    transReq, translator, err := translate.TranslateRequest(openaiReq, provider)
    if err != nil {
        // …handle translation error…
    }

    // Dispatch via proxy.Service (I/O layer)
    respStream, err := proxySvc.Send(provider, transReq, translator)
    // …
}

```

The proxy service receives both the translated request payload and the `Translator` implementation, using the latter to convert responses back to OpenAI format before writing them to the client connection.

## Extensibility and Design Principles

The translation layer follows three core design principles that facilitate maintenance and provider expansion:

- **I/O-Free Architecture**: The `internal/translate` package contains pure Go code with no network operations, enabling comprehensive unit testing without mocking HTTP clients.
- **Interface-Based Adapters**: New providers require only a small adapter implementing the `Translator` interface; the core pipeline in [`translate.go`](https://github.com/workweave/router/blob/main/translate.go) remains unchanged.
- **Schema Consistency**: All outbound responses conform to the OpenAI specification, allowing the router to evolve upstream support without breaking the public API contract.

## Summary

- The `internal/translate` package provides bidirectional conversion between OpenAI-compatible formats and diverse LLM provider APIs.
- **Strictify** modules enforce schema compliance before provider-specific translation occurs.
- The **Translator** interface abstracts provider differences, implemented via dedicated adapters for Anthropic, Gemini, and other services.
- **Stream conversion** in [`stream.go`](https://github.com/workweave/router/blob/main/stream.go) normalizes real-time responses into OpenAI delta format while preserving metadata integrity.
- **Tool validation** occurs before translation to ensure function-calling compatibility across heterogeneous backends.
- Billing and usage data normalize into OpenAI-style headers through [`billing_header.go`](https://github.com/workweave/router/blob/main/billing_header.go).

## Frequently Asked Questions

### How does WorkWeave Router standardize responses from multiple LLM providers?

The router instantiates a provider-specific `Translator` implementation returned by `TranslateRequest()` in [`internal/translate/translate.go`](https://github.com/workweave/router/blob/main/internal/translate/translate.go). This translator converts native response formats—including streaming chunks—into the OpenAI `ChatCompletion` schema before the HTTP handler writes data to the client, ensuring consistent field names, structures, and semantic meaning across all supported backends.

### What is the role of the Translator interface in the WorkWeave Router architecture?

The `Translator` interface defines methods for converting provider-native responses and streaming chunks into OpenAI-compatible structures. Located in the `internal/translate` package, this interface allows the proxy service to remain provider-agnostic; it simply calls translator methods on response data without knowing whether the upstream service was Anthropic, Google, or another OpenAI-compatible endpoint.

### How does WorkWeave Router handle streaming responses from different API formats?

The [`stream.go`](https://github.com/workweave/router/blob/main/stream.go) implementation, accessed through the `Translator` interface, rewrites provider-specific Server-Sent Events into OpenAI-style "delta" objects. For example, the `anthropicTranslator.StreamChunk()` method maps Anthropic's content fields to OpenAI's `delta.content` and `delta.role` fields, preserving ordering and finish reasons while hiding protocol differences from the client.

### Why does the router validate tool calls before translation?

Validation in [`internal/translate/toolcheck/toolcheck.go`](https://github.com/workweave/router/blob/main/internal/translate/toolcheck/toolcheck.go) occurs before provider-specific conversion to catch malformed JSON schemas or invalid function signatures early in the pipeline. This prevents errors from reaching upstream providers, reduces latency for invalid requests, and allows the router to normalize tool definitions into a provider-agnostic representation that any adapter can consume safely.