Migración de una aplicación Node.js con el SDK de OpenAI: Base URL, streaming y triaje con intervención humana
Aprende a migrar una aplicación Node.js existente con el SDK de OpenAI hacia una pasarela compatible como OneMux, gestionar streaming, diagnosticar errores y diseñar un flujo de triaje de soporte con aprobación humana.
En esta página
Migrar una aplicación Node.js en producción desde los endpoints directos de OpenAI hacia un proxy o pasarela unificada compatible no requiere reescribir la lógica principal del sistema. Gracias a que la librería oficial openai para Node.js expone configuraciones a nivel de cliente para modificar los orígenes de red y los encabezados, es posible redirigir el tráfico, auditar el consumo y aprovechar rutas alternativas sin sustituir el SDK.
Sin embargo, canalizar peticiones a través de una pasarela introduce ciertos factores operativos: administrar cabeceras de autenticación, procesar eventos de streaming sobre HTTP, diagnosticar errores en el perímetro y garantizar que las respuestas autónomas permanezcan bajo supervisión humana. En el triaje de atención al cliente —donde un modelo clasifica incidencias entrantes, redacta respuestas preliminares y propone acciones sobre los tickets—, validar las operaciones críticas mediante revisión humana resulta indispensable.
Esta guía muestra cómo reconfigurar el SDK de OpenAI en Node.js para trabajar con una pasarela compatible con OpenAI como OneMux, procesar propuestas de triaje en streaming e incorporar un control de aprobación humana antes de ejecutar acciones de alto impacto.
Arquitectura: triaje de soporte con aprobación humana
El triaje automatizado de soporte técnico implica procesar un ticket entrante, evaluar el sentimiento del usuario, clasificar la urgencia y proponer los siguientes pasos (como redactar una respuesta, añadir etiquetas o emitir una compensación parcial). Como se describe en la OpenAI Agents Guide, las arquitecturas de agentes que generan efectos secundarios en el mundo real se benefician de mantener el ciclo de orquestación dentro del código de la aplicación, donde se pueden aplicar salvaguardas y puntos de control de aprobación.
En lugar de conceder al modelo permisos de ejecución directa, la canalización de triaje se divide en dos fases bien diferenciadas:
- Análisis y propuesta (ejecución del modelo): El modelo procesa el mensaje del usuario, emite en streaming su razonamiento interno junto con un borrador de respuesta y genera una llamada estructurada a herramientas (tool call) con las acciones recomendadas.
- Aprobación y despacho (ejecución de la aplicación): La aplicación detiene el flujo de trabajo, almacena la propuesta en una cola de revisión y aguarda la confirmación de un agente humano antes de actualizar el estado del ticket o contactar al cliente.
Incoming Ticket ──> Node.js Service ──> OneMux Gateway ──> Model Inference
│
▼
Ticket Updated <── Support Agent <── Review Queue <── Proposed Actions
(Execution) (Approves) (Intercepted) & Draft Stream
Configuración del SDK de Node.js: Base URL y autenticación
El paquete oficial de npm openai permite redirigir las solicitudes a cualquier endpoint compatible modificando la propiedad baseURL. Puedes explorar los modelos disponibles en el catálogo de modelos de OneMux para seleccionar el modelo de completado idóneo.
En primer lugar, instala el paquete oficial:
npm install openai
Para apuntar a OneMux, inicializa la instancia del cliente con tu API key de OneMux y la URL base 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',
});
Verificación de la autenticación
Al enrutar el tráfico mediante una pasarela, los patrones de fallo en la autenticación presentan matices concretos. Si la clave de API no se envía, no es válida o la cuenta no dispone de saldo suficiente en la plataforma, el cliente capturará un error AuthenticationError (HTTP 401). Antes de desplegar procesos de triaje en entornos de producción, comprueba tus credenciales consultando la guía de inicio rápido de OneMux.
Implementación de streaming para la redacción de triaje en tiempo real
Los agentes de soporte obtienen una mejor experiencia cuando visualizan los borradores de triaje conforme se generan, en lugar de esperar a que se resuelva la carga útil completa. Al invocar chat.completions.create con el parámetro stream: true, el SDK devuelve un flujo iterable asíncrono compuesto por Server-Sent Events (SSE).
La siguiente implementación envía el borrador de respuesta a la salida estándar (o al panel interno del agente) en streaming mientras captura las llamadas estructuradas a herramientas para la categorización del triaje:
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,
};
}
La barrera de aprobación humana
Permitir la ejecución autónoma de llamadas a herramientas puede provocar reembolsos indebidos o escalados de prioridad injustificados. La aplicación debe almacenar el objeto TriageProposal generado en un estado intermedio —por ejemplo, un registro en base de datos con el estado PENDING_APPROVAL— en lugar de ejecutar las acciones inmediatamente.
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);
}
Esta separación asegura que, incluso si el modelo clasifica erróneamente una consulta rutinaria como urgente o sugiere una compensación no aplicable, un operador humano validará la acción antes de su ejecución.
Diagnóstico de errores: diferenciación entre errores del cliente, la pasarela y el proveedor ascendente
Al utilizar una pasarela compatible con OpenAI como OneMux, los incidentes pueden tener tres orígenes distintos: el código local de la aplicación, el proxy de la pasarela o el proveedor del modelo subyacente. Inspeccionar la instancia estándar APIError del SDK de openai permite aislar la causa raíz con precisión:
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);
}
}
Desglose de códigos de estado comunes
| Código de estado HTTP | Causa raíz principal | Corrección recomendada |
|---|---|---|
| 401 Unauthorized | Clave de API de OneMux ausente o inválida. | Verifica la variable ONEMUX_API_KEY y el reenvío de encabezados. |
| 402 Payment Required | Saldo de la cuenta agotado. | Revisa el consumo y recarga saldo en los precios de OneMux. |
| 429 Too Many Requests | Límite de tasa (rate limit) o concurrencia excedido. | Implementa retroceso exponencial (exponential backoff) o incrementa los límites asignados. |
| 500 Internal Error | Error en el modelo ascendente o excepción no controlada en la pasarela. | Consulta el estado del servicio de la pasarela y reintenta la solicitud. |
| 502 / 504 Bad Gateway | La pasarela no logra comunicarse con el proveedor ascendente. | Configura rutas alternativas de respaldo o confirma la disponibilidad del modelo en la documentación de OneMux. |
Limitaciones y parámetros no probados
Aunque OneMux ofrece compatibilidad directa con los endpoints estándar de chat completions de OpenAI (/v1/chat/completions), conviene considerar las siguientes limitaciones:
- Endpoints beta avanzados: Las funciones fuera de chat, embeddings y completions convencionales —como entornos sandbox alojados específicos o primitivas del runtime de asistentes administrados descritas en la documentación de OpenAI— requieren soporte explícito por parte de la pasarela. Comprueba la disponibilidad del endpoint en la documentación de la pasarela antes de desplegar.
- Paso de cabeceras personalizadas: Los encabezados personalizados de organización o proyecto (
OpenAI-Organization,OpenAI-Project) pueden ser ignorados o interpretados de forma distinta por las capas intermedias de proxy. Asegúrate de transmitir el token de autenticación mediante el esquema estándarBearer. - Gestión del estado: Si planeas migrar desde la API administrada de OpenAI Assistants hacia un bucle de agentes controlado por la aplicación, tu servicio en Node.js deberá encargarse del almacenamiento y la persistencia del historial de las sesiones.
Conclusión
Migrar una aplicación Node.js basada en el SDK de OpenAI a una pasarela compatible implica un esfuerzo mínimo: actualiza el parámetro baseURL, proporciona la clave de API correspondiente de la pasarela y adapta el registro de errores para procesar los códigos de estado propios del servicio intermedio. Al desacoplar las propuestas generadas por el modelo de los efectos secundarios reales mediante una barrera de aprobación, tu sistema de triaje de atención al cliente conservará su agilidad operativa minimizando el riesgo de acciones no deseadas.
Fuentes
- OpenAI Agents Guide: https://developers.openai.com/api/docs/guides/agents
- OneMux Developer Documentation: https://onemux.net/docs
FAQ
¿Puedo utilizar el SDK oficial de OpenAI para Node.js con OneMux sin modificar mis llamadas a los métodos existentes?
Sí. Como OneMux ofrece una API REST compatible con OpenAI, solo necesitas configurar `baseURL` hacia `https://api.onemux.net/v1` y suministrar tu API key de OneMux en el constructor del cliente. Métodos habituales como `client.chat.completions.create` operan con total normalidad.
¿Cómo procesa el streaming tanto los tokens de texto como los argumentos de una llamada a herramienta de forma simultánea?
Durante una petición en streaming, las partes emitidas contienen deltas. Cuando el modelo genera texto regular, este viaja en `delta.content`. Si el modelo activa una función o herramienta, `delta.tool_calls` transmite el nombre y fragmentos incrementales de la cadena JSON dentro de `function.arguments`, los cuales deben acumularse en un búfer y parsearse una vez concluido el flujo.
¿Por qué es fundamental una barrera de aprobación humana en los flujos de triaje de soporte?
Los modelos de lenguaje pueden malinterpretar el tono de un cliente o alucinar directrices internas. Establecer una compuerta de validación a nivel de aplicación entre las sugerencias del modelo (como emitir abonos, modificar planes de suscripción o cerrar incidencias prioritarias) y su ejecución efectiva evita que los fallos del sistema automatizado alcancen a los usuarios finales.
¿Cómo debe reaccionar mi aplicación si recibe un error HTTP 502 o 504 a través de la pasarela?
Un error 502 o 504 generalmente refleja que la pasarela experimentó un tiempo de espera agotado o problemas de red al conectarse con el proveedor original del modelo. Lo recomendable es aplicar una lógica de reintentos con retroceso exponencial y variación aleatoria (jitter), o conmutar dinámicamente hacia un modelo de respaldo si el flujo requiere alta disponibilidad.
Artículos relacionados
Guides
Migración de aplicaciones Node.js con el SDK de OpenAI: Base URL, Streaming y Structured Outputs
Guía técnica para desarrolladores de Node.js sobre la migración de aplicaciones con el SDK de OpenAI: configuración de base URLs personalizadas, autenticación, streaming de structured outputs y diagnóstico de errores de API.
Guides
¿Qué es GPT-5.6 Terra? Una opción práctica para APIs de soporte en e-commerce
GPT-5.6 Terra es el modelo de gama media equilibrado de OpenAI. Descubre dónde encaja en un stack de soporte de e-commerce, cómo sus precios en OneMux transforman los costes unitarios y cómo implementar un enrutamiento seguro.
Guides
Encuentra tu modelo GPT-5.6 ideal para soporte al cliente: por qué Terra es perfecto
Descubre por qué GPT-5.6 Terra es el modelo ideal para soporte al cliente, equilibrando costo, velocidad y precisión. Compara con otros modelos y aprende cómo OneMux simplifica el acceso.
Guides
Crea un agente de atención al cliente con LangGraph, llamadas a herramientas, aprobación humana y límites de ejecución
Un patrón práctico de LangGraph para clasificar solicitudes de atención al cliente: dirigir solicitudes, llamar a herramientas de consulta, pausar los reembolsos para su aprobación humana y limitar la ejecución del grafo.