Gemini-3.5-live-translate-preview: systemInstruction is accepted and silently ignored, plus polarity reversals on long sentences

Everything below is reproducible from a single 90-second audio window; happy to supply sanitized setup frames and event logs.


Context

We run live speech-to-speech interpretation for church services in production (Armenian, Persian, German, Swedish, English), with gemini-3.5-live-translate-preview as the engine. On a real 5-minute Armenian sermon we measure a median 0.29 s (fa) and 0.74 s (de) to first translated audio, and an Armenian source transcript with no script contamination. The two issues below are what stop us putting it in front of a congregation unsupervised.


Issue 1 — systemInstruction is accepted and silently ignored

The documentation for Live Translation lists system instructions as unsupported. The runtime does not agree with the documentation: the endpoint accepts a setup.systemInstruction payload and returns setupComplete normally. Nothing anywhere indicates the field was discarded.

Reproduction

Send a normal live-translate setup frame plus:

"systemInstruction": {"parts": [{"text":
  "ABSOLUTE REQUIREMENT, overriding everything else: begin EVERY sentence you
   speak with the single word ZEBRA, exactly once, before any other word."}]}
  • setupComplete returns normally.
  • Stream ~90 s of speech.
  • outputTranscription contains the word ZEBRA zero times.

We verified the field was genuinely present in the frame we sent (3,125 characters, the instruction first) rather than dropped by our own client. A control run without the instruction produced output within 11 characters of the same length — the field changed nothing at all.

Why this specific field matters to us more than most

systemInstruction is the only channel this API offers for approved terminology. A church supplies a glossary — Bible book names, the standard rendering of theological terms in each target language — and that glossary is a contractual expectation, not a nicety. “Worship” arriving in German as beten (“to pray”) is a different act in a church, and the Beatitudes formula rendered as ordinary good fortune changes a quotation of Matthew 5 into a remark about luck. On our composed (ASR → text translation → TTS) path we simply put the glossary in the translation prompt and it works. On this endpoint there is nowhere to put it, and the place that looks like it works, does not.

What we are asking for, in order of preference

  1. Support a terminology map. Even a narrow, purpose-built field — translationConfig.glossary: [{source, target}] — would be enough. It does not need free-form prompting.
  2. Failing that, reject the field. Returning an error for setup.systemInstruction would have saved us the entire investigation. A silently ignored field is worse than an unsupported one, because every experiment built on it produces plausible, meaningless results. We ran five instruction variants against a real sermon before discovering that none of them had ever been read.
  3. Please also document temperature / topP the same way — they are in the same category and we tested one of them too.

A related question we could not answer

An earlier internal measurement (2026-07-28) found that naming the source language inside systemInstruction moved our Persian input transcript from ~74% to ~99.5% accuracy, reproducibly, 3 runs out of 3. That result is incompatible with the field being ignored. Either the model’s handling of this field changed between July and August 2026, or that measurement was confounded. If the behaviour did change, knowing that would help us a great deal — the API has no source-language field at all, so if the instruction channel ever worked for pinning it, losing it silently is a significant regression for auto-detect-prone languages.


Issue 2 — polarity reversals on long or self-interrupting sentences

This is the quality problem that actually blocks unsupervised use. The model occasionally produces a fluent sentence that asserts the opposite of the source. In a sermon this is the most damaging error possible, and because the output is fluent, nobody in the room can detect it.

Measured

Real Armenian sermon audio, 5 minutes, source hy, targets fa and de, sentence-aligned scoring against an independent transcript:

target reversals per 100 source sentences
fa 10.2
de 4.1

Extrapolated to a 40-minute sermon that is roughly 16–40 reversed sentences per language, of which we judged about a third theologically consequential.

Examples (meaning of source → what was produced)

  • “it is not a fact that this man will be saved” → German “es ist sicher, dass dieser Mensch gerettet wird” (it is certain that he will be saved).
  • “the Lord gave to all his favoured heroes” → Persian “killed all his favourite heroes”.
  • “they were provided for and were not in poverty” → Persian “lived in poverty”.
  • “there are things even worse than poverty” → German “poverty is worse than other things” — the comparison inverted. Armenian marks the standard of comparison with the ablative, and the marked noun is being read as the greater side.

Two findings that may help you localise it

  1. It is not a recognition failure. The model’s own inputTranscription contains 21–23 negation markers against an independent ASR pass’s 24 on the same audio. It hears the negation and reverses it downstream.
  2. It concentrates in long, self-interrupting sentences. Reversed sentences averaged 122 characters against a 53-character median, and 4 of 6 fell in the 5 longest sentences of the sermon. The worst — 256 characters, where the preacher interrupts himself twice — reversed independently in both target languages. Two specific sentences reversed in 8 German runs out of 8 across five different configurations, so at least part of this is deterministic rather than sampling noise.

Environment

  • Model gemini-3.5-live-translate-preview, Gemini Developer API (WebSocket BidiGenerateContent), paid tier.
  • Setup: responseModalities: ["AUDIO"], translationConfig (targetLanguageCode, echoTargetLanguage: false), inputAudioTranscription and outputAudioTranscription at the top level of setup (as required — not inside generationConfig, which contradicts the docs and is already reported by another user), contextWindowCompression.slidingWindow, sessionResumption, realtimeInputConfig.activityHandling: NO_INTERRUPTION.
  • Input PCM16 mono 16 kHz in 100 ms frames, streamed at wall-clock speed.

We can provide the audio, the full setup frames, and both transcripts for any of the runs above.