OpenAI Respuestas API

ADK-Rust proporciona un cliente dedicado para Respuestas API de OpenAI (endpoint /v1/responses), el sucesor de API de finalización de chat. API de Respuestas es la forma recomendada de utilizar los modelos actuales GPT-5.6, incluido todo su rango de esfuerzo de razonamiento.

Descripción general

┌─────────────────────────────────────────────────────────────────────┐
│                  OpenAI Responses API Client                        │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   Endpoint:  POST /v1/responses                                     │
│   Client:    OpenAIResponsesClient                                  │
│   Config:    OpenAIResponsesConfig                                  │
│   Feature:   openai                                                 │
│                                                                     │
│   Capabilities:                                                     │
│   • Streaming and non-streaming                                     │
│   • Reasoning summaries                                             │
│   • Tool / function calling                                         │
│   • Multi-turn via previous_response_id                             │
│   • Built-in tools (web search, file search, code interpreter)      │
│   • System instructions                                             │
│   • Model-aware sampling controls and max_output_tokens             │
│   • Automatic retry with exponential backoff                        │
│                                                                     │
│   vs Chat Completions (OpenAIClient):                               │
│   • Stateful conversations (server-side context)                    │
│   • Native reasoning summaries                                      │
│   • Built-in tool hosting                                           │
│   • Simpler multi-turn (no manual message history)                  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Cuándo usar cada cliente

FunciónOpenAIClient (Completado de chat)OpenAIResponsesClient (Respuestas)
Endpoint/v1/chat/completions/v1/responses
ModelosModelos compatibles con chatGPT actuales y modelos de razonamiento
Resúmenes del razonamientoNo disponibleCompatibilidad nativa
Herramientas integradasNo disponibleBúsqueda web, búsqueda de archivos, intérprete de código
Estado del lado del servidorHistorial de mensajes manualprevious_response_id
Salida estructuradaresponse_formattext.format (planificado)
MadurezEstable, ampliamente adoptadoMás reciente, recomendado por OpenAI

Usa OpenAIResponsesClient cuando necesites modelos de razonamiento con resúmenes, herramientas integradas o quieras utilizar la última API de OpenAI. Usa OpenAIClient para mantener la compatibilidad con los flujos de trabajo existentes de Chat Completions.


Instalación

[dependencies]
adk-rust = { version = "2.1.0", features = ["openai"] }
adk-tool = "2.1.0"

O directamente con adk-model:

[dependencies]
adk-model = { version = "2.1.0", features = ["openai"] }

Configura tu clave de API:

export OPENAI_API_KEY="sk-..."

Inicio rápido

use adk_rust::prelude::*;
use adk_rust::session::{CreateRequest, SessionService};
use adk_rust::futures::StreamExt;
use adk_model::openai::{OpenAIResponsesClient, OpenAIResponsesConfig};
use std::collections::HashMap;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    let api_key = std::env::var("OPENAI_API_KEY")?;

    // 1. Create the Responses API client
    let config = OpenAIResponsesConfig::new(&api_key, "gpt-5.6-terra");
    let model = Arc::new(OpenAIResponsesClient::new(config)?);

    // 2. Build an agent
    let agent = Arc::new(
        LlmAgentBuilder::new("assistant")
            .instruction("You are a helpful assistant. Be concise.")
            .model(model)
            .build()?,
    );

    // 3. Create a session
    let sessions: Arc<dyn SessionService> = Arc::new(InMemorySessionService::new());
    sessions.create(CreateRequest {
        app_name: "my_app".into(),
        user_id: "user".into(),
        session_id: Some("s1".into()),
        state: HashMap::new(),
    }).await?;

    // 4. Run through the Runner
    let runner = Runner::builder()
        .app_name("my_app")
        .agent(agent)
        .session_service(sessions)
        .build()?;

    let message = Content::new("user").with_text("What is the capital of France?");
    let mut stream = runner.run(
        adk_rust::UserId::new("user")?,
        adk_rust::SessionId::new("s1")?,
        message,
    ).await?;

    while let Some(event) = stream.next().await {
        let event = event?;
        if let Some(content) = &event.llm_response.content {
            for part in &content.parts {
                if let Some(text) = part.text() {
                    print!("{text}");
                }
            }
        }
    }
    println!();
    Ok(())
}

Configuración

Configuración básica

use adk_model::openai::OpenAIResponsesConfig;

// Minimal — just API key and model
let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-luna");

// With organization and project
let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-terra")
    .with_organization("org-...")
    .with_project("proj-...");

// Custom base URL (for proxies or compatible APIs)
let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-terra")
    .with_base_url("https://my-proxy.example.com/v1");

Modelos de razonamiento

Para los modelos de razonamiento GPT-5.6, configura el esfuerzo de razonamiento y el resumen:

use adk_model::openai::{
    OpenAIReasoningEffort, OpenAIResponsesClient,
    OpenAIResponsesConfig, ReasoningSummary,
};

