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ón | OpenAIClient (Completado de chat) | OpenAIResponsesClient (Respuestas) |
|---|---|---|
| Endpoint | /v1/chat/completions | /v1/responses |
| Modelos | Modelos compatibles con chat | GPT actuales y modelos de razonamiento |
| Resúmenes del razonamiento | No disponible | Compatibilidad nativa |
| Herramientas integradas | No disponible | Búsqueda web, búsqueda de archivos, intérprete de código |
| Estado del lado del servidor | Historial de mensajes manual | previous_response_id |
| Salida estructurada | response_format | text.format (planificado) |
| Madurez | Estable, ampliamente adoptado | Má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 razonamiento | Descripción |
|---|---|
None | Desactiva el razonamiento para obtener la menor latencia |
Minimal | Razonamiento mínimo heredado en modelos que lo admiten |
Low | Bajo esfuerzo de razonamiento |
Medium | Razonamiento equilibrado |
High | Alto esfuerzo de razonamiento |
XHigh | Esfuerzo de razonamiento extremadamente alto |
Max | Razonamiento 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 razonamiento | Descripción |
|---|---|
Auto | El modelo decide si incluir un resumen |
Concise | Breve resumen del razonamiento |
Detailed | Resumen 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
| Modelo | Tipo | Descripción |
|---|---|---|
gpt-5.6-terra | Razonamiento | Opción predeterminada equilibrada para agentes de producción |
gpt-5.6-sol | Razonamiento | Razonamiento y programación insignia |
gpt-5.6-luna | Razonamiento | Flujos de trabajo rentables y de gran volumen |
gpt-5.6 | Razonamiento | Alias insignia |
gpt-5 | Razonamiento | Compatibilidad con la generación anterior |
gpt-4.1 familia | Chat | Compatibilidad y controles de muestreo explícitos |
o3 / o4-mini | Razonamiento | Compatibilidad 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::Textconpartial: true - Los deltas del resumen del razonamiento llegan como
Part::Thinkingconpartial: true - Las llamadas a funciones se emiten desde el evento
ResponseCompletedfinal, con los nombres y argumentos correctos - El evento final contiene
turn_complete: truecon 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 Estado | Categoría de error | Reintentable |
|---|---|---|
| 401 | Unauthorized | No |
| 429 | RateLimited | Sí |
| 500, 502, 503, 504 | Unavailable | Sí |
| Otros | Internal | No |
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:
- Chat básico sin transmisión
- Chat básico con transmisión
- Modelo de razonamiento con resumen (ruta de compatibilidad con
o4-mini) - Llamadas a herramientas con herramientas de función
- Conversación de varios turnos
- Instrucciones del sistema
- 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:
| Ejemplo | Ejecutar comando | Funcionalidad |
|---|---|---|
| WebSocket transporte | cargo run --manifest-path examples/openai_ws_minimal/Cargo.toml | Conexión persistente de baja latencia |
| Modo en segundo plano | cargo run --manifest-path examples/openai_background/Cargo.toml | Flujo de envío y consulta |
| Conversaciones API | cargo run --manifest-path examples/openai_conversations/Cargo.toml | Conversaciones de varios turnos gestionadas por el servidor |
| Herramientas integradas | cargo run --manifest-path examples/openai_builtin_tools/Cargo.toml | Generación de imágenes, búsqueda web |
| Investigación profunda | cargo run --manifest-path examples/openai_deep_research/Cargo.toml | Investigación automática en segundo plano |
| Respuestas abiertas | cargo run --manifest-path examples/openai_open_responses/Cargo.toml | Puntos de conexión independientes del proveedor |
Relacionado
- Proveedores de modelos en la nube — Todos los proveedores de LLM compatibles
- Ollama (local) — Ejecutar modelos localmente
- LlmAgent — Usar modelos con agentes
- Herramientas de funciones — Añadir herramientas a los agentes
Anterior: ← Proveedores en la nube | Siguiente: Ollama (local) →