For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegação principal
Theme

Gerenciamento de sessões do GPT-Live

Configure sessões, mantenha o contexto e gerencie o ciclo de vida da conversa.

Depois de se conectar ao GPT-Live, use os eventos da sessão para adicionar contexto, exibir transcrições e gerenciar a conexão. O GPT-Live pode ouvir e falar ao mesmo tempo. Acompanhe separadamente o texto da transcrição, o áudio reproduzido e o andamento das tarefas no backend para que a interface mostre o que o assistente está dizendo e quais tarefas ainda estão em execução.

Este guia pressupõe que sua conexão já emitiu session.started. Consulte Conexões para configurar a conexão e a transmissão de áudio e Delegação e ferramentas para executar tarefas no backend.

Configure uma sessão

Escolha o modelo, a voz e o modo de delegação ao criar a sessão. Dê ao modelo instruções para a conversa e inclua o histórico relevante. O GPT-Live gerencia o contexto automaticamente à medida que a conversa avança.

Campos de configuração

Configuração Como configurar ao iniciar Como alterar durante a sessão
Modelo Defina o campo obrigatório model. Inicie uma nova sessão para alterar o modelo.
Instruções Use instructions para definir o comportamento durante a conversa, com até 16.384 tokens. Adicione instruções com session.instructions.append.
Histórico Inclua em input as mensagens de texto anteriores que forem relevantes. O valor padrão é []. Use os eventos de acréscimo para adicionar contexto.
Voz Defina audio.output.voice como uma voz compatível ou uma voz personalizada autorizada. O padrão é marin. Inicie uma nova sessão para alterar a voz.
Delegação Defina delegation.type como client ou responses. Se você omitir a delegação ou usar null, a sessão usará o modo cliente. Atualize as configurações da Responses no modo atual.
Armazenamento Defina store como true para permitir a criação de forks da sessão. O padrão é false. Faça essa escolha ao iniciar a sessão.

Opções de voz

Escolha uma voz ao criar a sessão. Defina audio.output.voice com o nome usado na API, como "quartz". O GPT-Live inclui estas opções adicionais de voz:

Voz Nome na API Idioma Influência regional Apresentação Origem
Quartz quartz Inglês Australiana Feminina Gerada
Ripple ripple Inglês Australiana Masculina Natural
Vesper vesper Inglês Britânica Masculina Natural
Willow willow Inglês Irlandesa Feminina Natural
Stone stone Inglês Irlandesa Masculina Natural
Gleam gleam Inglês Norte-americana Feminina Natural
Meridian meridian Inglês Norte-americana Masculina Natural
Bossa bossa Português Brasileira Feminina Natural
Tempo tempo Português Brasileira Masculina Natural
Beacon beacon Inglês Filipina Masculina Gerada
Delta delta Inglês Sul dos EUA Feminina Gerada
Cinder cinder Inglês Sul dos EUA Masculina Gerada
Nuri nuri Alemão — Feminina Natural
Juni juni Alemão — Feminina Natural
Flitz flitz Alemão — Masculina Natural
Brise brise Francês — Feminina Natural
Sillage sillage Francês — Masculina Natural
Nira nira Híndi — Feminina Natural
Harema harema Japonês — Feminina Natural
Shida shida Japonês — Masculina Natural
Noeul noeul Coreano — Feminina Natural

A influência regional descreve o estilo de fala de cada voz. Teste a voz com os idiomas e a pronúncia de que seu aplicativo precisa. Para criar uma voz a partir de uma descrição em texto ou de uma gravação aprovada, consulte Vozes personalizadas.

Com WebSocket, escolha audio.format ao iniciar a sessão. O mesmo formato se aplica ao áudio de entrada e de saída da sessão. Para usar outro formato, inicie uma nova sessão. O WebRTC negocia o formato de áudio ao estabelecer a conexão, portanto omita audio.format nas solicitações WebRTC. Consulte Formatos de áudio para WebSocket para conhecer os formatos compatíveis e os detalhes da transmissão.

Atualize uma sessão em andamento

Use session.update para alterar session.delegation.responses em uma sessão que já usa delegação via Responses. Envie apenas as configurações que deseja alterar. As configurações omitidas mantêm seus valores. Consulte Configure a delegação via Responses para conhecer as configurações e o fluxo de atualização.

