OpenAI 응답 API
ADK-Rust은 OpenAI의 응답 API(/v1/responses 엔드포인트)를 위한 전용 클라이언트를 제공합니다. 이는 Chat Completions API의 후속 기능입니다. 응답 API은 전체 추론 노력 범위를 포함한 최신 GPT-5.6 모델을 사용하는 데 권장되는 방식입니다.
개요
┌─────────────────────────────────────────────────────────────────────┐
│ 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) │
│ │
└─────────────────────────────────────────────────────────────────────┘
어떤 클라이언트를 사용할지 선택하는 방법
| 기능 | OpenAIClient (Chat Completions) | OpenAIResponsesClient (Responses) |
|---|---|---|
| 엔드포인트 | /v1/chat/completions | /v1/responses |
| 모델 | 채팅 호환 모델 | 현재 GPT 및 추론 모델 |
| 추론 요약 | 사용 불가 | 기본 지원 |
| 내장 도구 | 사용 불가 | 웹 검색, 파일 검색, 코드 인터프리터 |
| 서버 측 상태 | 수동 메시지 기록 | previous_response_id |
| 구조화된 출력 | response_format | text.format (예정) |
| 성숙도 | 안정적이며 널리 채택됨 | OpenAI에서 권장하는 최신 방식 |
OpenAIResponsesClient 요약 기능이 있는 추론 모델, 기본 제공 도구가 필요하거나 OpenAI의 최신 API을 사용하려는 경우 사용하세요. 기존 Chat Completions 워크플로와의 하위 호환성이 필요한 경우 OpenAIClient을 사용하세요.
설치
[dependencies]
adk-rust = { version = "2.1.0", features = ["openai"] }
adk-tool = "2.1.0"
또는 adk-model을 직접 사용하세요:
[dependencies]
adk-model = { version = "2.1.0", features = ["openai"] }
API 키를 설정하세요:
export OPENAI_API_KEY="sk-..."
빠른 시작
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(())
}
구성
기본 구성
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");
추론 모델
GPT-5.6 추론 모델의 경우 추론 수준과 요약을 구성하세요:
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,
)?;
| 추론 수준 | 설명 |
|---|---|
None | 가장 짧은 지연 시간을 위해 추론 비활성화 |
Minimal | 이를 지원하는 모델에서 레거시 최소 추론 |
Low | 낮은 추론 노력 |
Medium | 균형 잡힌 추론 |
High | 높은 추론 노력 |
XHigh | 매우 높은 추론 노력 |
Max | 지원되는 모델에서 최대 추론 |
GPT-5.6은 Responses API을 통해 None, Low, Medium, High, XHigh 및 Max을 지원합니다. Chat Completions는 최대 XHigh까지 지원합니다.
| 추론 요약 | 설명 |
|---|---|
Auto | 모델이 요약을 포함할지 결정 |
Concise | 추론에 대한 간략한 요약 |
Detailed | 추론에 대한 철저한 요약 |
추론 요약은 응답 스트림에 Part::Thinking로 표시되므로, 모델의 사고 과정을 사용자에게 보여줄 수 있습니다.
재시도 구성
use adk_model::retry::RetryConfig;
let client = OpenAIResponsesClient::new(config)?
.with_retry_config(RetryConfig {
max_retries: 3,
..Default::default()
});
속도 제한(429), 서버 오류(500/502/503/504) 및 네트워크 장애가 발생하면 자동으로 재시도합니다.
사용 가능한 모델
| 모델 | 유형 | 설명 |
|---|---|---|
gpt-5.6-terra | 추론 | 프로덕션 에이전트를 위한 균형 잡힌 기본값 |
gpt-5.6-sol | 추론 | 대표적인 추론 및 코딩 |
gpt-5.6-luna | 추론 | 비용 효율적인 대규모 작업 |
gpt-5.6 | 추론 | 플래그십 별칭 |
gpt-5 | 추론 | 이전 세대 호환성 |
gpt-4.1 제품군 | 채팅 | 호환성 및 명시적 샘플링 제어 |
o3 / o4-mini | 추론 | 이전 세대 추론 호환성 |
기능
도구 호출
함수 도구는 OpenAIClient와 동일하게 작동합니다. 에이전트에서 도구를 정의하면 runner가 도구 호출 루프를 처리합니다.
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()?;
다중 턴 대화
Runner는 세션을 통해 대화 기록을 자동으로 관리합니다. 각 턴의 컨텍스트가 보존됩니다.
// 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."
요청별 추론 재정의
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()?;
기본 제공 도구
Responses API은 OpenAI 호스팅 도구를 지원합니다. adk-tool의 타입이 지정된 래퍼를 우선 사용하세요.
use adk_tool::OpenAIWebSearchTool;
use std::sync::Arc;
let agent = LlmAgentBuilder::new("researcher")
.model(model)
.tool(Arc::new(OpenAIWebSearchTool::new().preview()))
.build()?;
사용 가능한 래퍼에는 OpenAIWebSearchTool, OpenAIFileSearchTool, OpenAICodeInterpreterTool, OpenAIImageGenerationTool, OpenAIComputerUseTool, OpenAIMcpTool, OpenAILocalShellTool, OpenAIShellTool 및 OpenAIApplyPatchTool가 포함됩니다.
이전 응답 ID
서버 측 대화 상태를 사용하려면(로컬 세션 기록 우회) 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()?;
스트리밍 동작
Responses API 클라이언트는 텍스트 및 추론 델타를 실시간으로 스트리밍합니다.
- 텍스트 델타는
Part::Text으로partial: true과 함께 도착합니다. - 추론 요약 델타는
Part::Thinking으로partial: true와 함께 도착합니다. - 함수 호출은 올바른 이름과 인수를 포함하여 최종
ResponseCompleted이벤트에서 내보내집니다. - 최종 이벤트에는 사용량 메타데이터와 종료 사유가 포함된
turn_complete: true이 있습니다.
즉, 모델이 생성하는 동안 텍스트가 토큰 단위로 나타나는 것을 볼 수 있으며, 함수 호출은 실행할 수 있는 완전한 객체로 도착합니다.
공급자 메타데이터
모든 응답에는 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
}
추가 메타데이터에는 다음이 포함될 수 있습니다.
encrypted_content— 추론 모델에서 제공(컨텍스트 보존용)built_in_tool_outputs— 웹 검색, 파일 검색, 코드 인터프리터의 결과
오류 처리
오류는 적절한 범주를 갖춘 구조화된 AdkError로 매핑됩니다.
| HTTP 상태 | 오류 범주 | 재시도 가능 |
|---|---|---|
| 401 | Unauthorized | 아니요 |
| 429 | RateLimited | 예 |
| 500, 502, 503, 504 | Unavailable | 예 |
| 기타 | Internal | 아니요 |
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 */ }
}
백그라운드 모드 및 취소
장시간 실행되는 요청의 경우 background: true을 사용하여 제출하고 완료될 때까지 폴링합니다.
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?;
심층 리서치 모델(o3-deep-research, o4-mini-deep-research)은 명시적인 background: true 없이도 백그라운드 모드를 자동으로 활성화합니다.
예제
완전한 7개 시나리오 예제는 examples/openai_responses/에서 확인할 수 있습니다.
export OPENAI_API_KEY=sk-...
cargo run --manifest-path examples/openai_responses/Cargo.toml
다음 시나리오를 다룹니다:
- 기본 비스트리밍 채팅
- 기본 스트리밍 채팅
- 요약 기능이 포함된 추론 모델(
o4-mini호환 경로) - 함수 도구를 사용한 도구 호출
- 다중 턴 대화
- 시스템 지침
- 온도 및 생성 구성(
gpt-4.1-nano호환 경로)
추가 예제
독립 실행형 예제 crate 6개에서 특정 Responses API 기능을 보여 줍니다:
| 예시 | 실행 명령 | 기능 |
|---|---|---|
| WebSocket 전송 | cargo run --manifest-path examples/openai_ws_minimal/Cargo.toml | 지연 시간이 짧은 영구 연결 |
| 백그라운드 모드 | cargo run --manifest-path examples/openai_background/Cargo.toml | 제출 및 폴링 워크플로 |
| 대화 API | cargo run --manifest-path examples/openai_conversations/Cargo.toml | 서버 관리 다중 턴 |
| 내장 도구 | cargo run --manifest-path examples/openai_builtin_tools/Cargo.toml | 이미지 생성, 웹 검색 |
| 심층 리서치 | cargo run --manifest-path examples/openai_deep_research/Cargo.toml | 자동 백그라운드 리서치 |
| 오픈 응답 | cargo run --manifest-path examples/openai_open_responses/Cargo.toml | 공급자 독립 엔드포인트 |
관련 항목
- 클라우드 모델 제공업체 — 지원되는 모든 LLM 제공업체
- Ollama(로컬) — 모델을 로컬에서 실행
- LlmAgent — 에이전트에서 모델 사용
- 함수 도구 — 에이전트에 도구 추가
이전: ← 클라우드 제공업체 | 다음: Ollama(로컬) →