Skip to content

LLM Translation

For a small integration example, read Use the translation crate. For field mappings, use LLM Requests and Responses and Streams.

TranslationEngine converts between provider JSON and Switchyard protocol types. It makes no network calls. WireFormat identifies the built-in Chat Completions, Responses, and Anthropic Messages formats. FormatId can also identify custom formats registered through the codec interfaces.

Engine operations

All operations below are methods of TranslationEngine. The request and buffered-response methods take a TranslationPolicy.

Method Input and result Use it for
decode_request Provider JSON to LlmRequest, plus diagnostics. Accepting a request from a provider-facing gateway or harness.
encode_request LlmRequest to provider JSON, plus diagnostics. Sending a call through an existing client.
translate_request Source provider JSON to target provider JSON. Direct request conversion without handling the protocol value yourself.
decode_response Provider JSON to AggLlmResponse, plus diagnostics. Returning a buffered response to libsy.
encode_response AggLlmResponse to provider JSON, plus diagnostics. Returning a buffered answer in the caller's format.
translate_response Source provider JSON to target provider JSON. Direct buffered-response conversion.
decode_stream_event One parsed provider event to LlmResponseStreamEvent. Retaining the source event alongside neutral chunks.
encode_stream_event One LlmResponseStreamEvent to zero or more provider events. Replaying or converting incremental output.
finish_stream Stream state to any remaining target events. Closing the target format after the source stream ends.

Buffered encoders return TranslationOutput with the encoded body and TranslationDiagnostic values. Inspect diagnostics from decoding and encoding; the direct translation helpers combine them and annotate source/target formats.

Policies

These defaults come from TranslationPolicy::default().

Field and type Default Meaning
TranslationPolicy.unknown_field_policy: UnknownFieldPolicy UnknownFieldPolicy::Preserve Keep unknown provider fields where the codec can retain them. Alternatives warn and drop, or reject.
TranslationPolicy.lossy_conversion_policy: LossyConversionPolicy LossyConversionPolicy::AllowWithDiagnostics Allow known losses and record warnings. Use LossyConversionPolicy::Reject to fail on known lossy conversions.
TranslationPolicy.deterministic_ids: DeterministicIdPolicy DeterministicIdPolicy::GenerateStable, prefix sw Generate stable IDs when needed. The alternative preserves IDs without generation.
TranslationPolicy.preservation: PreservationPolicy PreservationPolicy::InMemory Retain original parsed bodies in protocol values for replay.
TranslationPolicy.target_capabilities: TargetCapabilities All capability fields unspecified Optionally constrain supported tools, media, reasoning, schema output, and other target features.

Unspecified capabilities are not proof that a model supports a feature. A provider can still reject the encoded request. Known-loss rejection covers the codec's implemented checks, rather than proving semantic equivalence for every possible provider extension.

Preservation and edits

An original body takes precedence over reconstructed fields for its own format. The codec looks up a request in PreservationMetadata.requests, or a buffered response in PreservationMetadata.responses.

Policy Behavior Boundary
PreservationPolicy::InMemory Keep original JSON in protocol values. Same-format replay works while that preservation data remains available.
PreservationPolicy::Embed Also embed preservation metadata in translated JSON. Supports multi-hop round trips when intermediaries retain it; provider metadata limits can prevent use.
PreservationPolicy::Disabled Do not use preservation for replay. Encoders reconstruct the body from current protocol fields.

If you edit a decoded request, remove that format's entry from PreservationMetadata.requests or encode with PreservationPolicy::Disabled. This applies to model changes, messages, generation settings, and schema enforcement. Apply the same rule to buffered response edits.

Replay preserves parsed JSON values, not original HTTP bytes, whitespace, or headers. Input cleanup can happen before capture, including removal of Codex internal compaction markers. Request.raw_request is host-owned and is not the codec's replay source. Preserved data can contain the full conversation and other sensitive provider fields.

Stream translation

Use a separate StreamTranslationState for each response stream. Feed parsed provider events to decode_stream_event, pass the resulting event to encode_stream_event, and call finish_stream when the source closes. The encoder may emit several target events for one input event.

When the source and target formats match, a preserved event replays its retained JSON. Cross-format encoding uses normalized chunks. After changing a stream event, use replace_normalized() to clear raw data that no longer describes it. The response reference explains what aggregation retains and drops.

Conversion limits

Retention and destination support are separate. Anthropic has no distinct developer authority, the OpenAI formats have no standard tool-result error flag, and provider built-in tools or encrypted reasoning may lack equivalents.

Use ProviderExtensions and preservation to retain source data, then inspect diagnostics and the destination model's capabilities. For a custom format, FormatCodec and StreamCodec define the codec contracts; TranslationEngine::with_registries accepts explicit registries.