Escolha o modo de delegação e defina os campos model, instructions, input, audio e store ao iniciar a sessão. Use session.update apenas para as configurações compatíveis da Responses descritas acima. A sessão rejeita outros campos de configuração. Para mudar o modo de delegação, crie uma nova sessão. Na inicialização, delegation: null seleciona a delegação pelo cliente e não restaura as configurações padrão da Responses.

Quando a atualização é bem-sucedida, a sessão emite session.updated com a configuração resultante. Associe esse evento ao event_id que você enviou usando client_event_id. Trate os comandos rejeitados no mesmo loop de eventos. Acompanhe as tarefas do backend e a fala do assistente pelos respectivos eventos.

Forneça histórico e contexto

Use o histórico na inicialização para retomar um assunto e acrescente contexto relevante ao longo da conversa. Mantenha as instruções confiáveis do aplicativo separadas das mensagens do usuário e dos resultados factuais.

Inicie uma sessão com o histórico de uma conversa

Inclua as mensagens de texto anteriores em session.input ao criar a sessão. Por exemplo, adicione este campo input à configuração de criação da sessão:

export const session = {
  model: "gpt-live-1",
  input: [
    {
      type: "message",
      role: "user",
      content: [
        {
          type: "input_text",
          text: "I need help with my recent order.",
        },
      ],
    },
    {
      type: "message",
      role: "assistant",
      content: [
        {
          type: "output_text",
          text: "What is the order number?",
        },
      ],
    },
  ],
};

A lista aceita até 128 mensagens, com um limite total de 8.192 tokens. Cada mensagem tem uma única parte de texto e um destes papéis: developer, user ou assistant. Mensagens do desenvolvedor e do usuário usam input_text. Mensagens do assistente usam text ou output_text. Coloque as instruções confiáveis do aplicativo em instructions ou em uma mensagem do desenvolvedor.

Selecione o histórico de texto necessário para a próxima interação e forneça-o ao iniciar a sessão. Durante a sessão, envie atualizações com os eventos de contexto descritos a seguir. Envie itens específicos do backend, como resultados de ferramentas, pelo fluxo de delegação.

Entenda quando o contexto chega ao modelo

Coloque em input todo o contexto de que o modelo precisa desde o início. O conteúdo completo do campo fica disponível assim que a sessão começa.

Durante a sessão, session.instructions.append, session.thinking.append e session.commentary.append acrescentam contexto ao longo do tempo. A confirmação chega quando a linha do tempo da sessão atinge o fim estimado do contexto adicionado. Os campos start_ms e end_ms da confirmação indicam o intervalo estimado dessa atualização na linha do tempo da sessão.

Esses tempos se referem à entrega do contexto. A fala e a reprodução têm seus próprios tempos. O modelo ainda pode responder antes de usar toda a atualização. Quando uma ação depender de uma nova instrução ou informação, verifique o comportamento resultante no aplicativo.

Se a linha do tempo da sessão parar de avançar, a confirmação poderá ficar pendente. Associe cada confirmação ao event_id enviado usando client_event_id e continue tratando erros enquanto aguarda. Ao fechar a sessão, você receberá erros para os acréscimos de contexto ainda pendentes.

Adicione contexto durante a conversa

Escolha o evento de acordo com o uso que o modelo deve fazer da atualização:

  • session.instructions.append: adicione instruções confiáveis do aplicativo que influenciem o comportamento e a fala.
  • session.thinking.append: adicione informações factuais sem pedir que o modelo as diga imediatamente.
  • session.commentary.append: forneça informações para o modelo dizer em voz alta. Ele pode reformulá-las.

Cada evento recebe content como uma string simples de até 500 tokens e exige um delegation_id. Use null para contexto que se aplica à sessão inteira. Por exemplo, envie o evento a seguir depois que seu aplicativo verificar que o usuário aceitou e iniciar a consulta:

export function sendUpdate(connection) {
  connection.send({
    type: "session.thinking.append",
    event_id: "context_1",
    delegation_id: null,
    content:
      "The user has already accepted the terms. The account lookup is still running.",
  });
}

Para acompanhar essa atualização, trate session.thinking.appended com client_event_id: "context_1" ou o erro correspondente. Consulte Entenda quando o contexto chega ao modelo para saber quando esperar a confirmação.

O assistente pode repetir informações fornecidas por qualquer um desses eventos. Envie apenas informações adequadas à conversa e mantenha credenciais e segredos no backend. Use session.instructions.append para definir o comportamento previsto pelo aplicativo. Forneça os resultados factuais das ferramentas como contexto e faça o código do aplicativo aplicar as permissões e exigir as confirmações necessárias.

