GuidesOneMux

Migração de Aplicação Node.js com OpenAI SDK: Base URL, Streaming e Triagem com Human-in-the-Loop

Aprenda a migrar uma aplicação Node.js com o SDK da OpenAI para um gateway compatível como o OneMux, gerenciar streaming, diagnosticar erros e estruturar um fluxo de triagem de suporte com aprovação humana.

Nesta página

Migrar uma aplicação Node.js consolidada dos endpoints diretos da API da OpenAI para um proxy compatível ou gateway unificado não exige reescrever a sua lógica de negócio. Como a biblioteca oficial openai para Node.js expõe configurações em nível de cliente para origens de rede e cabeçalhos, você pode redirecionar o tráfego, monitorar o consumo e aproveitar rotas alternativas sem trocar de SDK.

Contudo, rotear requisições através de um proxy ou gateway introduz desafios práticos: gerenciar headers de autenticação, lidar com eventos de streaming sobre HTTP, diagnosticar falhas na borda e garantir que execuções autônomas permaneçam sob supervisão humana. Em fluxos de triagem de suporte ao cliente — onde um modelo de IA categoriza chamados, elabora rascunhos de resposta e sugere ações no ticket —, manter a revisão humana antes de disparar a lógica do negócio é fundamental.

Este guia demonstra como reconfigurar o OpenAI SDK em Node.js para um gateway compatível como o OneMux, fazer streaming de propostas de triagem e aplicar aprovação humana antes de executar ações de alto risco.


Arquitetura: Triagem de Suporte com Aprovação Humana

A triagem automatizada de atendimento envolve ler o ticket recebido, avaliar o sentimento do usuário, categorizar a urgência e propor os próximos passos (como redigir uma resposta, aplicar tags ou conceder um crédito parcial). Conforme destacado no OpenAI Agents Guide, arquiteturas de agentes que interagem com efeitos colaterais no mundo real se beneficiam de manter o loop de orquestração dentro do código da aplicação, onde barreiras de proteção e checkpoints de aprovação podem ser controlados com precisão.

Em vez de conceder ao modelo autoridade direta de execução, o pipeline de triagem é dividido em duas etapas bem definidas:

  1. Análise e Proposta (Execução da IA): O modelo processa a mensagem do usuário, envia por streaming o raciocínio interno e um rascunho de resposta, gerando uma chamada de ferramenta estruturada (tool call) com as ações sugeridas.
  2. Aprovação e Despacho (Execução da Aplicação): A aplicação interrompe o fluxo, armazena a proposta em uma fila de revisão e aguarda a confirmação de um operador humano antes de alterar o status do ticket ou enviar mensagens ao cliente.
Incoming Ticket ──> Node.js Service ──> OneMux Gateway ──> Model Inference
                                                                 │
                                                                 ▼
Ticket Updated  <── Support Agent  <── Review Queue  <── Proposed Actions
   (Execution)        (Approves)       (Intercepted)       & Draft Stream

Configurando o Node.js SDK: Base URL e Autenticação

O pacote npm oficial openai permite direcionar requisições para qualquer endpoint compatível modificando a propriedade baseURL. Você pode conferir os modelos disponíveis no catálogo de modelos OneMux para selecionar a opção mais adequada para geração de texto.

Primeiro, instale o pacote oficial:

npm install openai

Para apontar para o OneMux, inicialize a instância do cliente com a sua chave de API OneMux e a base URL https://api.onemux.net/v1:

import OpenAI from 'openai';

// Initialize the OpenAI client pointing to the OneMux gateway
const client = new OpenAI({
  apiKey: process.env.ONEMUX_API_KEY,
  baseURL: 'https://api.onemux.net/v1',
});

Verificando a Autenticação

Ao passar por um gateway, os padrões de falha de autenticação mudam ligeiramente. Se a sua chave de API estiver ausente, inválida ou sem saldo suficiente na plataforma, o cliente capturará um AuthenticationError (HTTP 401). Antes de rodar tarefas de triagem em produção, valide suas credenciais consultando o guia de início rápido do OneMux.


Implementando Streaming para Rascunho de Triagem em Tempo Real

Agentes de suporte têm uma experiência muito melhor ao visualizar os rascunhos de triagem de forma incremental, em vez de esperar a resposta completa ser finalizada. Ao chamar chat.completions.create com stream: true, o SDK retorna um stream assíncrono iterável baseado em Server-Sent Events (SSE).

A implementação a seguir transmite o rascunho de resposta para a saída padrão (ou para o dashboard interno do agente), enquanto captura simultaneamente as chamadas de ferramentas estruturadas para a categorização do chamado:

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.ONEMUX_API_KEY,
  baseURL: 'https://api.onemux.net/v1',
});