let config = OpenAIResponsesConfig::new("sk-...", "gpt-5.6-terra")
    .with_reasoning_summary(ReasoningSummary::Detailed);

let model = OpenAIResponsesClient::new_with_reasoning_effort(
    config,
    OpenAIReasoningEffort::Max,
)?;
Esfuerzo de razonamientoDescripción
NoneDesactiva el razonamiento para obtener la menor latencia
MinimalRazonamiento mínimo heredado en modelos que lo admiten
LowBajo esfuerzo de razonamiento
MediumRazonamiento equilibrado
HighAlto esfuerzo de razonamiento
XHighEsfuerzo de razonamiento extremadamente alto
MaxRazonamiento máximo en modelos compatibles

GPT-5.6 admite None, Low, Medium, High, XHigh y Max mediante Responses API. Chat Completions admite hasta XHigh.

Resumen del razonamientoDescripción
AutoEl modelo decide si incluir un resumen
ConciseBreve resumen del razonamiento
DetailedResumen exhaustivo del razonamiento

Los resúmenes del razonamiento aparecen como Part::Thinking en el flujo de respuesta, lo que permite mostrar el proceso de pensamiento del modelo a los usuarios.

Configuración de reintentos

use adk_model::retry::RetryConfig;

let client = OpenAIResponsesClient::new(config)?
    .with_retry_config(RetryConfig {
        max_retries: 3,
        ..Default::default()
    });

Los reintentos son automáticos para los límites de frecuencia (429), los errores del servidor (500/502/503/504) y los fallos de red.


Modelos disponibles

ModeloTipoDescripción
gpt-5.6-terraRazonamientoOpción predeterminada equilibrada para agentes de producción
gpt-5.6-solRazonamientoRazonamiento y programación insignia
gpt-5.6-lunaRazonamientoFlujos de trabajo rentables y de gran volumen
gpt-5.6RazonamientoAlias insignia
gpt-5RazonamientoCompatibilidad con la generación anterior
gpt-4.1 familiaChatCompatibilidad y controles de muestreo explícitos
o3 / o4-miniRazonamientoCompatibilidad con el razonamiento de generaciones anteriores

Funcionalidades

Llamada de herramientas

Las herramientas de funciones funcionan igual que con OpenAIClient: define las herramientas en el agente y el ejecutor gestiona el ciclo de llamadas a herramientas:

use adk_rust::prelude::*;
use adk_model::openai::{OpenAIResponsesClient, OpenAIResponsesConfig};
use adk_tool::FunctionTool;
use std::sync::Arc;

async fn get_weather(
    _ctx: Arc<dyn ToolContext>,
    args: serde_json::Value,
) -> Result<serde_json::Value> {
    let city = args["city"].as_str().unwrap_or("unknown");
    Ok(serde_json::json!({
        "city": city,
        "temperature_f": 72,
        "conditions": "Sunny"
    }))
}

let weather_tool = FunctionTool::new(
    "get_weather",
    "Get current weather for a city. Requires a 'city' string parameter.",
    get_weather,
);

let config = OpenAIResponsesConfig::new(&api_key, "gpt-5.6-terra");
let model = Arc::new(OpenAIResponsesClient::new(config)?);

let agent = LlmAgentBuilder::new("weather_agent")
    .instruction("Use the get_weather tool to answer weather questions.")
    .model(model)
    .tool(Arc::new(weather_tool))
    .build()?;

Conversaciones de varios turnos

El ejecutor gestiona automáticamente el historial de la conversación mediante sesiones. Se conserva el contexto de cada turno:

// Turn 1
let msg1 = Content::new("user").with_text("My name is Alice.");
let mut stream = runner.run(uid.clone(), sid.clone(), msg1).await?;
// ... consume stream ...

// Turn 2 — the model remembers the previous turn
let msg2 = Content::new("user").with_text("What is my name?");
let mut stream = runner.run(uid.clone(), sid.clone(), msg2).await?;
// Response: "Your name is Alice."

Anulación del razonamiento por solicitud

Anula la configuración del razonamiento por solicitud mediante las extensiones de LlmRequest:

use adk_rust::prelude::*;

let agent = LlmAgentBuilder::new("flexible_reasoner")
    .model(model)
    .generate_content_config(GenerateContentConfig {
        extensions: {
            let mut ext = std::collections::HashMap::new();
            ext.insert("openai".to_string(), serde_json::json!({
                "reasoning": {
                    "effort": "high",
                    "summary": "detailed"
                }
            }));
            ext
        },
        ..Default::default()
    })
    .build()?;

Herramientas integradas

El cliente de Responses API admite herramientas alojadas en OpenAI. Se recomienda usar los envoltorios tipados de adk-tool:

use adk_tool::OpenAIWebSearchTool;
use std::sync::Arc;

let agent = LlmAgentBuilder::new("researcher")
    .model(model)
    .tool(Arc::new(OpenAIWebSearchTool::new().preview()))
    .build()?;