Para navegação entre páginas, seleções e outras mudanças na interface, consulte Compartilhe o contexto da interface e veja como enviar atualizações concisas que ajudem o GPT-Live a entender a que o usuário se refere.

Para atualizar o modelo sobre uma tarefa específica do backend, use o ID da delegação pelo cliente correspondente. O ID de delegação identifica a tarefa do Live. Os IDs de respostas da Responses e de chamadas de ferramentas identificam outros objetos. Consulte Envie o tipo de atualização adequado para conhecer o fluxo.

Quando o aplicativo detectar um problema, envie uma correção breve pelo WebSocket principal da sessão ou por um WebSocket de canal lateral. Consulte Aplique medidas de proteção à conversa para saber como implementar verificações, controlar ações e gerenciar a reprodução.

Gerencie a fala e as transcrições

Fragmentos incrementais de transcrição

Escute os eventos session.input_transcript.delta para a fala do usuário e session.output_transcript.delta para a fala do assistente. Cada evento contém um fragmento de texto e o intervalo correspondente na linha do tempo da sessão:

{
  "type": "session.input_transcript.delta",
  "event_id": "event_transcript_1",
  "delta": "What is",
  "start_ms": 1000,
  "end_ms": 1200
}

Concatene os fragmentos delta de cada participante exatamente como os recebeu, preservando os espaços e as palavras repetidas. Guarde os valores de start_ms e end_ms de cada fragmento. Esses valores indicam os milissegundos decorridos desde o início da sessão. O exemplo acima cobre o intervalo de 1.000 ms a 1.200 ms, sem incluir o instante de 1.200 ms. Os valores indicam o intervalo aproximado de cada fragmento, sem delimitar cada palavra com precisão. Use esses valores para organizar a transcrição em vez dos horários de chegada dos pacotes.

Os eventos de transcrição chegam para os intervalos que contêm texto, e o ritmo de entrega pode variar. Um fragmento pode conter apenas parte de uma frase, e uma pausa na entrega pode decorrer de um atraso na rede. Os fragmentos incrementais não têm ID de item, e nenhum evento marca o fim de um turno da conversa. Cabe ao aplicativo decidir como agrupá-los para exibição.

O processamento dos fragmentos de transcrição é opcional. Você pode usá-los para atualizar a interface, executar verificações ou iniciar tarefas antecipadamente enquanto a conversa continua. Para verificações simples, considere usar um modelo pequeno, como gpt-5.6-luna, com baixo esforço de raciocínio. Consulte Reaja a fragmentos de transcrição para ver exemplos e orientações sobre a conexão.

Use medidas de proteção baseadas na transcrição para monitorar a conversa e acionar intervenções enquanto os participantes falam. Se o aplicativo precisar verificar a fala do assistente antes de reproduzi-la, consulte Verifique a fala antes da reprodução para saber como usar um buffer e lidar com aprovação, interrupção e recuperação.

Acompanhe separadamente os tempos da transcrição e da reprodução de áudio. No WebSocket, os eventos session.output_audio.delta não têm campos de tempo e não há evento que sinalize o fim do áudio de saída. O WebRTC entrega o áudio pela faixa de mídia. Consulte Conexões para saber como lidar com o áudio.

Exiba legendas

O GPT-Live opera em full duplex, ou seja, a pessoa na chamada e o assistente podem falar ao mesmo tempo. Atualize as legendas de cada participante de forma independente para que ambas continuem recebendo texto quando as falas se sobrepuserem.

Se o aplicativo usar balões de conversa, os fragmentos “Eu gostaria” e “ de alterar minha reserva” podem aparecer em um único balão da pessoa na chamada. Se o assistente disser “Claro” enquanto a pessoa continua falando, exiba essa resposta em um balão separado e continue adicionando texto ao balão da pessoa. Guarde os fragmentos originais e suas marcas de tempo para que o texto recebido depois atualize o balão correto.

Use session.output_transcript.delta para legendar a fala e exiba as atualizações do backend separadamente. Tome as decisões sobre executar ferramentas ou cancelar tarefas na lógica de tarefas do aplicativo, separada da lógica que agrupa o texto para exibição.

Controle a entrada do microfone

Envie session.input_audio.mute para silenciar a entrada sem encerrar a sessão:

export function sendUpdate(connection) {
  connection.send({
    type: "session.input_audio.mute",
    event_id: "mute_1",
  });
}

Aguarde session.input_audio.muted com client_event_id: "mute_1" antes de considerar o comando aceito. Para retomar a entrada, envie session.input_audio.unmute e aguarde session.input_audio.unmuted. Trate os erros de ambos os comandos.

Ao silenciar a entrada, a sessão continua ativa. O modelo pode continuar gerando fala, e as tarefas delegadas podem continuar em execução. Se também precisar interromper a gravação ou a reprodução local, use os controles de captura do microfone e do reprodutor de áudio do aplicativo.

Cumprimente a pessoa antes que ela comece a falar

Para obter melhores resultados quando o GPT-Live precisar iniciar a conversa, inclua instruções para a saudação em uma mensagem developer em session.input ao criar a sessão. No WebSocket, inclua a mensagem no evento session.start. Assim, as instruções para a saudação ficam disponíveis desde o início.

Especifique o idioma e o que o assistente deve dizer. Oriente-o a começar imediatamente e depois fazer uma pausa para ouvir. Use o idioma que o aplicativo escolheu para a saudação até que a pessoa na chamada comece a falar. Por exemplo, use este texto na mensagem do desenvolvedor:

Cumprimente agora, em inglês, a pessoa que ligou. Apresente-se como o assistente de suporte e pergunte como pode ajudar. Depois, faça uma pausa para ouvir.

  1. Adicione a mensagem a session.input com role: "developer" e uma única parte de conteúdo do tipo input_text. Consulte Inicie uma sessão com o histórico de uma conversa para ver o formato da mensagem.
  2. Aguarde session.started e envie as mesmas instruções de saudação uma única vez por session.commentary.append, usando um event_id exclusivo e delegation_id: null, como no exemplo abaixo. Mantenha a entrada de áudio ativa, inclusive durante o silêncio antes de a pessoa falar. No WebSocket, continue enviando session.input_audio.append. No WebRTC, mantenha a faixa de áudio de entrada ativa.
  3. Verifique o áudio de saída e a transcrição para confirmar que o assistente cumprimentou a pessoa. As instruções iniciais podem melhorar a saudação, mas não garantem que o modelo fale.
{
  "type": "session.commentary.append",
  "event_id": "greeting_1",
  "delegation_id": null,
  "content": "Greet the caller now in English. Introduce yourself as the support assistant and ask how you can help. Then pause and listen."
}

O evento session.commentary.appended confirma o recebimento da solicitação. Ele não confirma que o assistente falou a saudação nem que o aplicativo a reproduziu. O GPT-Live pode reformular a saudação, acrescentar palavras ou permanecer em silêncio.

Se precisar de uma reprodução previsível da saudação, de um texto exato ou de saber precisamente quando a reprodução termina, use o aplicativo para reproduzir uma gravação verificada ou um trecho de áudio renderizado e controle a reprodução do GPT-Live durante esse intervalo. Teste as saudações nos idiomas compatíveis com o aplicativo, inclusive quando a pessoa começa a falar durante a saudação. Consulte Como escrever prompts para modelos de voz para saber como elaborar os prompts.

Transmita um aviso

Use session.instructions.append para pedir que o assistente diga um aviso com palavras específicas. Com session.commentary.append, o modelo pode reformular o texto. Após session.started, por exemplo, envie:

export function sendUpdate(connection) {
  connection.send({
    type: "session.instructions.append",
    event_id: "disclosure_1",
    delegation_id: null,
    content:
      "Immediately say the following disclosure exactly and in full before responding to the caller: This call may be recorded for quality and training purposes.",
  });
}

Mantenha o áudio de entrada ativo, como em Cumprimente a pessoa antes que ela comece a falar. Uma instrução enviada durante a conversa pode interromper uma fala em andamento.

Verifique o aviso gerado e sua reprodução antes de marcá-lo como entregue. A confirmação da instrução registra que ela foi aceita. Confira no próprio áudio quais palavras foram ditas. Se precisar de um texto exato e de saber precisamente quando a reprodução termina, use o aplicativo para reproduzir uma gravação verificada ou um trecho de áudio renderizado e controle a saída do GPT-Live durante esse intervalo. Consulte Controle a reprodução quando necessário.

Gerencie conversas mais longas

O GPT-Live gerencia conversas longas automaticamente e preserva as instruções originais fornecidas ao iniciar a sessão.