interface TriageProposal {
  draftResponse: string;
  category?: string;
  priority?: 'low' | 'medium' | 'high' | 'urgent';
  suggestedRefundAmount?: number;
}

export async function triageTicketStream(
  ticketId: string,
  customerMessage: string
): Promise<TriageProposal> {
  const tools: OpenAI.ChatCompletionTool[] = [
    {
      type: 'function',
      function: {
        name: 'propose_ticket_action',
        description: 'Propose triage tags, priority updates, or billing adjustments.',
        parameters: {
          type: 'object',
          properties: {
            category: {
              type: 'string',
              enum: ['billing', 'technical_bug', 'account_access', 'general'],
            },
            priority: {
              type: 'string',
              enum: ['low', 'medium', 'high', 'urgent'],
            },
            suggestedRefundAmount: {
              type: 'number',
              description: 'Refund amount in USD if the user experienced downtime.',
            },
          },
          required: ['category', 'priority'],
        },
      },
    },
  ];

  const stream = await client.chat.completions.create({
    model: 'gpt-4o',
    stream: true,
    tools,
    messages: [
      {
        role: 'system',
        content:
          'You are a support triage assistant. Analyze the ticket, stream a helpful draft reply for the customer, and call propose_ticket_action with triage metadata.',
      },
      {
        role: 'user',
        content: customerMessage,
      },
    ],
  });

  let draftResponse = '';
  let toolCallArguments = '';
  let toolName = '';

  for await (const chunk of stream) {
    const delta = chunk.choices[0]?.delta;

    // Stream conversational draft chunks
    if (delta?.content) {
      draftResponse += delta.content;
      process.stdout.write(delta.content);
    }

    // Accumulate tool call chunks
    if (delta?.tool_calls) {
      for (const toolCall of delta.tool_calls) {
        if (toolCall.function?.name) {
          toolName = toolCall.function.name;
        }
        if (toolCall.function?.arguments) {
          toolCallArguments += toolCall.function.arguments;
        }
      }
    }
  }

  let parsedAction = {};
  if (toolName === 'propose_ticket_action' && toolCallArguments) {
    try {
      parsedAction = JSON.parse(toolCallArguments);
    } catch (err) {
      console.error('Failed to parse tool call JSON payload:', err);
    }
  }

  return {
    draftResponse,
    ...parsedAction,
  };
}

O Gate de Aprovação Humana

A execução autônoma de tool calls pode resultar em reembolsos indevidos ou escalonamentos incorretos de prioridade. A aplicação deve persistir o objeto TriageProposal gerado em um estado intermediário — como um registro de banco de dados com status PENDING_APPROVAL — em vez de executar as ações imediatamente.

interface PendingReviewTicket {
  ticketId: string;
  status: 'PENDING_APPROVAL' | 'APPROVED' | 'REJECTED';
  proposal: TriageProposal;
}

// Step 1: Queue the proposal for human verification
async function queueForHumanReview(ticketId: string, proposal: TriageProposal) {
  console.log(`[Review Queue] Storing proposal for ticket ${ticketId}:`, proposal);
  // Persistence logic: await db.triageReviews.create({ ticketId, proposal, status: 'PENDING_APPROVAL' });
}

// Step 2: Human operator action handler
async function handleHumanDecision(
  reviewId: string,
  decision: 'APPROVE' | 'REJECT',
  modifiedProposal?: Partial<TriageProposal>
) {
  if (decision === 'REJECT') {
    console.log(`Review ${reviewId} rejected by operator.`);
    return;
  }

  // Execute business logic only after approval
  console.log(`Review ${reviewId} approved. Executing refund and priority assignment...`);
  // e.g., await paymentGateway.issueRefund(modifiedProposal.suggestedRefundAmount);
}

Essa separação assegura que, mesmo se o modelo classificar erroneamente uma dúvida trivial como urgente ou sugerir um crédito desnecessário, um operador humano interceptará a ação antes de sua efetivação.


Diagnóstico de Erros: Diferenciando Erros de Cliente, Gateway e Upstream

Ao utilizar um gateway compatível com a OpenAI como o OneMux, as falhas podem ter três origens: o código da sua aplicação local, o proxy do gateway ou o provedor do modelo upstream. Inspecionar a instância padrão de APIError fornecida pelo SDK da openai ajuda a identificar a causa raiz com precisão:

import OpenAI from 'openai';

