OpenAI Responses API

ADK-Rust fournit un client dédié aux Responses API de OpenAI (point de terminaison /v1/responses) — le successeur des API Chat Completions. Les API Responses constituent la méthode recommandée pour utiliser les modèles GPT-5.6 actuels, y compris toute leur plage d'efforts de raisonnement.

Vue d’ensemble

┌─────────────────────────────────────────────────────────────────────┐
│                  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)                  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Quand utiliser quel client

FonctionnalitéOpenAIClient (Chat Completions)OpenAIResponsesClient (Responses)
Point de terminaison/v1/chat/completions/v1/responses
ModèlesModèles compatibles avec le chatGPT actuels et modèles de raisonnement
Résumés du raisonnementNon disponiblePrise en charge native
Outils intégrésNon disponibleRecherche web, recherche de fichiers, interpréteur de code
État côté serveurHistorique manuel des messagesprevious_response_id
Sortie structuréeresponse_formattext.format (prévue)
MaturitéStable, largement adoptéPlus récent, recommandé par OpenAI

Utilisez OpenAIResponsesClient lorsque vous avez besoin de modèles de raisonnement avec des résumés, des outils intégrés, ou que vous souhaitez utiliser la dernière API de OpenAI. Utilisez OpenAIClient pour assurer la compatibilité avec les workflows Chat Completions existants.


Installation

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

Ou directement avec adk-model :

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

Définissez votre clé API :

export OPENAI_API_KEY="sk-..."

Démarrage rapide

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(())
}

Configuration

Configuration de base

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");

Modèles de raisonnement

Pour les modèles de raisonnement GPT-5.6, configurez l’effort et le résumé du raisonnement :

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,
)?;
Effort de raisonnementDescription
NoneDésactiver le raisonnement pour obtenir la latence la plus faible
MinimalRaisonnement minimal hérité sur les modèles qui le prennent en charge
LowFaible effort de raisonnement
MediumRaisonnement équilibré
HighEffort de raisonnement élevé
XHighEffort de raisonnement très élevé
MaxRaisonnement maximal sur les modèles pris en charge

GPT-5.6 prend en charge None, Low, Medium, High, XHigh et Max via les API de Responses. Chat Completions prend en charge jusqu’à XHigh.

Résumé du raisonnementDescription
AutoLe modèle décide s’il doit inclure un résumé
ConciseBref résumé du raisonnement
DetailedRésumé détaillé du raisonnement

Les résumés du raisonnement apparaissent sous la forme Part::Thinking dans le flux de réponses, ce qui vous permet d’afficher le processus de réflexion du modèle aux utilisateurs.

Configuration des nouvelles tentatives

use adk_model::retry::RetryConfig;

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

Les nouvelles tentatives sont automatiques en cas de limitations de débit (429), d’erreurs du serveur (500/502/503/504) et d’échecs réseau.


Modèles disponibles

ModèleTypeDescription
gpt-5.6-terraRaisonnementModèle par défaut équilibré pour les agents de production
gpt-5.6-solRaisonnementRaisonnement et programmation de pointe
gpt-5.6-lunaRaisonnementCharges de travail à haut volume et économiques
gpt-5.6RaisonnementAlias phare
gpt-5RaisonnementCompatibilité avec la génération précédente
gpt-4.1 familleConversationCompatibilité et contrôles explicites de l’échantillonnage
o3 / o4-miniRaisonnementCompatibilité avec le raisonnement des générations précédentes

Fonctionnalités

Appel d’outils

Les outils de fonction fonctionnent de la même manière qu’avec OpenAIClient — définissez les outils sur l’agent et le runner gère la boucle d’appel d’outil :

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()?;

Conversations multi-tours

Le Runner gère automatiquement l’historique des conversations via les sessions. Le contexte de chaque tour est conservé :

// 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."

Remplacement du raisonnement par requête