A janela de contexto padrão comporta 128.000 tokens, incluindo as instruções, o texto da conversa e os tokens de áudio que não aparecem na transcrição.

O GPT-Live resume em segundo plano os trechos mais antigos da conversa. Quando o uso da janela de contexto ultrapassa 90%, o GPT-Live inicia outro mecanismo de voz na mesma sessão para substituir o atual. O novo mecanismo recebe as instruções originais e até 8.192 tokens do histórico da conversa, incluindo mensagens recentes e, quando disponível, um resumo das mensagens mais antigas. A preparação de um resumo não altera imediatamente o contexto do mecanismo em execução.

O GPT-Live pode resumir ou omitir detalhes de trechos mais antigos da conversa. Guarde no aplicativo os fatos importantes, as ações confirmadas e o estado atual das tarefas. Forneça o contexto relevante quando necessário.

Armazene uma sessão e crie um fork

Um fork inicia uma nova sessão a partir de uma conversa por voz salva. Use esse recurso para executar vários testes de avaliação a partir da mesma conversa de referência ou para que o usuário possa continuar a conversa depois que uma sessão terminar. Cada fork recebe uma nova conexão e um novo ID de sessão e tem como ponto de partida a conversa de origem e sua configuração salva.

Execute avaliações a partir de uma conversa de referência

Suponha que você queira testar como seu agente lida com uma pessoa que pede para alterar um pedido. Grave a conversa inicial uma única vez, até o ponto em que a pessoa identifica o pedido. Encerre a sessão e aguarde a finalização antes que a pessoa solicite a alteração. Assim, cada avaliação pode criar um fork da mesma sessão de referência e receber o mesmo trecho de áudio seguinte: “Actually, can you send it to my office instead?”

Em cada teste, restaure o mesmo pedido de teste e o mesmo estado do aplicativo, forneça a próxima fala da pessoa e avalie a nova resposta e as ações das ferramentas. Você pode repetir o cenário ou comparar as configurações compatíveis do backend da Responses. Meça o tempo de inicialização do fork separadamente do tempo de resposta. Consulte o guia de avaliação do GPT-Live para saber como escolher cenários e medir resultados.

Os forks herdam o modelo do GPT-Live, a voz e as instruções originais. Para comparar outro modelo de voz ou prompt inicial, crie novas sessões com a configuração desejada. A API de fork usa a gravação concluída da sessão de origem, portanto encerre a sessão de referência no ponto em que deseja iniciar a avaliação.

Continue a conversa após o término da sessão

Uma pessoa pode, por exemplo, desligar e ligar novamente mais tarde ou se reconectar após a queda de uma chamada. Se a sessão anterior tiver uma gravação concluída e armazenada, o aplicativo poderá criar um fork dessa sessão em uma nova conexão e continuar a partir da conversa salva.

Salve o estado das tarefas do aplicativo junto com o ID da sessão de origem. Antes de continuar, verifique o andamento das tarefas pendentes no backend e forneça os resultados atuais à nova sessão. Por exemplo, se uma alteração de pedido já tiver sido enviada, confirme o resultado antes de tentar outra alteração. Use o novo ID de sessão para os controles e as conexões de canal lateral e encaminhe os próximos resultados do backend à nova sessão.

Prepare uma sessão para criar forks

  1. Ative o armazenamento ao criar a sessão de origem. Defina store: true na configuração da sessão. O valor padrão é false. O armazenamento precisa estar habilitado para o projeto e exige uma política de dados que permita a persistência.
  2. Salve o ID da sessão de origem. Obtenha o ID em session.started ou na resposta de criação via WebRTC e associe-o ao registro da conversa no aplicativo.
  3. Conclua as tarefas e feche a sessão de origem. Termine as tarefas necessárias no backend e siga as instruções de Uso e encerramento ordenado. Mantenha a conexão aberta até receber session.closed e trate eventuais erros de finalização. Para criar um fork, é preciso ter uma gravação concluída e armazenada. Salvar a gravação pode aumentar o tempo de finalização.
  4. Inicie um fork em uma nova conexão. Use o ID da sessão de origem no fluxo de transporte descrito a seguir, salve o novo ID de sessão e conclua a inicialização antes de continuar a conversa. Defina explicitamente o campo store da sessão criada: use true se quiser criar outro fork dessa continuação mais tarde ou false se não precisar armazenar esse teste. Se você omitir o campo, a nova sessão herdará a configuração de origem.

