Interrupções de streaming e SSE: recuperação sem duplicatas
Diferencie quedas de SSE, preserve a saída parcial e repita com segurança sem duplicar efeitos colaterais.
Uma solicitação de API em streaming só termina quando chega o evento terminal previsto pelo protocolo. Socket fechado, timeout do cliente ou o último fragmento de texto não comprovam conclusão. Após uma queda, preserve os eventos recebidos, a Request ID e o estado da operação. Antes de repetir, verifique efeitos colaterais: não existe continuação universal a partir do último token, e um retry cego pode executar uma ferramenta duas vezes.
Encerramento normal ou queda real
Server-Sent Events envia uma sequência de eventos por uma conexão HTTP longa. O cliente lê até um destes resultados:
completed confirma sucesso terminal; failed é um erro entregue no stream; disconnected indica que o transporte terminou sem final confirmado. Esse último estado precisa de diagnóstico. OpenAI Responses usa eventos como response.created, fragmentos de output e response.completed; Anthropic Messages usa message_start, eventos de bloco de conteúdo, message_delta e message_stop. Não misture esses nomes no mesmo parser.
Quer reproduzir uma queda de streaming em uma solicitação controlada? Crie sua própria conta BetterToken e API Key, abra a referência de API e comece com um stream curto sem Tool Calls. Compare hora, modelo e status com o Dashboard. Só então adicione um retry limitado.
Dados para guardar na queda
Um log mínimo separa problema do cliente de problema do servidor:
Não salve API Key, prompt completo, argumentos de ferramentas ou resposta sensível. Texto parcial só deve ser guardado se a política da aplicação permitir. Em produção, hash da operação, número de eventos e último marcador de sequência seguro costumam ser mais úteis. A Request ID pode chegar em cabeçalhos HTTP ou em um evento; registre-a logo no início.
Verifique o parser antes da rede
O cliente precisa lidar com várias linhas data: no mesmo evento, linhas vazias, fragmentos UTF-8 no limite de chunks, tipos desconhecidos sem encerrar o processo, evento de erro depois de HTTP 200, evento terminal sem o último delta e argumentos de ferramenta divididos. Um chunk TCP não é um evento SSE: monte primeiro uma frame SSE completa e depois faça parse do JSON.
Implemente is_terminal_success e is_terminal_failure separadamente para Responses, Chat Completions e Messages. Considerar evento desconhecido como sucesso esconde o estado necessário para decidir um retry.
Verifique timeout em cada camada
Uma conexão longa atravessa timeout do SDK ou cliente HTTP, timeout idle/read da aplicação, reverse proxy, load balancer ou ingress, proxy corporativo, rede móvel ou doméstica e limite de geração no servidor. Timeout geral e idle timeout são diferentes. Se o modelo envia eventos regularmente, um idle timeout curto não deveria disparar; se pausas longas são aceitáveis, ajuste o valor à carga esperada.
Verifique também o buffering do proxy. Se ele acumula chunks SSE, o usuário não vê texto por muito tempo e recebe um bloco grande ou timeout. Meça o tempo até o primeiro evento e os intervalos entre eventos localmente, atrás do reverse proxy e em produção.
Saída parcial: mostrar, salvar ou descartar
Texto parcial pode ser útil na interface, mas seu estado deve ser explícito. Não mostre uma resposta interrompida como concluída.
streaming: o texto ainda muda;complete: chegou evento terminal de sucesso;partial: a conexão caiu depois de vários eventos;failed: o protocolo entregou um erro;cancelled: usuário ou aplicação interrompeu a solicitação.
Para partial, mantenha o texto recebido separado da nova geração. Unir duas gerações automaticamente é perigoso: o modelo pode repetir conteúdo, mudar a redação ou chamar ferramentas em outra ordem.
Quando repetir uma solicitação
A segurança do retry depende da ação.
Texto sem ações externas
Uma solicitação curta de texto normalmente pode ser repetida com tentativas limitadas. Mostre o resultado antigo como partial e a resposta nova como geração separada, ou substitua apenas depois de confirmação explícita.
Tool Calls e transações
Antes de repetir, verifique se a ferramenta já foi executada. Se o stream caiu depois de enviar o comando, uma segunda solicitação pode recriar uma issue, e-mail ou transação de pagamento. Use Idempotency Key no nível da ferramenta, sua própria Operation ID e um log de ações concluídas.
Tarefa longa de agente
“Continuar do último token” raramente é confirmado pelo protocolo. Restaure a tarefa a partir do estado salvo da aplicação: mensagens confirmadas, resultados de ferramentas e última etapa concluída. Fragmentos brutos de texto não são um estado consistente de agente.
Retry limitado com backoff
Uma política de retry precisa ter número finito de tentativas:
O erro ser retryable depende de erro de protocolo, HTTP status, evento terminal e efeitos colaterais. 401, Model ID incorreto e JSON inválido não são resolvidos com espera. 429, 5xx temporário ou falha de transporte às vezes permitem novo envio, mas apenas com limite e considerando os cabeçalhos do provider. Backoff não substitui classificação de erro.
Teste mínimo
- Envie uma solicitação curta de streaming sem ferramentas.
- Anote todos os tipos de evento e espere o evento terminal.
- Encerre artificialmente o cliente após alguns eventos.
- Verifique que o resultado é
partial. - Teste um retry limitado.
- Repita atrás do proxy de produção.
- Compare as duas solicitações por hora, modelo e status no Dashboard.
Consulte os tipos exatos em OpenAI Streaming Responses e Anthropic Messages Streaming.
FAQ
É possível continuar um stream do último token?
Não há mecanismo universal. Guarde resultado parcial e estado da aplicação, depois siga os recursos da API concreta. Uma nova solicitação pode repetir ou alterar o texto.
Por que termina com erro apesar de HTTP status 200?
Os cabeçalhos chegam antes da geração completa. O erro pode aparecer depois como evento de protocolo ou queda de transporte; status sozinho não basta.
É preciso repetir após toda desconexão?
Não. Primeiro verifique evento terminal, erro, Request ID e efeitos colaterais. Retry de Tool Call exige idempotência.
Onde procurar se funciona localmente?
Verifique reverse proxy, load balancer, idle timeout, buffering e rede corporativa. Compare intervalos entre eventos antes e depois de cada camada.
O que verificar no BetterToken?
Abra Dashboard e compare hora, modelo, status e uso. Confira parâmetros atuais na referência de API; nunca envie ao suporte a API Key completa ou prompt sensível.