OpenAI Respostas API

ADK-Rust fornece um cliente dedicado para as Respostas API da OpenAI (endpoint /v1/responses) — a sucessora das API de Chat Completions. A API de Respostas é a maneira recomendada de usar os modelos atuais GPT-5.6, incluindo todo o seu intervalo de esforço de raciocínio.

Visão geral

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

Quando usar cada cliente

RecursoOpenAIClient (Chat Completions)OpenAIResponsesClient (Responses)
Endpoint/v1/chat/completions/v1/responses
ModelosModelos compatíveis com chatGPT atuais e modelos de raciocínio
Resumos de raciocínioNão disponívelSuporte nativo
Ferramentas integradasNão disponívelPesquisa na web, pesquisa de arquivos, interpretador de código
Estado no lado do servidorHistórico manual de mensagensprevious_response_id
Saída estruturadaresponse_formattext.format (planejado)
MaturidadeEstável, amplamente adotadoMais recente, recomendado por OpenAI

Use OpenAIResponsesClient quando precisar de modelos de raciocínio com resumos, ferramentas integradas ou quiser usar o API mais recente de OpenAI. Use OpenAIClient para compatibilidade retroativa com fluxos de trabalho existentes do Chat Completions.


Instalação

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

Ou diretamente com adk-model:

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

Defina sua chave API:

export OPENAI_API_KEY="sk-..."

Início 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(())
}

Configuração

Configuração 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 raciocínio

Para modelos de raciocínio GPT-5.6, configure o esforço de raciocínio e o resumo:

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,
)?;
Esforço de raciocínioDescrição
NoneDesativar o raciocínio para obter a menor latência
MinimalRaciocínio mínimo legado em modelos compatíveis
LowBaixo esforço de raciocínio
MediumRaciocínio equilibrado
HighAlto esforço de raciocínio
XHighEsforço de raciocínio extra alto
MaxRaciocínio máximo nos modelos compatíveis

GPT-5.6 oferece suporte a None, Low, Medium, High, XHigh e Max por meio da Responses API. Chat Completions oferece suporte a até XHigh.

Resumo do raciocínioDescrição
AutoO modelo decide se deve incluir um resumo
ConciseBreve resumo do raciocínio
DetailedResumo detalhado do raciocínio

Resumos do raciocínio aparecem como Part::Thinking no fluxo de resposta, permitindo que você mostre o processo de pensamento do modelo aos usuários.

Configuração de novas tentativas

use adk_model::retry::RetryConfig;

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

As novas tentativas são automáticas para limites de taxa (429), erros do servidor (500/502/503/504) e falhas de rede.


Modelos disponíveis

ModeloTipoDescrição
gpt-5.6-terraRaciocínioOpção padrão equilibrada para agentes em produção
gpt-5.6-solRaciocínioRaciocínio e programação de alto nível
gpt-5.6-lunaRaciocínioCargas de trabalho de alto volume e baixo custo
gpt-5.6RaciocínioAlias principal
gpt-5RaciocínioCompatibilidade com a geração anterior
gpt-4.1 famíliaConversaCompatibilidade e controles explícitos de amostragem
o3 / o4-miniRaciocínioCompatibilidade com raciocínio de geração anterior

Recursos

Chamada de ferramentas

As ferramentas de função funcionam da mesma forma que com OpenAIClient — defina as ferramentas no agente e o executor gerencia o ciclo de chamada da ferramenta:

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

Conversas com várias rodadas

O executor gerencia automaticamente o histórico da conversa por meio das sessões. O contexto de cada rodada é preservado:

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

Substituição do raciocínio por solicitação

Substitua as configurações de raciocínio por solicitação usando extensões 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()?;

Ferramentas integradas

O cliente API de Responses é compatível com ferramentas hospedadas em OpenAI. Prefira os wrappers 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()?;

Os wrappers disponíveis incluem OpenAIWebSearchTool, OpenAIFileSearchTool, OpenAICodeInterpreterTool, OpenAIImageGenerationTool, OpenAIComputerUseTool, OpenAIMcpTool, OpenAILocalShellTool, OpenAIShellTool e OpenAIApplyPatchTool.

ID da resposta anterior

Para obter o estado da conversa no servidor (ignorando o histórico da sessão local), passe 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()?;

Comportamento de streaming

O cliente API de Responses transmite deltas de texto e raciocínio em tempo real:

  • Os deltas de texto chegam como Part::Text com partial: true
  • Os deltas do resumo do raciocínio chegam como Part::Thinking com partial: true
  • As chamadas de função são emitidas a partir do evento ResponseCompleted final, com nomes e argumentos corretos
  • O evento final contém turn_complete: true com metadados de uso e o motivo de finalização

Isso significa que você vê o texto aparecer token por token enquanto o modelo o gera, e as chamadas de função chegam como objetos completos prontos para execução.


Metadados do provedor

Cada resposta inclui metadados do provedor com o 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
}

Metadados adicionais podem incluir:

  • encrypted_content — de modelos de raciocínio (para preservação do contexto)
  • built_in_tool_outputs — resultados de pesquisa na web, pesquisa de arquivos e interpretador de código

Tratamento de erros

Os erros são mapeados para AdkError estruturados com categorias apropriadas:

HTTP StatusCategoria do erroRepetível
401UnauthorizedNão
429RateLimitedSim
500, 502, 503, 504UnavailableSim
OutrosInternalNão
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 em segundo plano e cancelamento

Para solicitações de longa duração, envie com background: true e consulte o status até a conclusão:

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

Os modelos de pesquisa aprofundada (o3-deep-research, o4-mini-deep-research) ativam automaticamente o modo em segundo plano sem background: true explícito.


Exemplo

Um exemplo completo com 7 cenários está disponível em examples/openai_responses/:

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

Cenários abordados:

  1. Chat básico sem streaming
  2. Chat básico com streaming
  3. Modelo de raciocínio com resumo (caminho de compatibilidade com o4-mini)
  4. Chamada de ferramentas com ferramentas de função
  5. Conversa com várias interações
  6. Instruções do sistema
  7. Temperatura e configuração de geração (caminho de compatibilidade com gpt-4.1-nano)

Exemplos adicionais

Seis crates de exemplo independentes demonstram recursos específicos de API:

ExemploComando de execuçãoRecurso
WebSocket transportcargo run --manifest-path examples/openai_ws_minimal/Cargo.tomlConexão persistente de baixa latência
Modo em segundo planocargo run --manifest-path examples/openai_background/Cargo.tomlFluxo de trabalho de envio e consulta
Conversas APIcargo run --manifest-path examples/openai_conversations/Cargo.tomlVárias interações gerenciadas pelo servidor
Ferramentas integradascargo run --manifest-path examples/openai_builtin_tools/Cargo.tomlGeração de imagens, pesquisa na web
Pesquisa aprofundadacargo run --manifest-path examples/openai_deep_research/Cargo.tomlPesquisa automática em segundo plano
Respostas abertascargo run --manifest-path examples/openai_open_responses/Cargo.tomlEndpoints independentes de provedor


Anterior: ← Provedores de nuvem | Próximo: Ollama (local) →