As gravações armazenadas ficam disponíveis por 30 dias. Com zero retenção de dados (ZDR), o sistema trata store como false e a criação de forks fica indisponível. Para avaliações com forks, use uma organização sem ZDR que tenha o armazenamento habilitado para o projeto.

Se não houver uma gravação concluída e armazenada, inicie uma nova sessão com o histórico de texto relevante que você salvou. Consulte Controles de dados do GPT-Live para conhecer os requisitos de armazenamento.

Por exemplo, defina o campo a seguir na configuração do evento WebSocket session.start da sessão de origem ou na solicitação de criação via WebRTC:

{
  "store": true
}

Inicie o fork pelo transporte usado no aplicativo:

Transporte Como iniciar o fork
WebSocket Conecte-se a wss://api.openai.com/v1/live/sessions/{source_session_id}/fork.
WebRTC Envie uma nova oferta SDP para POST /v1/live/sessions/{source_session_id}/fork. Aplique a resposta SDP retornada em transport.sdp à nova conexão entre pares.

O fork herda o modelo, as instruções originais e a entrada da sessão de origem. Ao iniciar o fork, envie apenas as configurações que o transporte permite substituir:

  • WebSocket: store, as configurações de delegação via Responses e o campo audio.format da nova conexão. Envie um evento session.start com um objeto session. Use {} para manter as configurações herdadas quando houver suporte à herança.
  • WebRTC: store, as configurações de delegação via Responses e as permissões do cliente no frontend.

Para um fork via WebSocket, defina audio.format para a nova conexão ou use o padrão PCM16 a 24 kHz. O fork via WebSocket não herda o formato de áudio de origem nem as permissões do canal de dados do frontend. O WebRTC negocia o formato de áudio ao estabelecer a conexão, portanto omita audio.format. O WebRTC preserva as configurações de permissão do frontend, a menos que você as substitua.

Com WebSocket, aguarde session.started antes de enviar outros comandos. Com WebRTC, a solicitação HTTP inicia a sessão. Continue pela conexão negociada sem enviar outro session.start.

Inicie um fork via WebSocket

Defina OPENAI_API_KEY. Os exemplos usam o ID que o aplicativo salvou para a sessão de origem armazenada. Eles confirmam a inicialização e depois fecham o fork. Para continuar a conversa, envie e receba áudio após session.started seguindo o fluxo de conexão via WebSocket. Consulte a referência de forks via WebSocket para conhecer os campos e eventos de inicialização.

import OpenAI from "openai";
import { ForksWS } from "openai/resources/live/forks/ws";

async function forkSession(sourceSessionId) {
  const ws = new ForksWS(new OpenAI(), { session_id: sourceSessionId });
  let finalized = false;
  let closeRequested = false;
  try {
    for await (const event of ws) {
      if (event.type === "open") {
        ws.send({ type: "session.start", session: {} });
      } else if (event.type === "error") {
        throw event.error;
      } else if (event.type === "message") {
        if (event.message.type === "session.started") {
          console.log("Fork ready:", event.message.session.id);
          // This startup example closes the fork after confirming it is ready.
          ws.send({ type: "session.close" });
          closeRequested = true;
        } else if (event.message.type === "session.closed") {
          console.log("Final usage:", event.message.usage);
          if (!closeRequested) {
            throw new Error("Fork ended before startup completed");
          }
          finalized = true;
          break;
        }
      }
    }
    if (!finalized) throw new Error("Connection closed before session.closed");
  } finally {
    ws.close();
  }
}

Inicie um fork via WebRTC

Crie uma nova oferta SDP no frontend e envie-a ao backend. Os exemplos de backend a seguir usam essa oferta e o ID que o aplicativo salvou para a sessão de origem armazenada:

import OpenAI from "openai";

async function forkSession(sourceSessionId, offerSdp) {
  const client = new OpenAI();
  const fork = await client.live.sessions.fork(sourceSessionId, {
    transport: { type: "webrtc", sdp: offerSdp },
  });
  console.log(JSON.stringify(fork));
}

Devolva a resposta ao frontend, aplique transport.sdp como resposta SDP da nova conexão entre pares e guarde o novo session.id. Mantenha a chave de API no backend.