Los envoltorios disponibles incluyen OpenAIWebSearchTool, OpenAIFileSearchTool, OpenAICodeInterpreterTool, OpenAIImageGenerationTool, OpenAIComputerUseTool, OpenAIMcpTool, OpenAILocalShellTool, OpenAIShellTool y OpenAIApplyPatchTool.

ID de respuesta anterior

Para el estado de la conversación en el servidor (omitiendo el historial de sesión local), pasa previous_response_id:

let agent = LlmAgentBuilder::new("stateful")
    .model(model)
    .generate_content_config(GenerateContentConfig {
        extensions: {
            let mut ext = std::collections::HashMap::new();
            ext.insert("openai".to_string(), serde_json::json!({
                "previous_response_id": "resp_abc123"
            }));
            ext
        },
        ..Default::default()
    })
    .build()?;

Comportamiento de streaming

El cliente de Responses API transmite deltas de texto y razonamiento en tiempo real:

  • Los deltas de texto llegan como Part::Text con partial: true
  • Los deltas del resumen del razonamiento llegan como Part::Thinking con partial: true
  • Las llamadas a funciones se emiten desde el evento ResponseCompleted final, con los nombres y argumentos correctos
  • El evento final contiene turn_complete: true con los metadatos de uso y el motivo de finalización

Esto significa que ves cómo aparece el texto token a token mientras el modelo genera, y las llamadas a funciones llegan como objetos completos listos para ejecutarse.


Metadatos del proveedor

Cada respuesta incluye metadatos del proveedor con response_id:

if let Some(meta) = &response.provider_metadata {
    let response_id = meta["openai"]["response_id"].as_str();
    // Use for previous_response_id, logging, debugging
}

Los metadatos adicionales pueden incluir:

  • encrypted_content — de modelos de razonamiento (para conservar el contexto)
  • built_in_tool_outputs — resultados de búsqueda web, búsqueda de archivos e intérprete de código

Gestión de errores

Los errores se asignan a AdkError estructurados con las categorías correspondientes:

HTTP EstadoCategoría de errorReintentable
401UnauthorizedNo
429RateLimited
500, 502, 503, 504Unavailable
OtrosInternalNo
match runner.run(uid, sid, message).await {
    Ok(stream) => { /* process stream */ }
    Err(e) if e.is_retryable() => { /* retry logic */ }
    Err(e) if e.is_unauthorized() => { /* check API key */ }
    Err(e) => { /* handle other errors */ }
}

Modo en segundo plano y cancelación

Para solicitudes de larga duración, envíalas con background: true y consulta periódicamente su finalización:

use adk_model::openai::{OpenAIResponsesClient, OpenAIResponsesConfig};

let client = OpenAIResponsesClient::new(config)?;

// Submit with background: true via extensions
let mut gen_config = GenerateContentConfig::default();
gen_config.extensions.insert("openai".into(), serde_json::json!({ "background": true }));

// ... send request, extract response_id from provider_metadata ...

// Poll until terminal status
let response = client.poll_response("resp_abc123").await?;
// Check provider_metadata["openai"]["status"]: "completed", "in_progress", "failed", "cancelled"

// Cancel a running background response
let cancelled = client.cancel_response("resp_abc123").await?;

Los modelos de investigación profunda (o3-deep-research, o4-mini-deep-research) habilitan automáticamente el modo en segundo plano sin necesidad de especificar background: true.


Ejemplo

Hay disponible un ejemplo completo con 7 escenarios en examples/openai_responses/:

export OPENAI_API_KEY=sk-...
cargo run --manifest-path examples/openai_responses/Cargo.toml

Escenarios incluidos:

  1. Chat básico sin transmisión
  2. Chat básico con transmisión
  3. Modelo de razonamiento con resumen (ruta de compatibilidad con o4-mini)
  4. Llamadas a herramientas con herramientas de función
  5. Conversación de varios turnos
  6. Instrucciones del sistema
  7. Temperatura y configuración de generación (ruta de compatibilidad con gpt-4.1-nano)

Ejemplos adicionales

Seis crates de ejemplo independientes demuestran características específicas de Responses API:

EjemploEjecutar comandoFuncionalidad
WebSocket transportecargo run --manifest-path examples/openai_ws_minimal/Cargo.tomlConexión persistente de baja latencia
Modo en segundo planocargo run --manifest-path examples/openai_background/Cargo.tomlFlujo de envío y consulta
Conversaciones APIcargo run --manifest-path examples/openai_conversations/Cargo.tomlConversaciones de varios turnos gestionadas por el servidor
Herramientas integradascargo run --manifest-path examples/openai_builtin_tools/Cargo.tomlGeneración de imágenes, búsqueda web
Investigación profundacargo run --manifest-path examples/openai_deep_research/Cargo.tomlInvestigación automática en segundo plano
Respuestas abiertascargo run --manifest-path examples/openai_open_responses/Cargo.tomlPuntos de conexión independientes del proveedor


Anterior: ← Proveedores en la nube | Siguiente: Ollama (local) →

OpenAI Respuestas API - Documentación ADK-Rust | ADK-Rust