Remplacez les paramètres de raisonnement pour chaque requête à l’aide des extensions 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()?;

Outils intégrés

Le client Responses API prend en charge les outils hébergés par OpenAI. Préférez les wrappers typés 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()?;

Les wrappers disponibles comprennent OpenAIWebSearchTool, OpenAIFileSearchTool, OpenAICodeInterpreterTool, OpenAIImageGenerationTool, OpenAIComputerUseTool, OpenAIMcpTool, OpenAILocalShellTool, OpenAIShellTool et OpenAIApplyPatchTool.

Identifiant de réponse précédent

Pour l’état de conversation côté serveur (en contournant l’historique de session local), transmettez 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()?;

Comportement du streaming

Le client Responses API diffuse en temps réel les deltas de texte et de raisonnement :

  • Les deltas de texte arrivent sous la forme de Part::Text avec partial: true
  • Les deltas du résumé du raisonnement arrivent sous la forme de Part::Thinking avec partial: true
  • Les appels de fonction sont émis depuis l’événement ResponseCompleted final avec les noms et arguments corrects
  • L’événement final contient turn_complete: true avec les métadonnées d’utilisation et la raison de fin

Cela signifie que vous voyez le texte apparaître token par token pendant que le modèle génère, tandis que les appels de fonction arrivent sous forme d’objets complets prêts à être exécutés.


Métadonnées du fournisseur

Chaque réponse inclut des métadonnées du fournisseur avec le 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
}

Les métadonnées supplémentaires peuvent inclure :

  • encrypted_content — provenant des modèles de raisonnement (pour préserver le contexte)
  • built_in_tool_outputs — résultats de la recherche web, de la recherche de fichiers et de l’interpréteur de code

Gestion des erreurs

Les erreurs sont mappées vers des AdkError structurées avec les catégories appropriées :

HTTP StatutCatégorie d’erreurRéessayable
401UnauthorizedNon
429RateLimitedOui
500, 502, 503, 504UnavailableOui
AutreInternalNon
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 */ }
}

Mode en arrière-plan et annulation

Pour les requêtes de longue durée, envoyez-les avec background: true et interrogez régulièrement leur état jusqu’à leur achèvement :

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?;

Les modèles de recherche approfondie (o3-deep-research, o4-mini-deep-research) activent automatiquement le mode en arrière-plan sans background: true explicite.


Exemple

Un exemple complet couvrant 7 scénarios est disponible à l’adresse examples/openai_responses/ :

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

Scénarios couverts :

  1. Conversation de base sans flux
  2. Conversation de base avec flux
  3. Modèle de raisonnement avec résumé (chemin de compatibilité o4-mini)
  4. Appel d’outils avec des outils de fonction
  5. Conversation à plusieurs tours
  6. Instructions système
  7. Température et configuration de génération (chemin de compatibilité gpt-4.1-nano)

Exemples supplémentaires

Six crates d’exemple autonomes illustrent des fonctionnalités spécifiques de Responses API :

ExempleCommande d’exécutionFonctionnalité
transport WebSocketcargo run --manifest-path examples/openai_ws_minimal/Cargo.tomlConnexion persistante à faible latence
Mode en arrière-plancargo run --manifest-path examples/openai_background/Cargo.tomlFlux de travail de soumission et d’interrogation
Conversations APIcargo run --manifest-path examples/openai_conversations/Cargo.tomlÉchanges multiples gérés côté serveur
Outils intégréscargo run --manifest-path examples/openai_builtin_tools/Cargo.tomlGénération d’images, recherche sur le Web
Recherche approfondiecargo run --manifest-path examples/openai_deep_research/Cargo.tomlRecherche automatique en arrière-plan
Réponses ouvertescargo run --manifest-path examples/openai_open_responses/Cargo.tomlPoints de terminaison indépendants du fournisseur


Précédent : ← Fournisseurs cloud | Suivant : Ollama (local) →