Use o novo ID de sessão para conexões de canal lateral e controles da sessão. Antes de tentar executar novamente uma ação que ficou pendente, verifique o resultado no backend e restaure o estado atual das tarefas do aplicativo. Se não houver uma gravação concluída e armazenada, inicie uma nova sessão com o histórico salvo.

Baixe uma gravação

Após a finalização da gravação armazenada, baixe o áudio com GET /v1/live/sessions/{session_id}/content. A resposta contém um WAV estéreo em formato binário, com o áudio de entrada no canal esquerdo e o de saída no direito. Os exemplos usam o ID que o aplicativo salvou para a sessão armazenada e gravam o fluxo da resposta em recording.wav:

import OpenAI from "openai";
import { createWriteStream } from "node:fs";
import { pipeline } from "node:stream/promises";

async function downloadRecording(sessionId) {
  const client = new OpenAI();
  const response = await client.live.sessions.downloadRecording(sessionId);
  if (!response.body) throw new Error("Recording response has no body");
  await pipeline(response.body, createWriteStream("recording.wav"));
}

Feche sessões ociosas e retome a conversa

Em aplicativos com intervalos longos entre as interações, feche a sessão de voz durante a inatividade e inicie uma nova quando o usuário voltar. Guarde o contexto da conversa e o estado das tarefas do aplicativo para que o usuário possa continuar sem repetir o que já disse. Por exemplo, um assistente veicular pode retomar a conversa quando o motorista reativar o controle por voz, enquanto um assistente de programação pode manter o processo de trabalho em execução no backend entre conversas por voz.

  1. Decida quando fechar a sessão. Defina no aplicativo um tempo limite de inatividade que leve em conta a atividade de áudio, a reprodução da fala do assistente e as interações com o aplicativo. Considere pausas esperadas, como o tempo para ler ou pensar. Só feche a sessão quando a reprodução terminar e nenhuma tarefa pendente depender da sessão de voz atual. Intervalos entre eventos de transcrição, por si só, não indicam silêncio.
  2. Salve o estado e encerre a sessão de forma ordenada. Salve o ID da sessão de origem, o contexto da conversa e o estado atual das tarefas. Conclua as tarefas necessárias da Responses e siga as instruções de Uso e encerramento ordenado. Registre o listener de session.closed, envie session.close e aguarde session.closed antes de liberar a conexão. Com a delegação pelo cliente, as tarefas do backend gerenciadas pelo aplicativo podem continuar de forma independente enquanto a sessão de voz estiver fechada.
  3. Identifique quando reiniciar. Ofereça um botão Retomar conversa, um controle que o usuário possa pressionar para falar ou um mecanismo de ativação gerenciado pelo aplicativo. Uma sessão do Live fechada não consegue ouvir o usuário. Se usar detecção local de fala para reiniciar automaticamente, mantenha a captura do microfone ativa e armazene o início da fala em um buffer enquanto a conexão é estabelecida. Envie esse áudio assim que a nova sessão estiver pronta para preservar as primeiras palavras do usuário.
  4. Restaure o contexto em uma nova sessão. Se a sessão de origem foi criada com store: true, o armazenamento está habilitado e é permitido pela política de dados e a gravação foi finalizada com sucesso, crie um fork da sessão armazenada. Caso contrário, inicie uma nova sessão com o histórico de texto salvo. Salve o novo ID de sessão, verifique o estado das operações pendentes no backend e encaminhe os próximos resultados à nova sessão. Guarde o estado das operações no aplicativo para evitar que a reinicialização repita ações já concluídas.

Silenciar o microfone mantém a sessão ativa. Para escolher um tempo limite de inatividade, compare o tempo de uso de voz que você economizaria com os custos de criação da sessão e a espera até que a voz esteja disponível novamente. Consulte Custos de sessões de voz e Cobranças pela inicialização do WebRTC.

Trate erros e encerre a sessão

Continue lendo os eventos da sessão até que ela seja finalizada. Distinga comandos rejeitados, falhas de conexão e sessões concluídas para que o aplicativo possa reagir de forma adequada a cada situação.

Trate comandos rejeitados

Leia os eventos error junto com as confirmações. Quando presente, error.client_event_id identifica o comando enviado que falhou:

{
  "type": "error",
  "event_id": "event_error",
  "error": {
    "type": "invalid_request_error",
    "code": "immutable_field_update",
    "message": "The delegation type cannot change after session startup.",
    "param": "session.delegation.type",
    "client_event_id": "event_update"
  }
}

