Guía práctica de decisiones de diseño poco aprovechadas que pueden mejorar considerablemente la calidad, la velocidad, el costo y la confiabilidad de tus despliegues.
Empieza siempre con la API Responses. Es la API principal de OpenAI y la mejor opción para acceder a los comportamientos más recientes de los modelos, las herramientas integradas, los flujos de trabajo con estado y las funciones para agentes.
Elige un modelo para tu carga de trabajo
Evalúa la familia de modelos GPT-6 con tu carga de trabajo. Usa gpt-6-astra cuando necesites la mayor capacidad, gpt-6.1-sol para tareas complejas de programación y trabajo profesional a un costo menor que el de Astra, y gpt-6-luna para ejecutar tareas repetibles de forma eficiente. Elige el modelo que dé buenos resultados en tareas representativas en lugar de enviar todas las solicitudes al modelo de mayor capacidad.
Al migrar a GPT-6, conserva la función que cumple tu modelo actual en la carga de trabajo y, si el nuevo modelo lo admite, el nivel efectivo de esfuerzo de razonamiento. Usa la API Responses para el razonamiento con herramientas. GPT-6 Astra y GPT-6.1 Sol requieren Responses para llamar a herramientas. En Chat Completions, GPT-6 Sol y GPT-6 Luna admiten llamadas a funciones solo con reasoning_effort: "none". Si el esfuerzo de razonamiento es distinto de none, elimina temperature, top_p y top_logprobs. Elimina también logprobs de las solicitudes de Chat Completions y message.output_text.logprobs del arreglo include de Responses. Comprueba qué modelos y funciones admiten la residencia de datos antes de elegir un modelo o un nivel de procesamiento. Consulta la guía de migración de modelos para conocer otras comprobaciones de compatibilidad. Ejecuta evaluaciones representativas antes de cambiar los prompts o agregar nuevas capacidades. Compara el éxito de las tareas, la latencia, la cantidad de tokens de entrada, de salida, de razonamiento y de escritura en caché, y el costo por tarea completada con éxito.
Configura reasoning.effort
Usa reasoning.effort para determinar cuánto debe razonar el modelo antes de responder.
GPT-6 Astra, GPT-6.1 Sol, GPT-6 Sol y GPT-6 Luna admiten low, medium, high, xhigh y max. GPT-6 Sol y GPT-6 Luna también admiten none, a diferencia de GPT-6 Astra y GPT-6.1 Sol. Con un esfuerzo menor, el modelo responde más rápido y usa menos tokens de razonamiento. Un esfuerzo mayor le da más tiempo para planificar, depurar, sintetizar información y sopesar opciones en varios pasos.
Usa low cuando el trabajo consista principalmente en extraer, enrutar o clasificar información, o en reescribir texto de manera rutinaria. Usa medium o high cuando el modelo necesite diagnosticar un problema, comparar opciones, elaborar un plan o razonar sobre código. Usa xhigh o max solo si las evaluaciones representativas indican que la mejora en la calidad justifica la latencia y el costo adicionales. Si migras desde minimal, o desde none a GPT-6 Astra o GPT-6.1 Sol, empieza con low y compara los resultados. En los demás casos, conserva el esfuerzo efectivo actual y comprueba si los cambios cumplen tus objetivos de calidad, latencia y costo.
Para las cargas de trabajo más difíciles en las que la calidad sea prioritaria, compara también reasoning.mode: "pro" con el modo estándar usando el mismo nivel de esfuerzo. El modo y el esfuerzo de razonamiento son independientes. El modo Pro puede mejorar la confiabilidad al permitir que el modelo trabaje más antes de devolver una única respuesta final, pero aumenta la latencia y el consumo de tokens.
Ajusta el esfuerzo de razonamiento según la tarea
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import OpenAI from "openai";const openai = new OpenAI();const prompt = [ "Our CI job started failing after a dependency bump.", "", "Error:", "TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'", "", "Identify the likeliest root cause and the smallest safe fix.",].join("\n");const response = await openai.responses.create({ model: "gpt-6-astra", reasoning: { effort: "xhigh", mode: "pro" }, input: prompt,});console.log(response.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from openai import OpenAIclient = OpenAI()prompt ="""Our CI job started failing after a dependency bump.Error:TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'Identify the likeliest root cause and the smallest safe fix."""response = client.responses.create(model="gpt-6-astra",reasoning={"effort": "xhigh", "mode": "pro"},input=prompt,)print(response.output_text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.core.JsonValue;import com.openai.models.Reasoning;import com.openai.models.ReasoningEffort;import com.openai.models.responses.ResponseCreateParams;ResponseCreateParams params = ResponseCreateParams.builder() .model("gpt-6-astra") .input( "Our CI job started failing after a dependency bump. Error: TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'. Identify the likeliest root cause and the smallest safe fix.") .reasoning( Reasoning.builder() .effort(ReasoningEffort.XHIGH) .putAdditionalProperty("mode", JsonValue.from("pro")) .build()) .build();client.responses().create(params).output().stream() .flatMap(item -> item.message().stream()) .flatMap(message -> message.content().stream()) .flatMap(content -> content.outputText().stream()) .forEach(text -> System.out.println(text.text()));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22require "openai"client = OpenAI::Client.newprompt = <<~PROMPT Our CI job started failing after a dependency bump. Error: TypeError: Timeout.__init__() got an unexpected keyword argument 'connect' Identify the likeliest root cause and the smallest safe fix.PROMPTresponse = client.responses.create( model: "gpt-6-astra", reasoning: { effort: :xhigh, mode: :pro }, input: prompt)puts(response.output_text)
Cambia el esfuerzo de razonamiento durante la conversación
Para cambiar el esfuerzo entre respuestas de un modelo GPT-6 en modo estándar con un solo agente, agrega un elemento de entrada configuration_update antes del siguiente mensaje del usuario. Conserva el valor de reasoning.effort de la solicitud para que el prefijo original del prompt se pueda seguir almacenando en caché. La actualización se aplica a partir de la siguiente respuesta y sigue vigente hasta que otra actualización la sustituya. Las actualizaciones de configuración son incompatibles con la compactación o el truncamiento automáticos, y /responses/compact rechaza los historiales que las contienen. Para compactar el historial, incluye un elemento compaction_trigger y agrega una nueva actualización después.
Configura text.verbosity
text.verbosity es el principal ajuste para equilibrar brevedad y exhaustividad. Usa un nivel de detalle bajo cuando el producto requiera una respuesta rápida y breve, y uno alto cuando la respuesta necesite una explicación más amplia, una estructura más clara o todo el contexto. Con un nivel de detalle bajo, el modelo genera menos tokens de salida y devuelve el resultado más rápido.
En tareas de programación, medium y high suelen producir respuestas más extensas, mejor organizadas y con una estructura más clara. Con low, la respuesta es más concisa y se limita a lo esencial.
Al migrar, comprueba si las instrucciones generales como “Sé breve” siguen siendo útiles. Da preferencia a text.verbosity para controlar el nivel de detalle predeterminado y usa el prompt para especificar el contenido, la estructura y la extensión que necesitas.
Reduce el nivel de detalle para obtener respuestas breves
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import OpenAI from "openai";const openai = new OpenAI();const incident = [ "Summarize this incident for the next on-call engineer.", "- checkout latency spiked from 220 ms to 4.8 s", "- only us-east-1 was affected", "- rollback is complete", "- likely trigger: cache stampede after deploy",].join("\n");const response = await openai.responses.create({ model: "gpt-6-astra", text: { verbosity: "low" }, input: incident,});console.log(response.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17from openai import OpenAIclient = OpenAI()response = client.responses.create(model="gpt-6-astra",text={"verbosity": "low"},input=""" Summarize this incident for the next on-call engineer. - checkout latency spiked from 220 ms to 4.8 s - only us-east-1 was affected - rollback is complete - likely trigger: cache stampede after deploy """,)print(response.output_text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package mainimport ( "context" "fmt" "strings" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/responses")func main() { client := openai.NewClient() incident := strings.Join([]string{ "Summarize this incident for the next on-call engineer.", "- checkout latency spiked from 220 ms to 4.8 s", "- only us-east-1 was affected", "- rollback is complete", "- likely trigger: cache stampede after deploy", }, "\n") response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", Text: responses.ResponseTextConfigParam{Verbosity: "low"}, Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(incident)}, }) if err != nil { panic(err) } fmt.Println(response.OutputText())}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.models.responses.ResponseCreateParams;import com.openai.models.responses.ResponseTextConfig;ResponseCreateParams params = ResponseCreateParams.builder() .model("gpt-6-astra") .input( "Summarize this incident for the next on-call engineer: checkout latency spiked from 220 ms to 4.8 s, only us-east-1 was affected, rollback is complete, and the likely trigger was a cache stampede.") .text(ResponseTextConfig.builder().verbosity(ResponseTextConfig.Verbosity.LOW).build()) .build();client.responses().create(params).output().stream() .flatMap(item -> item.message().stream()) .flatMap(message -> message.content().stream()) .flatMap(content -> content.outputText().stream()) .forEach(text -> System.out.println(text.text()));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18require "openai"client = OpenAI::Client.newincident = <<~INCIDENT Summarize this incident for the next on-call engineer. - checkout latency spiked from 220 ms to 4.8 s - only us-east-1 was affected - rollback is complete - likely trigger: cache stampede after deployINCIDENTresponse = client.responses.create( model: "gpt-6-astra", text: { verbosity: :low }, input: incident)puts(response.output_text)
Configura el parámetro phase del asistente
phase es una etiqueta de los mensajes del asistente en el historial de la conversación. Le indica al modelo si un mensaje anterior del asistente era un comentario intermedio sobre el trabajo en curso o la respuesta final. Usa phase: "commentary" para las actualizaciones de progreso, las notas previas a una llamada a una herramienta y otros mensajes intermedios. Usa phase: "final_answer" para la respuesta completa.
El asistente podría decir algo así:
Comentario del asistente sobre el trabajo en curso
1
2
3
4
5{"role": "assistant","phase": "commentary","content": "I'm checking the logs and comparing them to the last successful deploy."}
Ese mensaje informa sobre el progreso. La respuesta llega después. El asistente podría decir:
Respuesta final del asistente
1
2
3
4
5{"role": "assistant","phase": "final_answer","content": "The deploy failed because the migration referenced a column that does not exist in production."}
Esto resulta útil en flujos de trabajo prolongados o que usan muchas herramientas, en los que el asistente puede mostrar avances antes de terminar. Cuando vuelvas a enviar ese historial en solicitudes posteriores a gpt-5.3-codex o modelos más recientes, conserva y vuelve a enviar phase en los mensajes del asistente para que el modelo distinga los avances del resultado final. Así disminuye la probabilidad de que el agente se detenga antes de tiempo y aumenta la de que continúe hasta llegar a la respuesta final.
Usa tool_search
En lugar de cargar todo el catálogo de herramientas en cada solicitud, usa la búsqueda de herramientas. Agrega {"type": "tool_search"} y marca con defer_loading: true las definiciones que resulten costosas de cargar. Así, el modelo puede cargar solo las que necesite durante la ejecución. Al inicio de la solicitud, el modelo solo ve el nombre y la descripción de la herramienta de búsqueda. Si decide que necesita una herramienta de carga diferida, ejecuta la búsqueda. Solo entonces se cargan en el contexto las definiciones diferidas y el modelo puede llamar a esas herramientas. Esto ahorra tokens y conserva el rendimiento de la caché.
La búsqueda de herramientas tiene dos modos:
Búsqueda de herramientas alojada: es la opción más sencilla. Úsala cuando ya sepas qué herramientas podrían estar disponibles para la solicitud.
Búsqueda de herramientas ejecutada por el cliente: úsala cuando tu aplicación deba decidir qué herramientas están disponibles, por ejemplo, según el tenant, el proyecto o los permisos del usuario, o según un registro interno.
Empieza con la búsqueda de herramientas alojada, salvo que tu aplicación necesite controlar por sí misma cómo se descubren las herramientas.
Agrupa las herramientas según la intención del usuario. Usa un espacio de nombres o un servidor MCP cuando puedas. Al modelo le resulta más fácil elegir entre unos pocos grupos bien definidos que entre muchas funciones en una sola lista. Recomendamos mantener cada espacio de nombres por debajo de unas 10 funciones para optimizar el uso de tokens y el rendimiento del modelo.
Redacta descripciones breves que permitan distinguir los espacios de nombres. Incluye las instrucciones detalladas en las definiciones de las herramientas de carga diferida. Evita reunir todo en un único espacio de nombres enorme.
Usa la búsqueda alojada con herramientas de carga diferida
Las llamadas programáticas a herramientas permiten que los modelos compatibles escriban código JavaScript que llama a las herramientas admitidas y reduce el volumen de sus resultados intermedios en un entorno de ejecución alojado. Úsalas en etapas bien delimitadas en las que el código pueda filtrar, unir, ordenar por relevancia, eliminar duplicados, combinar o comprobar resultados extensos antes de devolver al modelo un resultado estructurado más pequeño.
Agrega la herramienta programmatic_tool_calling y habilita esta modalidad para cada herramienta compatible. Usa allowed_callers: ["programmatic"] para las herramientas que solo se llamen desde un programa, o allowed_callers: ["direct", "programmatic"] si el modelo también puede llamarlas directamente. Mantén las llamadas directas si cada resultado puede cambiar la siguiente decisión del modelo, si una acción requiere aprobación o si la respuesta final debe conservar citas o artefactos nativos. Documenta los campos que devuelve cada herramienta y su comportamiento ante errores para que el modelo pueda escribir un programa correcto sin tener que inspeccionar primero un resultado.
El bucle de ejecución de herramientas debe gestionar los elementos program y program_output, así como los elementos function_call que emita el programa y sus correspondientes elementos function_call_output. Conserva cada call_id y copia el campo caller de la llamada a la función en su salida para que el servicio pueda reanudar el programa correcto.
Verifica tanto program_output como el mensaje final del asistente. Aunque el programa devuelva el resultado correcto, la respuesta final podría estar incompleta. Compara el éxito de las tareas, la evidencia requerida, el total de tokens, la latencia y el costo con los del mismo flujo de trabajo usando llamadas directas.
Usa el modo multiagente para trabajar en paralelo
El modo multiagente permite que los modelos compatibles, incluidos los modelos GPT-6, deleguen partes independientes del trabajo a subagentes y sinteticen sus resultados. Úsalo cuando puedas dividir la investigación, el análisis o la implementación en tareas concretas y delimitadas que usen contextos separados y se ejecuten en paralelo.
Establece multi_agent.enabled en true en la solicitud. Para HTTP, usa el SDK beta de Responses con client.beta.responses y pasa responses_multi_agent=v1 en betas. Para conexiones HTTP directas o WebSocket, envía OpenAI-Beta: responses_multi_agent=v1. Los esquemas de los elementos pueden cambiar mientras el modo multiagente esté en beta.
Da preferencia a un solo agente para tareas breves, secuencias en las que cada paso dependa del anterior o trabajos que escriban en el mismo recurso mutable. Los subagentes pueden aumentar el consumo de tokens, así que empieza con el valor predeterminado de max_concurrent_subagents, que es 3, y mide la calidad, la latencia y el costo de principio a fin. En flujos multiagente prolongados o que usan muchas herramientas, el modo WebSocket puede reducir la sobrecarga que supone continuar la ejecución.
Antes de habilitar el modo multiagente, ten en cuenta sus limitaciones actuales: no admite /responses/compact, reasoning.summary ni max_tool_calls. El servidor compacta automáticamente el contexto raíz y el de cada subagente.
Usa llamadas asíncronas a herramientas
En los modelos GPT-6, configura async: true en una función o herramienta personalizada si el modelo puede seguir trabajando mientras tu aplicación la ejecuta. Inicia con anticipación las llamadas lentas y deja que el modelo se ocupe del trabajo independiente. Tu aplicación sigue siendo responsable de ejecutar la llamada y darle seguimiento. Luego devuelve el resultado en una solicitud posterior a Responses con el call_id original. La ejecución asíncrona no se aplica a las herramientas integradas ni a las llamadas programáticas a herramientas. En el modo multiagente, no combines herramientas asíncronas con llamadas en paralelo a herramientas. Consulta el flujo completo en Llamadas asíncronas a herramientas.
Aprovecha las herramientas integradas
Las herramientas integradas son capacidades nativas de la API. En lugar de crear cada herramienta por tu cuenta, puedes darle al modelo acceso a herramientas que ya funcionan dentro de la API Responses. El modelo puede decidir cuándo usarlas.
OpenAI sigue incorporando herramientas nativas, así que empieza con las herramientas integradas cuando se ajusten a tu flujo de trabajo. Crea herramientas personalizadas cuando las opciones nativas no cubran la tarea. Entre las herramientas integradas y las opciones relacionadas disponibles se encuentran las siguientes:
Búsqueda web: busca información actualizada en la web.
Búsqueda de archivos: busca en archivos cargados o en almacenes de vectores.
Intérprete de código: ejecuta Python para realizar análisis, hacer cálculos, crear gráficos y procesar archivos.
Shell: ejecuta comandos de shell en un contenedor alojado o en tu propio entorno de ejecución.
Uso de la computadora: interactúa con una interfaz mediante capturas de pantalla, clics, escritura y desplazamiento.
Generación de imágenes: genera o edita imágenes.
MCP/conectores: conecta el modelo a servicios y herramientas externos.
Habilidades: adjunta paquetes de instrucciones reutilizables y archivos de flujo de trabajo.
Aplicación de parches: realiza modificaciones estructuradas en el código.
La calidad del modelo es otra razón para darles preferencia. Las herramientas integradas forman parte de la distribución de datos que usamos en el posentrenamiento: entrenamos y evaluamos los modelos con los formatos, comportamientos y salidas de esas herramientas. Con las herramientas integradas, los modelos de OpenAI eligen mejor qué herramienta usar, la ejecutan con mayor precisión y fallan menos que con herramientas nuevas.
Aprovecha la compactación
La compactación es una herramienta de ingeniería de contexto que determina qué información conserva el modelo a lo largo de muchos turnos. En los agentes de larga duración, la cuestión va más allá de “¿Llegaré al límite de contexto?”. Los mensajes antiguos, los registros de herramientas, los reintentos y los detalles desactualizados ocupan el espacio que necesita el modelo para conservar el estado relevante.
La compactación permite reducir el tamaño del contexto de forma controlada y conservar el estado necesario para los siguientes turnos. Después de un avance importante, como terminar una etapa de depuración o acotar las posibles causas de un problema, puedes compactar la ventana de contexto anterior y continuar a partir del resultado. Así, el modelo mantiene el foco: el siguiente turno parte del estado relevante sin arrastrar cada paso intermedio del razonamiento, cada comando fallido y cada línea de razonamiento obsoleta.
Puedes usar la compactación de dos maneras:
Deja que el servidor se encargue: si usas previous_response_id, activa context_management con un compact_threshold. El servidor compactará automáticamente la conversación cuando crezca demasiado. Tú sigues enviando solo el mensaje más reciente del usuario.
Hazlo por tu cuenta: si administras todo el arreglo de entrada, llama a client.responses.compact(). Devuelve una ventana de contexto más pequeña. Usa esa salida directamente en la siguiente llamada a responses.create().
No edites la salida compactada. Contiene el estado de la máquina que permite al modelo continuar, en un formato distinto al de un resumen para lectores. Pásala tal como la recibiste y luego agrega el siguiente mensaje del usuario.
Continúa a partir del estado compactado de la respuesta
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import OpenAI from "openai";import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";const openai = new OpenAI();// Full window collected from a long debugging session:// user messages, assistant outputs, tool calls, and tool outputs.const longWindow = sessionItems;const compacted = await openai.responses.compact({ model: "gpt-6-astra", input: longWindow,});const nextResponse = await openai.responses.create({ model: "gpt-6-astra", store: false, input: [ // Preserve replayable compacted items. ...toResponseInputItems(compacted.output), { type: "message", role: "user", content: "We found the bad cache invalidation path. Write the fix plan " + "and the verification checklist.", }, ],});console.log(nextResponse.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30from openai import OpenAIclient = OpenAI()# Full window collected from a long debugging session:# user messages, assistant outputs, tool calls, and tool outputs.long_window = session_itemscompacted = client.responses.compact(model="gpt-6-astra",input=long_window,)next_response = client.responses.create(model="gpt-6-astra",store=False,input=[*compacted.output, # Use compact output as-is. {"type": "message","role": "user","content": ("We found the bad cache invalidation path. Write the fix plan ""and the verification checklist." ), }, ],)print(next_response.output_text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27require "openai"client = OpenAI::Client.newlong_window = [ { role: :user, content: "Find the cache invalidation bug in this debugging session." }]compacted = client.responses.compact( model: "gpt-6-astra", input: long_window)input = compacted.output.dupinput << { role: :user, content: "We found the bad cache invalidation path. Write the fix plan and the verification checklist."}response = client.responses.create( model: "gpt-6-astra", store: false, input: input)puts(response.output_text)
Optimiza el almacenamiento en caché de prompts
El almacenamiento en caché de prompts reduce automáticamente la latencia y el costo cuando las solicitudes reutilizan un mismo prefijo largo. Coloca primero las instrucciones, los ejemplos y el material de referencia que no cambian, y después el contenido dinámico específico de cada usuario. Mantén estables las definiciones de las herramientas y su orden, y agrega los turnos nuevos al final de la conversación sin reescribir el contexto anterior.
GPT-5.6 introdujo el almacenamiento explícito en caché de prompts. El almacenamiento implícito sigue siendo la opción predeterminada, pero los modelos GPT-5.6 y las familias posteriores también admiten puntos de corte explícitos y una política de caché para toda la solicitud. Si después de un prefijo estable viene un sufijo variable, agrega un prompt_cache_breakpoint explícito al final de la parte reutilizable. Establece prompt_cache_options.mode en explicit solo cuando la solicitud deba usar únicamente los puntos de corte que indiques, sin ningún punto de corte implícito. Los modelos anteriores siguen admitiendo únicamente el almacenamiento automático en caché de prompts.
En los modelos GPT-5.6 y las familias posteriores, la tarifa por escribir tokens en caché es 1,25 veces la tarifa por token de entrada sin caché. Registra cached_tokens y cache_write_tokens y compara el volumen de escrituras con el de las lecturas posteriores para medir el costo neto y ajustar la ubicación de los puntos de corte.
Usa una prompt_cache_key estable para las solicitudes que compartan un prefijo reutilizable. Esto ayuda a dirigir las solicitudes relacionadas a la misma caché y a optimizar la tasa de aciertos en modelos anteriores a GPT-5.6. Para los grupos con mucho tráfico, sigue las pautas para distribuir el tráfico entre más claves.
En GPT-5.6 y versiones posteriores, prompt_cache_key es opcional: puedes lograr tasas de aciertos óptimas sin ella. Puedes usarla para contabilizar por separado el uso de la caché por cliente, usuario o espacio de trabajo. Esto facilita explicar el consumo de tokens en caché y la facturación de cada grupo. Asigna una clave distinta a cada cliente y mantenla estable en las solicitudes relacionadas de ese cliente. Usar claves distintas también ayuda a evitar que un cliente sondee los aciertos de caché de otro. Consulta Cómo contabilizar por separado el uso de la caché con claves.
Contabiliza por separado el uso de la caché de un cliente
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import OpenAI from "openai";const openai = new OpenAI();const instructions = [ "You are the support agent for Acme.", "Follow the Acme support policy and escalation rubric.", "Use the same tone, safety rules, and tool plan for each ticket.",].join("\n");const response = await openai.responses.create({ model: "gpt-6-astra", prompt_cache_key: "tenant-acme-support-agent", instructions, input: "Summarize the current escalation for the on-call lead.",});console.log(response.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18from openai import OpenAIclient = OpenAI()instructions ="""You are the support agent for Acme.Follow the Acme support policy and escalation rubric.Use the same tone, safety rules, and tool plan for each ticket."""response = client.responses.create(model="gpt-6-astra",prompt_cache_key="tenant-acme-support-agent",instructions=instructions,input="Summarize the current escalation for the on-call lead.",)print(response.output_text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29package mainimport ( "context" "fmt" "strings" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/responses")func main() { client := openai.NewClient() instructions := strings.Join([]string{ "You are the support agent for Acme.", "Follow the Acme support policy and escalation rubric.", "Use the same tone, safety rules, and tool plan for each ticket.", }, "\n") response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", PromptCacheKey: openai.String("tenant-acme-support-agent"), Instructions: openai.String(instructions), Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Summarize the current escalation for the on-call lead.")}, }) if err != nil { panic(err) } fmt.Println(response.OutputText())}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.models.responses.ResponseCreateParams;ResponseCreateParams params = ResponseCreateParams.builder() .model("gpt-6-astra") .instructions( "You are the support agent for Acme.\n" + "Follow the Acme support policy and escalation rubric.\n" + "Use the same tone, safety rules, and tool plan for each ticket.") .input("Summarize the current escalation for the on-call lead.") .promptCacheKey("tenant-acme-support-agent") .build();client.responses().create(params).output().stream() .flatMap(item -> item.message().stream()) .flatMap(message -> message.content().stream()) .flatMap(content -> content.outputText().stream()) .forEach(text -> System.out.println(text.text()));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18using OpenAI.Responses;#pragma warning disable OPENAI001string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;ResponsesClient client = new(key);CreateResponseOptions options = new(){ Model = "gpt-6-astra", PromptCacheKey = "tenant-acme-support-agent", Instructions = "Follow the Acme support policy and escalation rubric.",};options.InputItems.Add( ResponseItem.CreateUserMessageItem("Summarize the current escalation for the on-call lead."));ResponseResult response = await client.CreateResponseAsync(options);Console.WriteLine(response.GetOutputText());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17require "openai"client = OpenAI::Client.newinstructions = <<~INSTRUCTIONS You are the support agent for Acme. Follow the Acme support policy and escalation rubric. Use the same tone, safety rules, and tool plan for each ticket.INSTRUCTIONSresponse = client.responses.create( model: "gpt-6-astra", prompt_cache_key: "tenant-acme-support-agent", instructions: instructions, input: "Summarize the current escalation for the on-call lead.")puts(response.output_text)
Usa reasoning.encrypted_content
Los modelos compatibles, incluidos los modelos GPT-6, pueden conservar el razonamiento entre llamadas. Usa reasoning.context: "all_turns" cuando los objetivos, los supuestos y las prioridades de la tarea se mantengan estables. Usa current_turn si el razonamiento previo ya no es pertinente y podría hacer que el modelo se aferre a un enfoque desactualizado. Si omites reasoning.context o lo estableces en auto, revisa el campo reasoning.context de la respuesta para confirmar qué modo se aplicó.
La persistencia del razonamiento solo funciona cuando están disponibles los elementos de razonamiento anteriores. Usa previous_response_id para las respuestas almacenadas. Si tus requisitos de retención cero de datos (ZDR) impiden almacenar datos de las respuestas, el contenido de razonamiento cifrado permite transferir el razonamiento sin mantener estado en el servidor.
Los elementos de razonamiento en la salida de la respuesta incluyen contenido de razonamiento cifrado de forma predeterminada. Puedes acceder a él mediante la propiedad encrypted_content de cada elemento de razonamiento. Tu aplicación no necesita interpretar ese valor. Basta con que conserve cada elemento tal como lo recibe y lo vuelva a enviar en el siguiente turno para que el modelo pueda continuar el flujo de trabajo.
Pasa el razonamiento cifrado entre turnos sin estado
Ajusta el nivel de detalle de las imágenes según la tarea
El parámetro detail de las imágenes tiene el valor predeterminado auto. La forma en que se ajusta el tamaño depende del modelo. Las imágenes grandes pueden consumir más tokens de entrada y aumentar la latencia. Consulta la tabla de tamaños de imagen por modelo y, antes del despliegue, mide el consumo de tokens de imagen y verifica los límites con el modelo elegido.
Elige el valor de detail según la tarea. Ajusta el tamaño de la imagen, usa low si los detalles visuales finos son poco importantes o usa high para el análisis estándar de imágenes con alta fidelidad. En los modelos compatibles, usa original si el detalle adicional mejora la calidad al trabajar con imágenes grandes o densas, o en tareas de precisión de coordenadas, OCR, localización o inspección visual. Antes del despliegue, mide el consumo de tokens de imagen y la latencia en el peor de los casos.
Envía un identificador de seguridad
Si tu aplicación atiende a usuarios finales individuales, envía con cada solicitud un safety_identifier estable que proteja su privacidad. Esto ayuda a OpenAI a detectar usos indebidos y le da a tu equipo una forma estable de rastrear infracciones de las políticas. También reduce la probabilidad de que el uso indebido por parte de un usuario interrumpa el acceso del resto de la organización.
Aplica una función hash al nombre de usuario o a la dirección de correo electrónico en lugar de enviar información que identifique al usuario. Si el usuario no inició sesión, usa un ID de sesión estable.
Gestiona el monitoreo de desalineación
En los flujos de trabajo con agentes que usen GPT-6 Astra, ten en cuenta el monitoreo de desalineación. Si una solicitud devuelve 403 con misalignment_policy_violation, deja de enviar acciones para esa conversación y no reintentes automáticamente el flujo bloqueado. Gestiona también los errores durante la transmisión y revisa las acciones que podrían haberse ejecutado. Suscríbete a safety.alert.created si tu equipo necesita alertas del proyecto. El webhook no sustituye la gestión de errores de las solicitudes. Consulta en la guía qué solicitudes de Responses se pueden detener automáticamente.
Gestiona los aumentos rápidos de tráfico y la sobrecarga del modelo
Revisa el estado HTTP y error.code antes de decidir cómo recuperarte del error. Un 429 con slow_down indica que la frecuencia de las solicitudes aumentó demasiado rápido: respeta Retry-After si está presente, reduce el tráfico y luego auméntalo gradualmente. Un 503 con server_is_overloaded indica que el modelo solicitado está temporalmente sobrecargado: respeta Retry-After si está presente y luego vuelve a intentarlo. Si falta el encabezado, aumenta exponencialmente la espera entre reintentos con una variación aleatoria y limita el número de reintentos. Los errores de facturación, gasto y cuota requieren que tomes medidas antes de reintentar. No interpretes todos los errores 429 como un límite de solicitudes temporal. Consulta los límites de solicitudes y los códigos de error.
Usa background=True
Usa background=True para solicitudes que puedan tardar mucho tiempo. En lugar de mantener abierta la conexión del cliente, la API inicia un trabajo y devuelve un ID. Tu aplicación puede consultar periódicamente el estado del trabajo hasta que termine, falle o se cancele. Usa esta opción para análisis extensos, ejecuciones prolongadas de herramientas o trabajos que requieran seguimiento del estado y reintentos.
Ejecuta una respuesta en segundo plano y consulta su estado
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// Replace the illustrative IDs and URLs below with your own resource values.import OpenAI from "openai";const openai = new OpenAI();const logBundleFileId = "file_123";let job = await openai.responses.create({ model: "gpt-6-astra", background: true, store: false, input: "Analyze this large log bundle and cluster the primary failure modes.", tools: [ { type: "code_interpreter", container: { type: "auto", file_ids: [logBundleFileId], }, }, ],});while (["queued", "in_progress"].includes(job.status)) { await new Promise((resolve) => setTimeout(resolve, 2000)); job = await openai.responses.retrieve(job.id);}console.log(job.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28# Replace the illustrative IDs and URLs below with your own resource values.from openai import OpenAIimport timeclient = OpenAI()log_bundle_file_id ="file_123"job = client.responses.create(model="gpt-6-astra",background=True,store=False,input="Analyze this large log bundle and cluster the primary failure modes.",tools=[ {"type": "code_interpreter","container": {"type": "auto","file_ids": [log_bundle_file_id], }, } ],)while job.status in {"queued", "in_progress"}: time.sleep(2) job = client.responses.retrieve(job.id)print(job.output_text)
Puedes combinar esta opción con stream=True para recibir eventos de progreso, aunque el primer evento puede tardar más en llegar que en una solicitud normal.
Desde la perspectiva de la interfaz, el modo en segundo plano indica: “La tarea está en curso. Aquí puedes ver su estado y aquí aparecerá el resultado cuando esté listo”.
Usa el modo WebSocket
El modo WebSocket está diseñado para flujos de trabajo prolongados con muchas llamadas a herramientas. Mantienes abierta una conexión persistente y, para continuar, envías solo los elementos de entrada nuevos junto con previous_response_id. En flujos con 20 llamadas a herramientas o más, hemos observado ejecuciones de principio a fin hasta un 40 % más rápidas, aproximadamente.
Cómo funciona: el primer mensaje se parece a una solicitud normal de Responses e incluye el modelo, las instrucciones, las herramientas y la entrada del usuario. El servidor transmite los eventos de respuesta. Si el modelo solicita una herramienta, tu aplicación la ejecuta. Luego, en lugar de enviar una nueva solicitud HTTP, envías otro evento response.create por el mismo socket con el previous_response_id correspondiente a la respuesta anterior y el elemento nuevo. Así se reduce la latencia. Con HTTP convencional, cada paso posterior requiere una solicitud nueva. En el modo WebSocket, la conexión permanece abierta y mantiene en memoria el estado de la respuesta más reciente. Cuando el turno siguiente continúa a partir de esa respuesta, el servicio necesita menos trabajo de preparación.
Si tu flujo consiste en una sola solicitud y una sola respuesta, sigue usando HTTP. Si funciona como un agente de larga duración, prueba el modo WebSocket.
Usa valores distintos de stream_id para las conversaciones paralelas en una misma conexión y dirige los eventos intercalados según su stream_id. Una conexión admite hasta 16 respuestas activas, mientras que las solicitudes de un mismo flujo se ejecutan en orden. Las conexiones duran hasta 60 minutos. Para continuar, previous_response_id funciona igual que en el modo HTTP, con una caché local de la conexión para la última respuesta de cada flujo.
Nota: el modo WebSocket es compatible con ZDR porque tus datos se conservan solo en memoria, sin escribirse en disco.
El ejemplo de Python usa pip install "openai[realtime]>=3.8.0".
El ejemplo de JavaScript usa npm install openai@^7.10.0 ws.
El ejemplo de Ruby usa gem install openai async-websocket.
Para Go, ejecuta go get github.com/openai/openai-go/v3@v3.98.0.
Para Java, agrega la dependencia de Maven com.openai:openai-java:4.101.0.
Estas versiones de los SDK de Go y Java ofrecen compatibilidad nativa con WebSocket para Responses.
Inicia una sesión WebSocket con la API Responses
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76import OpenAI from "openai";import { ResponsesWS } from "openai/resources/responses/ws";const testLogTool = { type: "function", name: "search_test_logs", description: "Search test logs for a query.", parameters: { type: "object", properties: { query: { type: "string" } }, required: ["query"], additionalProperties: false, }, strict: true,};const codeSearchTool = { type: "function", name: "search_code", description: "Search the codebase for a query.", parameters: { type: "object", properties: { query: { type: "string" } }, required: ["query"], additionalProperties: false, }, strict: true,};const openai = new OpenAI();const ws = new ResponsesWS(openai);try { ws.send({ type: "response.create", model: "gpt-6-astra", store: false, input: [ { type: "message", role: "user", content: [ { type: "input_text", text: "Find the flaky test in this run, call the tools you need, " + "and keep going until you can explain the root cause.", }, ], }, ], tools: [testLogTool, codeSearchTool], }); let completed = false; for await (const event of ws) { if (event.type === "error") throw event.error; if (event.type !== "message") continue; const message = event.message; if (message.type === "response.completed") { console.log(JSON.stringify(message.response.output)); completed = true; break; } if ( message.type === "response.failed" || message.type === "response.incomplete" ) { throw new Error(JSON.stringify(message)); } } if (!completed) { throw new Error("Connection closed before the response finished."); }} finally { ws.close();}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61from openai import OpenAIfrom openai.types.responses import FunctionToolParamtest_log_tool: FunctionToolParam = {"type": "function","name": "search_test_logs","description": "Search test logs.","parameters": {"type": "object","properties": {"query": {"type": "string"}},"required": ["query"],"additionalProperties": False, },"strict": True,}code_search_tool: FunctionToolParam = {"type": "function","name": "search_code","description": "Search source code.","parameters": {"type": "object","properties": {"query": {"type": "string"}},"required": ["query"],"additionalProperties": False, },"strict": True,}client = OpenAI()with client.responses.connect() as connection:# Use the same typed parameters as client.responses.create(...). connection.response.create(model="gpt-6-astra",store=False,input=[ {"type": "message","role": "user","content": [ {"type": "input_text","text": ("Find the flaky test in this run, call the tools ""you need, and keep going until you can explain ""the root cause." ), } ], } ],tools=[test_log_tool, code_search_tool], )for event in connection:if event.type =="response.completed":print(event.response.output)breakif event.type in {"response.failed", "response.incomplete", "error"}:raiseRuntimeError(event.to_json())else:raiseRuntimeError("Connection closed before the response finished.")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.core.JsonValue;import com.openai.models.responses.*;import java.util.*;var tools = new ArrayList<Tool>();for (var name : List.of("search_test_logs", "search_code")) tools.add( Tool.ofFunction( FunctionTool.builder() .name(name) .description("Search for a query.") .strict(true) .parameters( FunctionTool.Parameters.builder() .putAdditionalProperty("type", JsonValue.from("object")) .putAdditionalProperty( "properties", JsonValue.from(Map.of("query", Map.of("type", "string")))) .putAdditionalProperty("required", JsonValue.from(List.of("query"))) .putAdditionalProperty("additionalProperties", JsonValue.from(false)) .build()) .build()));try (var conn = client.responses().connect()) { conn.send( ResponsesClientEvent.ofResponseCreate( ResponsesClientEvent.ResponseCreate.builder() .model("gpt-6-astra") .store(false) .input( "Find the flaky test in this run, call the tools you need, and keep going until you can explain the root cause.") .tools(tools) .build())); var response = conn.finalResponse(); if (response.status().filter(ResponseStatus.COMPLETED::equals).isEmpty()) throw new IllegalStateException( "Response ended with status " + response.status().orElse(null)); System.out.println(response.output());}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58require "async"require "openai"require "json"def wait_for_response(connection) while (event = connection.receive) case event.type.to_s when "response.completed" then return event.response when "response.failed", "response.incomplete", "error" raise "Response failed: #{event.to_json}" end end raise "Connection closed before the response finished"endtest_log_tool = { type: "function", name: "search_test_logs", description: "Search test logs.", parameters: { type: "object", properties: { query: { type: "string" } }, required: ["query"], additionalProperties: false }, strict: true}code_search_tool = { type: "function", name: "search_code", description: "Search source code.", parameters: { type: "object", properties: { query: { type: "string" } }, required: ["query"], additionalProperties: false }, strict: true}client = OpenAI::Client.newSync do |task| task.with_timeout(120) do client.responses.connect(request_options: { timeout: 10 }) do |connection| connection.response.create( stream_id: "main", model: "gpt-6-astra", store: false, input: [ { role: "user", content: "Find the flaky test in this run, call the tools you need, and keep going until you can explain the root cause." } ], tools: [test_log_tool, code_search_tool] ) puts(JSON.pretty_generate(wait_for_response(connection).output.map(&:to_h))) end endend
Ajusta las instrucciones durante el turno
Si los usuarios pueden agregar requisitos mientras un modelo GPT-6 está trabajando, usa una conexión WebSocket a la API Responses. Envía response.steer con el ID de la respuesta activa en previous_response_id y la nueva entrada del usuario. Sigue leyendo los eventos para recibir la continuación. El evento response.steer.accepted indica que la actualización está en la cola. Ajustar las instrucciones no modifica la salida que ya recibió tu aplicación ni revierte las ejecuciones de herramientas que ya comenzaron. Consulta cómo ajustar las instrucciones durante el turno para conocer el flujo de eventos y cómo gestionar los resultados de las herramientas.
Conclusión
La API Responses es la base para crear aplicaciones de OpenAI más inteligentes y capaces. Su principal ventaja es que permite pasar de prompts aislados a flujos de trabajo duraderos que usan herramientas, tienen en cuenta el contexto y se adaptan a la complejidad de la tarea. Sigue esta guía para mejorar el rendimiento en despliegues reales.