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
| Recurso | OpenAIClient (Chat Completions) | OpenAIResponsesClient (Responses) |
|---|---|---|
| Endpoint | /v1/chat/completions | /v1/responses |
| Modelos | Modelos compatíveis com chat | GPT atuais e modelos de raciocínio |
| Resumos de raciocínio | Não disponível | Suporte nativo |
| Ferramentas integradas | Não disponível | Pesquisa na web, pesquisa de arquivos, interpretador de código |
| Estado no lado do servidor | Histórico manual de mensagens | previous_response_id |
| Saída estruturada | response_format | text.format (planejado) |
| Maturidade | Estável, amplamente adotado | Mais 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ínio | Descrição |
|---|---|
None | Desativar o raciocínio para obter a menor latência |
Minimal | Raciocínio mínimo legado em modelos compatíveis |
Low | Baixo esforço de raciocínio |
Medium | Raciocínio equilibrado |
High | Alto esforço de raciocínio |
XHigh | Esforço de raciocínio extra alto |
Max | Raciocí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ínio | Descrição |
|---|---|
Auto | O modelo decide se deve incluir um resumo |
Concise | Breve resumo do raciocínio |
Detailed | Resumo 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
| Modelo | Tipo | Descrição |
|---|---|---|
gpt-5.6-terra | Raciocínio | Opção padrão equilibrada para agentes em produção |
gpt-5.6-sol | Raciocínio | Raciocínio e programação de alto nível |
gpt-5.6-luna | Raciocínio | Cargas de trabalho de alto volume e baixo custo |
gpt-5.6 | Raciocínio | Alias principal |
gpt-5 | Raciocínio | Compatibilidade com a geração anterior |
gpt-4.1 família | Conversa | Compatibilidade e controles explícitos de amostragem |
o3 / o4-mini | Raciocínio | Compatibilidade 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::Textcompartial: true - Os deltas do resumo do raciocínio chegam como
Part::Thinkingcompartial: true - As chamadas de função são emitidas a partir do evento
ResponseCompletedfinal, com nomes e argumentos corretos - O evento final contém
turn_complete: truecom 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 Status | Categoria do erro | Repetível |
|---|---|---|
| 401 | Unauthorized | Não |
| 429 | RateLimited | Sim |
| 500, 502, 503, 504 | Unavailable | Sim |
| Outros | Internal | Nã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:
- Chat básico sem streaming
- Chat básico com streaming
- Modelo de raciocínio com resumo (caminho de compatibilidade com
o4-mini) - Chamada de ferramentas com ferramentas de função
- Conversa com várias interações
- Instruções do sistema
- 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:
| Exemplo | Comando de execução | Recurso |
|---|---|---|
| WebSocket transport | cargo run --manifest-path examples/openai_ws_minimal/Cargo.toml | Conexão persistente de baixa latência |
| Modo em segundo plano | cargo run --manifest-path examples/openai_background/Cargo.toml | Fluxo de trabalho de envio e consulta |
| Conversas API | cargo run --manifest-path examples/openai_conversations/Cargo.toml | Várias interações gerenciadas pelo servidor |
| Ferramentas integradas | cargo run --manifest-path examples/openai_builtin_tools/Cargo.toml | Geração de imagens, pesquisa na web |
| Pesquisa aprofundada | cargo run --manifest-path examples/openai_deep_research/Cargo.toml | Pesquisa automática em segundo plano |
| Respostas abertas | cargo run --manifest-path examples/openai_open_responses/Cargo.toml | Endpoints independentes de provedor |
Relacionados
- Provedores de modelos na nuvem — Todos os provedores LLM compatíveis
- Ollama (local) — Execute modelos localmente
- LlmAgent — Usando modelos com agentes
- Ferramentas de função — Adicionando ferramentas aos agentes
Anterior: ← Provedores de nuvem | Próximo: Ollama (local) →