Implemente um tratamento genérico para erros cujo código seja null ou que não incluam o ID do evento do cliente. Se o erro indicar um campo imutável, mantenha a configuração atual ou crie uma nova sessão com as configurações desejadas.

Trate eventos de moderação

A moderação pode afetar a sessão de duas maneiras:

  • Alguns eventos de moderação encerram a sessão.
  • Outros cortam o áudio do assistente pelo restante da fala em andamento e emitem um evento error sem encerrar a sessão.

Continue tratando eventos error durante a reprodução do áudio. Acompanhe separadamente as interrupções de áudio e o fechamento da sessão. Só marque uma mensagem falada como entregue depois de verificar a reprodução. Aplique suas próprias medidas de proteção à conversa em conjunto com a moderação integrada.

Uso e encerramento ordenado

O evento session.usage.updated informa o tempo acumulado de uso de voz em segundos:

{
  "type": "session.usage.updated",
  "event_id": "event_usage_1",
  "usage": { "seconds": 12 },
  "context_window": { "usage_ratio": 0.42 }
}

Use o valor mais recente de usage.seconds como tempo total de uso de voz até o momento. Por exemplo, se uma atualização indicar 12 segundos e a seguinte indicar 15, o uso total será de 15 segundos. Acompanhe separadamente o uso de tokens do backend pelos eventos aninhados de conclusão da Responses. Consulte Otimização de custos para saber como contabilizar o uso.

Para encerrar a sessão de forma ordenada:

  1. Conclua as tarefas delegadas à Responses de que o aplicativo precisa, incluindo o envio de resultados de funções pendentes e a continuação das respostas.
  2. Registre o listener de session.closed antes de enviar session.close.
  3. Envie session.close e pare de enviar novas tarefas à sessão. Mantenha ativos a conexão WebSocket ou WebRTC, o canal de dados e os receptores de canal lateral conectados até que todos os eventos pendentes da sessão sejam processados.
  4. Leia o valor final de usage.seconds, o motivo em reason e o registro do estado da sessão no evento session.closed. Preserve os dados de uso das tarefas delegadas já recebidos por response.event.
  5. Após esse evento, libere os recursos de transporte e os dispositivos de áudio. Se a finalização falhar ou exceder o tempo limite definido pelo aplicativo, informe que ela ficou incompleta e libere os recursos.

O envio de session.close cancela as respostas da Responses que estão na fila e faz com que a sessão rejeite novos comandos. Uma resposta em andamento pode terminar, mas uma resposta que aguarda o resultado de uma função não pode continuar depois que o fechamento começa. Decida separadamente se deseja concluir ou cancelar as tarefas que o aplicativo executa por delegação pelo cliente.

Use session.closed para confirmar a finalização e consultar o registro da configuração final. Mantenha o transporte aberto até receber esse evento. Se o socket fechar antes, registre a finalização como não confirmada. Se fechar depois de um evento session.closed válido, preserve o resultado confirmado.

O campo reason do evento final indica por que a sessão terminou:

Motivo Significado
close_requested O aplicativo enviou session.close ou chamou o endpoint de encerramento da chamada.
expired A sessão atingiu o limite de duração.
content Um filtro de segurança encerrou a sessão.
remote_hangup A conexão principal remota foi encerrada de forma ordenada.
connection_lost A conexão principal ou a conexão upstream caiu inesperadamente.

O evento session.closed confirma a finalização mesmo quando a sessão termina por perda de conexão ou por motivos de segurança. Sem esse evento, o uso final permanece sem confirmação. Uma sessão com armazenamento habilitado pode levar mais tempo para finalizar enquanto a gravação é salva. Defina um tempo limite no aplicativo que leve isso em conta.

Recupere a conversa após uma falha de conexão

Um erro HTTP na criação da sessão indica que ela não chegou a emitir session.started. Trate os erros de inicialização separadamente dos que ocorrem durante uma sessão em andamento. Se a conexão cair durante a sessão, antes de session.closed, guarde o último valor de uso observado e marque o uso final como não confirmado.

Se houver uma gravação concluída e armazenada, crie um fork para continuar em uma nova sessão. Caso contrário, crie uma sessão substituta com o histórico relevante que você salvou. Antes de continuar, consulte o backend para verificar as ações pendentes, restaure o estado atual das tarefas e atualize o encaminhamento dos resultados para impedir que resultados atrasados da sessão anterior sobrescrevam o trabalho mais recente.