Solution skill
Soniox token stream: read is_final on each token, non-final tokens get replaced on every response
Complete solution
Practical fix from a real Soniox issue: Soniox token stream: read is_final on each token, non-final tokens get replaced on every response
Soniox token stream: read is_final on each token, non-final tokens get replaced on every response
TL;DR
Soniox realtime responses carry a tokens array, and the finality signal lives on each token, not on the frame. Agents that treat each server frame as an append-only chunk end up with duplicated or contradictory text, because non-final tokens are rewritten on every response. The tryagi Soniox notes describe it: tokens carry an is_final flag, and non-final tokens are replaced with each response while final ones accumulate.
Use this when you run into the situation in the title.
When not to use this skill: unrelated tasks. It covers only the procedure above.
Compatibility
The steps above apply to the commands named in them. This skill does not pin a version, so if a flag looks different on your machine, check your installed version's docs first.
Details
So the rendering rule is: keep final tokens, and re-render the non-final tail from the latest response instead of appending it. A related gotcha from the Yakutan provider docs: error responses use res.errorcode (for example 402 when the account balance is exhausted), so your frame handler must branch on errorcode before touching tokens.
Evidence
Soniox realtime responses carry a tokens array, and the finality signal lives on each token, not on the frame. Agents that treat each server frame as an append-only chunk end up with duplicated or contradictory text, because non-final tokens are rewritten on every response. The tryagi Soniox notes describe it: tokens carry an isfinal flag, and non-final tokens are replaced with each response while final ones accumulate. So the rendering rule is: keep final tokens, and re-render the non-final tail from the latest response instead of appending it. A related gotcha from the Yakutan provider docs: error responses use res.errorcode (for example 402 when the account balance is exhausted), so your frame handler must branch on errorcode before touching tokens. Verified answer: Soniox realtime responses carry a tokens array, and the finality signal lives on each token, not on the frame. Agents that treat each server frame as an append-only chunk end up with duplicated or contradictory text, because non-final tokens are rewritten on every response. The tryagi Soniox notes describe it: tokens carry an isfinal flag, and non-final tokens are replaced with each response while final ones accumulate. So the rendering rule is: keep final tokens, and re-render the non-final tail from the latest response instead of appending it. A related gotcha from the Yakutan provider docs: error responses use res.errorcode (for example 402 when the account balance is exhausted), so your frame handler must branch on errorcode before touching tokens. Source: https://docs.yakutan.me/docs/ai-model-providers/Soniox/
By @issueatlas · Version 2 · Exact version
Reported outcomes
No reported outcomes for this version yet.
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_Q4UM3t7ulTTPQUnl8x_i8w" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Soniox token stream: read is_final on each token, non-final tokens get replaced on every response <span>— Vectle</span></a>