안내서
이 안내서는 OpenAI Agents SDK의 실시간 기능을 사용하여 음성 지원 AI 에이전트를 구축하는 방법을 심도 있게 다룹니다.
베타 기능
실시간 에이전트는 베타 단계입니다. 구현을 개선하면서 호환성에 영향을 주는 변경이 있을 수 있습니다.
개요
실시간 에이전트는 오디오와 텍스트 입력을 실시간으로 처리하고 실시간 오디오로 응답하는 대화형 흐름을 제공합니다. OpenAI의 Realtime API와 지속적인 연결을 유지하여 지연이 낮은 자연스러운 음성 대화가 가능하며, 인터럽션(중단 처리)을 우아하게 처리할 수 있습니다.
아키텍처
핵심 구성 요소
실시간 시스템은 여러 핵심 구성 요소로 이루어져 있습니다:
- RealtimeAgent: instructions, tools, handoffs 로 구성된 에이전트
- RealtimeRunner: 구성 관리.
runner.run()을 호출하여 세션을 가져올 수 있습니다 - RealtimeSession: 단일 상호작용 세션. 일반적으로 사용자가 대화를 시작할 때마다 하나를 만들고 대화가 끝날 때까지 유지합니다
- RealtimeModel: 기본 모델 인터페이스(일반적으로 OpenAI의 WebSocket 구현)
세션 흐름
일반적인 실시간 세션은 다음 흐름을 따릅니다:
- instructions, tools, handoffs 로RealtimeAgent 를 생성합니다
- 에이전트와 구성 옵션으로RealtimeRunner 를 설정합니다
await runner.run()을 사용해세션을 시작하고 RealtimeSession 을 반환받습니다send_audio()또는send_message()를 사용하여 세션에오디오 또는 텍스트 메시지 전송합니다- 세션을 순회(iterate)하여이벤트 수신합니다 - 오디오 출력, 전사, 도구 호출, 핸드오프, 오류 등의 이벤트가 포함됩니다
- 사용자가 에이전트의 발화를 가로챌 때인터럽션(중단 처리) 처리를 수행하며, 현재 오디오 생성은 자동으로 중지됩니다
세션은 대화 이력을 유지하고 실시간 모델과의 지속적인 연결을 관리합니다.
에이전트 구성
RealtimeAgent 는 일반 Agent 클래스와 유사하게 동작하지만 몇 가지 중요한 차이점이 있습니다. 전체 API 세부 정보는RealtimeAgent API 참고를 확인하세요.
일반 에이전트와의 주요 차이점:
- 모델 선택은 에이전트 레벨이 아닌 세션 레벨에서 구성됩니다
- structured output 을 지원하지 않습니다(
outputType은 지원되지 않음) - 음성(voice)은 에이전트별로 구성할 수 있지만 첫 번째 에이전트가 말한 이후에는 변경할 수 없습니다
- 그 외 tools, handoffs, instructions 등의 기능은 동일하게 동작합니다
세션 구성
모델 설정
세션 구성으로 기본 실시간 모델 동작을 제어할 수 있습니다. 모델 이름(예:gpt-realtime), 음성 선택(alloy, echo, fable, onyx, nova, shimmer), 지원 모달리티(텍스트 및/또는 오디오)를 구성할 수 있습니다. 오디오 형식은 입력 및 출력 모두에 대해 설정할 수 있으며, 기본값은 PCM16 입니다.
오디오 구성
오디오 설정은 세션이 음성 입력과 출력을 처리하는 방식을 제어합니다. Whisper 같은 모델을 사용한 입력 오디오 전사를 구성하고, 언어 선호도를 설정하며, 도메인 특화 용어의 정확도를 높이기 위한 전사 프롬프트를 제공할 수 있습니다. 턴 감지 설정을 통해 에이전트가 언제 응답을 시작하고 멈출지 제어하며, 음성 활동 감지 임계값, 무음 지속 시간, 감지된 음성 주변 패딩 등의 옵션을 제공합니다.
도구와 함수
도구 추가
일반 에이전트와 마찬가지로, 실시간 에이전트는 대화 중에 실행되는 함수 도구를 지원합니다:
fromagentsimportfunction_tool@function_tooldefget_weather(city:str)->str:"""Get current weather for a city."""# Your weather API logic herereturnf"The weather in{city} is sunny, 72°F"@function_tooldefbook_appointment(date:str,time:str,service:str)->str:"""Book an appointment."""# Your booking logic herereturnf"Appointment booked for{service} on{date} at{time}"agent=RealtimeAgent(name="Assistant",instructions="You can help with weather and appointments.",tools=[get_weather,book_appointment],)핸드오프
핸드오프 생성
핸드오프를 통해 전문화된 에이전트 간에 대화를 전달할 수 있습니다.
fromagents.realtimeimportrealtime_handoff# Specialized agentsbilling_agent=RealtimeAgent(name="Billing Support",instructions="You specialize in billing and payment issues.",)technical_agent=RealtimeAgent(name="Technical Support",instructions="You handle technical troubleshooting.",)# Main agent with handoffsmain_agent=RealtimeAgent(name="Customer Service",instructions="You are the main customer service agent. Hand off to specialists when needed.",handoffs=[realtime_handoff(billing_agent,tool_description="Transfer to billing support"),realtime_handoff(technical_agent,tool_description="Transfer to technical support"),])이벤트 처리
세션은 세션 객체를 순회하여 청취할 수 있는 이벤트를 스트림으로 제공합니다. 이벤트에는 오디오 출력 청크, 전사 결과, 도구 실행 시작 및 종료, 에이전트 핸드오프, 오류 등이 포함됩니다. 처리해야 할 핵심 이벤트는 다음과 같습니다:
- audio: 에이전트 응답의 원문 오디오 데이터
- audio_end: 에이전트 발화 종료
- audio_interrupted: 사용자가 에이전트를 중단함
- tool_start/tool_end: 도구 실행 라이프사이클
- handoff: 에이전트 핸드오프 발생
- error: 처리 중 오류 발생
전체 이벤트 세부 정보는RealtimeSessionEvent를 참조하세요.
가드레일
실시간 에이전트에는 출력 가드레일만 지원됩니다. 이러한 가드레일은 실시간 생성 중 성능 문제를 피하기 위해 디바운스되어 주기적으로 실행되며(모든 단어마다 실행되지 않음), 기본 디바운스 길이는 100자이며 구성 가능합니다.
가드레일은RealtimeAgent에 직접 연결하거나 세션의run_config를 통해 제공할 수 있습니다. 두 소스의 가드레일은 함께 실행됩니다.
fromagents.guardrailimportGuardrailFunctionOutput,OutputGuardraildefsensitive_data_check(context,agent,output):returnGuardrailFunctionOutput(tripwire_triggered="password"inoutput,output_info=None,)agent=RealtimeAgent(name="Assistant",instructions="...",output_guardrails=[OutputGuardrail(guardrail_function=sensitive_data_check)],)가드레일이 트리거되면guardrail_tripped 이벤트를 생성하고 에이전트의 현재 응답을 인터럽트할 수 있습니다. 디바운스 동작은 안전성과 실시간 성능 요구 사이의 균형을 돕습니다. 텍스트 에이전트와 달리, 실시간 에이전트는 가드레일이 트립되더라도 Exception 을 발생시키지않습니다.
오디오 처리
session.send_audio(audio_bytes)를 사용해 오디오를 세션으로 보내거나,session.send_message()를 사용해 텍스트를 보낼 수 있습니다.
오디오 출력을 위해서는audio 이벤트를 수신하고 선호하는 오디오 라이브러리를 통해 오디오 데이터를 재생하세요. 사용자가 에이전트를 중단할 때 즉시 재생을 멈추고 대기 중인 오디오를 지우기 위해audio_interrupted 이벤트를 반드시 수신하세요.
SIP 통합
Realtime Calls API로 도착하는 전화 통화에 실시간 에이전트를 연결할 수 있습니다. SDK는OpenAIRealtimeSIPModel을 제공하며, SIP 를 통한 미디어 협상을 수행하면서 동일한 에이전트 흐름을 재사용합니다.
사용하려면 모델 인스턴스를 러너에 전달하고 세션을 시작할 때 SIPcall_id를 제공하세요. 통화 ID는 수신 전화를 알리는 웹훅으로 전달됩니다.
fromagents.realtimeimportRealtimeAgent,RealtimeRunnerfromagents.realtime.openai_realtimeimportOpenAIRealtimeSIPModelrunner=RealtimeRunner(starting_agent=agent,model=OpenAIRealtimeSIPModel(),)asyncwithawaitrunner.run(model_config={"call_id":call_id_from_webhook,"initial_model_settings":{"turn_detection":{"type":"semantic_vad","interrupt_response":True},},},)assession:asyncforeventinsession:...발신자가 전화를 끊으면 SIP 세션이 종료되고 실시간 연결이 자동으로 닫힙니다. 완전한 전화 예시는examples/realtime/twilio_sip를 참조하세요.
모델 직접 액세스
하위 모델에 액세스하여 커스텀 리스너를 추가하거나 고급 작업을 수행할 수 있습니다:
이렇게 하면 연결에 대한 더 하위 수준의 제어가 필요한 고급 사용 사례를 위해RealtimeModel 인터페이스에 직접 액세스할 수 있습니다.
예시
완전한 동작 code examples 은examples/realtime 디렉터리를 확인하세요. UI 구성 요소가 있는 데모와 없는 데모가 포함되어 있습니다.