try {
  await triageTicketStream('ticket-101', 'System is down since morning!');
} catch (error) {
  if (error instanceof OpenAI.APIError) {
    console.error(`Status Code: ${error.status}`);
    console.error(`Error Message: ${error.message}`);
    console.error(`Error Code: ${error.code}`);
    console.error(`Error Type: ${error.type}`);

    switch (error.status) {
      case 401:
        console.error('Check your OneMux API key in environment variables.');
        break;
      case 402:
        console.error('Account balance exhausted. Top up credits in the dashboard.');
        break;
      case 429:
        console.error('Rate limit reached or concurrent request ceiling exceeded.');
        break;
      case 502:
      case 504:
        console.error('Upstream model provider timeout or network disruption via gateway.');
        break;
      default:
        console.error('Unhandled API exception.');
    }
  } else {
    console.error('Non-API runtime error:', error);
  }
}

Análise dos Códigos de Status Mais Comuns

Status HTTPCausa Raiz PrimáriaResolução Recomendada
401 UnauthorizedChave de API OneMux ausente ou inválida.Verifique a configuração de ONEMUX_API_KEY e o repasse de cabeçalhos.
402 Payment RequiredSaldo esgotado na conta.Revise o consumo e recarregue os créditos na página de preços OneMux.
429 Too Many RequestsLimite de taxa (rate limit) ou concorrência atingido.Implemente backoff exponencial ou solicite aumento de limites ao provedor.
500 Internal ErrorFalha no modelo upstream ou exceção não tratada no gateway.Verifique o status operacional do gateway e tente reenviar a requisição.
502 / 504 Bad GatewayGateway incapaz de alcançar o provedor upstream.Configure roteamento de fallback ou valide a disponibilidade do modelo na documentação do OneMux.

Limitações e Parâmetros Não Testados

Embora o OneMux ofereça compatibilidade direta para os endpoints padrão de chat completions da OpenAI (/v1/chat/completions), tenha em mente as seguintes restrições:

  1. Endpoints Beta Avançados: Endpoints fora do escopo central de chat, embeddings e completions — como ambientes sandboxed específicos ou primitivas gerenciadas de runtime da Assistants API detalhadas na documentação da OpenAI — dependem de suporte explícito do gateway. Confirme a disponibilidade na documentação do gateway antes de implantar.
  2. Repasse de Headers Customizados: Cabeçalhos personalizados de organização ou projeto (OpenAI-Organization, OpenAI-Project) podem ser ignorados ou tratados de forma diferente pelas camadas de proxy. Certifique-se de que o token de autenticação seja enviado via cabeçalho padrão Bearer.
  3. Gerenciamento de Estado: Caso planeje migrar da Assistants API hospedada na OpenAI para um loop de agente controlado na aplicação, sua aplicação Node.js será responsável por manter o histórico e a persistência da sessão.

Conclusão

Migrar uma aplicação Node.js existente que usa o OpenAI SDK para um gateway compatível é um processo simples: basta atualizar a baseURL, definir a chave de API do gateway e ajustar os logs de erro para mapear os status específicos do serviço. Ao desacoplar as propostas do modelo dos efeitos colaterais reais por meio de um gate de aprovação, seu pipeline de triagem de suporte ganha agilidade operacional sem abrir mão da segurança contra execuções indesejadas.


Fontes

Perguntas frequentes

Posso usar o SDK oficial da OpenAI para Node.js com o OneMux sem alterar minhas chamadas de métodos existentes?

Sim. Como o OneMux implementa uma API REST compatível com a OpenAI, você só precisa configurar a propriedade `baseURL` para `https://api.onemux.net/v1` e fornecer sua chave de API OneMux no construtor do cliente. Métodos como `client.chat.completions.create` continuam funcionando da mesma forma.

Como o streaming lida simultaneamente com tokens de texto e argumentos de tool calls?

Durante uma requisição em streaming, os chunks retornam deltas. Quando o modelo gera texto comum, `delta.content` contém os fragmentos streamed. Quando o modelo aciona uma função ou ferramenta, `delta.tool_calls` transmite o nome e pedaços incrementais da string JSON em `function.arguments`, que devem ser acumulados em buffer e analisados após o término do stream.

Por que um gate de aprovação humana é necessário em fluxos de triagem de suporte?

Modelos de IA podem interpretar incorretamente o tom do cliente ou alucinar regras operacionais. Inserir uma etapa de aprovação na aplicação entre as recomendações do modelo (como liberar estornos, alterar planos de faturamento ou fechar tickets de alta prioridade) e sua execução evita que decisões equivocadas cheguem diretamente ao usuário final.

O que minha aplicação deve fazer caso receba um erro HTTP 502 ou 504 através do gateway?

Erros 502 ou 504 geralmente indicam que o gateway sofreu timeout ou teve problemas de conectividade ao se comunicar com o provedor upstream do modelo. O ideal é implementar lógica de retentativa com backoff exponencial e jitter, ou configurar uma rota de fallback para um modelo secundário caso a alta disponibilidade seja indispensável.

Artigos relacionados