The translation pipeline
Every request that hits AdaptiveAPI flows through the same five-stage pipeline. The job of each stage is to keep the wire format intact while moving human text in and out of the right language.
The five stages
- Tokenise. Wrap untranslatable spans (IDs, URLs, code, JSON inside JSON) in
<adaptiveapi id="TAG_n"/>placeholders. - Translate. Send the tokenised text to the configured translator.
- Verify. Confirm every placeholder reappears in the output exactly once. If not, fall back to source text and increment
adaptiveapi_placeholder_integrity_failures_total. - Detokenise. Replace placeholders with their original verbatim spans.
- Re-emit. Stitch back into the upstream wire format (chat-completion JSON, Anthropic message, MCP JSON-RPC, generic JSON, SSE event).
Streaming
The pipeline supports two streaming strategies. Pick per route, override
per request with X-AdaptiveApi-Stream-Mode.
Sentence-boundary (default)
Buffer per choices[i].delta.content, flush at sentence
boundaries once the buffer reaches 80 chars (configurable), translate the
completed segment, re-emit a synthetic SSE delta. Clients see token-by-token
UI with a modest per-sentence latency cost. Best balance of fidelity and
perceived responsiveness.
Progressive
Translate smaller fragments more often, accepting some retranslation churn. Lower first-token latency at the cost of slightly less stable phrasing mid-sentence. Useful for chat UIs where the first words on screen matter.
Post-completion
Buffer the entire response, translate once, emit a single delta. Cheaper
per-call when answers are short. Set stream_mode: "post" per
route or pass X-AdaptiveApi-Stream-Mode: post.
Tool calls
OpenAI's tool_calls[*].function.arguments is a JSON string
containing JSON. The pipeline parses the inner JSON, walks it with a
key-aware denylist, translates the leaves that are actually human text, and
re-serialises.
The default denylist:
- Exact keys:
id,uuid,email,slug,key,locale,tz,url,href,path. - Suffix patterns:
*_id,*_code,*Id,*Code.
Argument keys are preserved verbatim. tool_call_id and
function.name never change. Extend per tenant via proxy rules:
{
"toolArgKeys": ["internal_note", "customer_id"]
}
Glossaries
Glossaries are tenant-scoped and bind to a route or override per request
with X-AdaptiveApi-Glossary. They map 1:1 to DeepL v3
multilingual glossaries on the wire, so terms behave identically whether
you call DeepL directly or through AdaptiveAPI.
Two entry kinds:
- Do-not-translate. The term is preserved verbatim regardless of language pair.
- Source-to-target. The translator is instructed to render this exact term as the given target.
Style rules
DeepL v3 style rules with up to ten 300-character custom instructions per rule, passed to DeepL on every translate call. Useful for things like:
- "Always use formal address (Sie, vous)."
- "Translate marketing copy idiomatically rather than literally."
- "Keep code snippets and identifiers in English."
PII redaction
The redactor runs early in the pipeline, before translation and before the upstream call. Built-in regex detectors cover email, Luhn-validated cards, US SSN, IBAN, IPv4, and phone numbers. Microsoft Presidio plugs in as a sidecar for higher recall (names, locations, organisations). Custom regex rules let you teach the redactor about your own identifiers.
Full coverage in PII detection.
Placeholder integrity
Each translation round trip has a hard invariant: every
<adaptiveapi id="TAG_n"/> tag emitted into the source must
reappear exactly once in the translator output. If it does not, the
pipeline falls back to the source text, increments the
adaptiveapi_placeholder_integrity_failures_total counter, and
logs the failure. Alert above 0.5% over your observation window.