Skip to main content

Crate switchyard_translation

Crate switchyard_translation 

Source
Expand description

§switchyard-translation

Pure Rust translation between OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages request, response, and streaming formats.

The crate translates through provider-neutral LLM types from switchyard-protocol and does not depend on provider SDKs, HTTP servers, Python, or FFI bindings.

§Translate a request

use serde_json::json;
use switchyard_translation::{TranslationEngine, TranslationPolicy, WireFormat};

fn translate_request() -> Result<(), Box<dyn std::error::Error>> {
    let request = json!({
        "model": "switchyard",
        "input": "What's the weather in Paris?",
        "tools": [{
            "type": "function",
            "name": "get_weather",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": { "type": "string" }
                }
            }
        }]
    });

    let engine = TranslationEngine::default();
    let policy = TranslationPolicy::default();

    for destination in [WireFormat::OpenAiChat, WireFormat::AnthropicMessages] {
        let result = engine.translate_request(
            WireFormat::OpenAiResponses,
            destination,
            &request,
            &policy,
        )?;
        println!(
            "Responses -> {}\n{}\nDiagnostics: {}\n",
            destination.as_str(),
            serde_json::to_string_pretty(&result.body)?,
            serde_json::to_string_pretty(&result.diagnostics)?
        );
    }

    Ok(())
}

§Translate a response

use serde_json::json;
use switchyard_translation::{TranslationEngine, TranslationPolicy, WireFormat};

fn translate_response() -> Result<(), Box<dyn std::error::Error>> {
    let response = json!({
        "output": [{
            "type": "function_call",
            "call_id": "call_weather",
            "name": "get_weather",
            "arguments": "{\"city\":\"Paris\"}"
        }]
    });

    let engine = TranslationEngine::default();
    let policy = TranslationPolicy::default();

    for destination in [WireFormat::OpenAiChat, WireFormat::AnthropicMessages] {
        let result = engine.translate_response(
            WireFormat::OpenAiResponses,
            destination,
            &response,
            &policy,
        )?;
        println!(
            "Responses -> {}\n{}\nDiagnostics: {}\n",
            destination.as_str(),
            serde_json::to_string_pretty(&result.body)?,
            serde_json::to_string_pretty(&result.diagnostics)?
        );
    }

    Ok(())
}

§Translation policy

The examples above use TranslationPolicy::default(). A translation policy decides what happens when an item cannot be translated exactly: keep it, warn about it, or return an error.

The default policy:

  • Allows known information loss with warnings.
  • Generates stable IDs when the source has none.
  • Keeps the source payload in memory.
  • Leaves target capabilities unspecified.

The lossy_conversion_policy field controls whether known conversions that lose information are allowed. LossyConversionPolicy has two variants:

  • AllowWithDiagnostics (default): continue translation and record a lossy_conversion warning in the result’s diagnostics field.
  • Reject: return TranslationError::LossyConversion when a known lossy conversion is encountered.

Calling translate_request/translate_response annotates every diagnostic with source and target formats.

To reject known lossy conversions:

use switchyard_translation::{LossyConversionPolicy, TranslationPolicy};

let policy = TranslationPolicy {
    lossy_conversion_policy: LossyConversionPolicy::Reject,
    ..TranslationPolicy::default()
};

§License

Licensed under the Apache License, Version 2.0. See the Switchyard repository for details.

Re-exports§

pub use codecs::responses::is_anthropic_thinking_envelope;
pub use util::PRESERVATION_METADATA_KEY;
pub use util::normalize_anthropic_tool_use_ids;
pub use util::prepare_request_for_target;
pub use util::sanitize_anthropic_tool_use_id;
pub use diagnostic::*;
pub use engine::*;
pub use error::*;
pub use policy::*;
pub use stream::*;

Modules§

codecs
Buffered wire-format codecs that translate between provider JSON and IR.
diagnostic
Diagnostics emitted when translation preserves, drops, or degrades data.
engine
Registry-backed translation engine for buffered requests and responses.
error
Error types for request, response, and streaming translation.
format
Wire-format identifiers carried by the shared protocol types.
llm
Provider-neutral conversation types shared by routing, clients, and translation.
policy
Policy knobs that control translation strictness and target capabilities.
stream
Public compatibility module for streaming translation APIs.
util
Shared helpers for codec validation, diagnostics, and preservation metadata.

Structs§

AggLlmResponse
Normalized, fully-buffered response — the aggregate of a completed generation. This is the terminal form of a streamed LlmResponse.
FormatId
Extensible wire-format identifier used by codec registries.
InputCacheUsage
Optional cache-token detail kept out of the common, cache-free usage allocation.
InstructionBlock
Instruction content separated from normal conversation messages.
LlmRequest
Normalized request representation shared by Switchyard components.
LlmResponseStreamEvent
One streaming item crossing the host/algorithm boundary.
McpListedTool
A tool discovered on an MCP server.
McpToolConfig
Settings for an individual MCP tool or the defaults for a toolset.
McpToolset
Configuration for a URL-based remote MCP toolset.
Message
One normalized conversation message.
OutputParams
Output budget and structured-output options.
PreservationMetadata
Exact source payloads retained for lossless same-format round trips.
ProviderExtensions
Provider-specific fields that do not have first-class conversation fields.
ProviderStreamEvent
Parsed provider event retained for same-format replay.
ReasoningParams
Provider reasoning controls preserved by translation.
ResponseOutput
One assistant output item in a normalized response.
SamplingParams
Provider sampling parameters with common cross-provider names.
ToolCall
Normalized assistant tool call.
ToolDefinition
Normalized tool definition.
ToolResult
Normalized tool result message content.
UrlCitation
A source URL cited by generated text.
Usage
Normalized token usage counts.

Enums§

ContentBlock
Normalized content block variants carried by messages and tool results.
FileSource
File payload forms supported by the conversation model.
ImageSource
Image payload forms supported by the conversation model.
LlmResponseChunk
One provider-neutral streaming response chunk.
LlmStreamError
Why a translated event stream stopped early.
McpContent
MCP discovery and execution history. Results reference the matching call’s server identity.
MediaSource
Audio and video payload forms supported by the conversation model.
Role
Actor role normalized across provider APIs.
StopReason
Normalized reason a model stopped producing output.
Tool
A tool available to the model, in catalog order.
ToolChoice
Normalized tool choice policy.
WireFormat
Built-in provider API formats.

Functions§

decode_aggregated_response
Decodes a buffered wire_format response body into the neutral aggregate.
decode_request
Decodes a wire_format request body into the neutral IR.
decode_stream
Decodes provider SSE bytes into normalized stream events.
encode_aggregated_response
Encodes a buffered aggregate into wire_format’s JSON body, stamping served_model over the encoded id so the caller sees which model answered. Passing None leaves the id the upstream reported.
encode_aggregated_response_with_extensions
Encodes an aggregated response, honouring request extensions.
encode_request
Encodes a normalized request into wire_format’s JSON body.
encode_stream
Encodes a stream of IR chunks into a stream of target-format wire events.
encode_stream_with_extensions
Encodes a response stream, honouring request extensions.

Type Aliases§

LlmResponseStream
A boxed, Send stream of response events. Each item may fail independently mid-stream.
RawEventStream
A stream of wire-format event objects in one format — the unframed body of an SSE response. The serving layer frames each Value (e.g. as an SSE data:/event: block).