Decisions API는 GPT-Live에 기본으로 통합되어 있어 사용자가 말하는 도중에도 빠르게 결정을 내릴 수 있습니다.
네이티브 위임을 사용하면 요청이 앱을 거쳐 왕복하는 단계를 생략할 수 있습니다. 사용자 정의 위임에서는 Live가 앱에 알리면 앱이 Decisions를 호출합니다. 네이티브 위임에서는 Live가 Decisions를 직접 호출합니다.
결정 시점 선택하기
- 앱이 처리할 수 있는 요청을 Live가 인식하면 Live가 위임하도록 하세요.
session.delegation에 선택지를 설정하고 언제 위임할지 Live에 알려 주세요. - 사용자가 말하거나 Live가 답하는 동안 대화에 반응하세요. 입력 또는 출력 전사 텍스트의 증분을 기준으로
session.triggers를 설정하세요.
Live 세션이 진행 중일 때도 질문을 변경할 수 있습니다. session.update를 보내고 해당 요청에 대한 session.updated를 받은 뒤 그 단계의 결정 항목을 추가하세요. 위임 유형은 세션을 만들 때 설정하며 세션이 끝날 때까지 고정됩니다.
Live가 위임하도록 하기
Live는 요청 한 번으로 개발자가 정의한 작업 중 무엇을 수행할지, 앱이 Responses API를 호출해야 할지 Decisions에 판단을 맡길 수 있습니다.
차량용 음성 어시스턴트를 만든다고 가정해 보세요. 운전자는 실내 온도 조절, 앞유리 김 서림 제거 기능 켜기나 끄기, 길 안내와 식당 검색을 요청할 수 있습니다. none을 선택하면 해당 실내 설정은 그대로 유지됩니다.
차량 실내 설정 조절하기
“좀 춥네요.”
- 실내 온도올리기
- 김 서림 제거변경 없음
- Responses 호출아니요
“온도를 조금 올렸어요.”
차량 실내 제어 범위를 벗어나는 요청 처리하기
- 실내 온도변경 없음
- 김 서림 제거켜기
- Responses 호출예
Responses의 도구 호출에 따라 샌프란시스코까지 길 안내를 시작하고 현지 식당을 검색합니다. 두 결과를 모두 Responses에 반환합니다.
김 서림 제거 기능의 상태, 길 안내 시작 여부, 검색으로 찾은 식당.
위임 설정하기
먼저 Live 연결이 정상적으로 작동하는지 확인하고 api.decisions.write 권한을 확보하세요. 평소 사용하는 Live 연결 헤더를 그대로 사용하세요. Decisions 전용 알파 헤더는 필요하지 않습니다.
WebRTC 세션 요청에서 아래 객체의 필드를 session 아래에 기존 transport와 같은 수준으로 추가하세요. 세션 지침은 Live에 언제 위임할지 알려 줍니다. 선택형 질문은 Decisions에 무엇을 반환할지 알려 줍니다. 네이티브 결정 요청 한 번으로 세 질문에 각각 독립적인 답을 얻습니다.
{
"model": "gpt-live-1",
"instructions": "Delegate the driver’s whole request, including cabin controls, navigation, and local search. Wait for the app to report what happened, then tell the driver in natural language.",
"delegation": {
"type": "decisions",
"decisions": {
"model": "gpt-6-luna",
"questions": [
{
"type": "choice",
"name": "cabin_temperature",
"instructions": "Choose temperature_up if the driver feels cold or wants more heat, temperature_down if they feel hot or want to cool down, or none if the request is unrelated.",
"choices": [
{ "value": "temperature_up" },
{ "value": "temperature_down" },
{ "value": "none" }
]
},
{
"type": "choice",
"name": "windshield_defogger",
"instructions": "Choose on if the driver reports a foggy windshield or asks to defog it, off if they say the glass is clear now or ask to turn the defogger off, or none if the request is unrelated.",
"choices": [
{ "value": "on" },
{ "value": "off" },
{ "value": "none" }
]
},
{
"type": "choice",
"name": "needs_response",
"instructions": "Choose yes if any part of the request goes beyond these cabin controls, such as getting directions or finding restaurants. Otherwise choose no.",
"choices": [{ "value": "yes" }, { "value": "no" }]
}
]
}
}
}
Live는 대화 전사 텍스트를 Decisions에 자동으로 보냅니다.
작업 실행 및 결과 전달하기
delegation.id는 session.delegation.created에서 읽어 저장하세요. decision.event 중 해당 delegation_id가 있는 이벤트에서 event.type이 decision.completed인지 확인하고 event.decision.answers에서 질문 이름별로 선택된 값을 읽으세요. 답이 none이면 해당 작업은 수행하지 않습니다. WebRTC 이벤트를 필터링한다면 session.delegation.created와 decision.event를 모두 허용하세요.
“좀 춥네요.”라는 말에 Decisions는 temperature_up, none, no를 선택합니다. 온도를 올린 뒤 실제 설정값을 읽어 오세요. 이제 차량 대시보드에 자동 모드의 목표 온도가 22 °C로 표시되고 김 서림 제거 기능은 꺼져 있다고 가정해 보세요. 이렇게 확인한 실내 상태를 decision.item.create로 Decisions에 보내세요.
{
"type": "decision.item.create",
"event_id": "evt_cabin_after_temperature_up_1",
"item": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "Use the latest cabin state snapshot as the current state. Cabin temperature is set to 22 °C in automatic mode. Windshield defogger is off."
}
]
}
}
대시보드에 표시된 상태가 바뀔 때만 전체 실내 상태를 간결하게 정리한 스냅샷을 추가하세요. 가장 최근 스냅샷을 현재 상태로 간주하세요. 이전 입력을 그대로 두면 프롬프트 캐싱에 사용하는 접두부가 유지됩니다.
decision.item.created를 받은 뒤 이 요청의 위임 ID를 사용해 session.commentary.append로 결과를 Live에 보내세요.
{
"type": "session.commentary.append",
"delegation_id": "del_cabin_1",
"content": "I raised the cabin temperature and confirmed the new setting on the dashboard."
}
샌프란시스코에 관한 요청에서는 Decisions가 none, on, yes를 선택합니다. 김 서림 제거 기능을 켜고 상태를 읽어 온 뒤 위와 같은 방식으로 갱신된 실내 상태 스냅샷을 추가하세요. 그런 다음 서버에서 api.responses.write 권한으로 Responses를 호출하세요. Responses가 “거기”를 샌프란시스코로 이해할 수 있도록 실내 제어 결과와 운전자의 요청 전체를 함께 보내세요.
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6.1-sol",
"instructions": "The car has handled the cabin controls. Use the tools for the rest of the request, then briefly tell the driver what happened based on the results.",
"input": "Driver: My windshield is foggy, so please defog it, navigate to San Francisco, and find me some good restaurants there.\nCabin results: Windshield defogger confirmed on. Temperature unchanged.",
"tools": [
{
"type": "function",
"name": "start_navigation",
"description": "Start navigation to a destination and report whether the route started.",
"parameters": {
"type": "object",
"properties": { "destination": { "type": "string" } },
"required": ["destination"],
"additionalProperties": false
},
"strict": true
},
{
"type": "function",
"name": "find_restaurants",
"description": "Find well-rated restaurants in the named city or area.",
"parameters": {
"type": "object",
"properties": { "location": { "type": "string" } },
"required": ["location"],
"additionalProperties": false
},
"strict": true
}
]
}'위 예시는 Responses 함수 호출 플로우의 첫 요청입니다. 각 function_call에 지정된 함수를 전달받은 인수로 실행한 뒤, function_call_output에 실제 결과 또는 오류와 해당 call_id를 담아 반환하세요. Responses가 최종 답변을 반환할 때까지 반복하세요.
Live에는 Responses의 간결한 최종 답변과 확인된 실내 상태만 보내세요. session.commentary.append에 동일한 delegation_id를 사용하세요.
전사 텍스트에 반응하기
대화에 맞춰 반응해야 할 때는 전사 트리거를 사용하세요. 예를 들어 디지털 캐릭터가 “저 취직했어요!”라는 말을 듣고 사용자가 아직 말하는 동안 미소를 지으며 고개를 끄덕일 수 있습니다. 출력 트리거를 사용하면 Live가 “정말 잘됐네요!”라고 말할 때 캐릭터가 더 활짝 웃으며 몸을 앞으로 기울이게 할 수 있습니다.
session.input_transcript.delta“저 취직했어요!”
session.output_transcript.delta“정말 잘됐네요!”
session.input_transcript.delta“지원한 회사에 떨어졌어요.”
session.triggers에 아래와 같은 트리거를 추가하세요. 표정, 강도, 몸짓을 각각 선택하도록 요청합니다.
{
"type": "decisions",
"event_type": "session.input_transcript.delta",
"decisions": {
"questions": [
{
"type": "choice",
"name": "expression",
"instructions": "Choose your expression as you listen to the person's latest words.",
"choices": [
{ "value": "neutral" },
{ "value": "happy" },
{ "value": "sad" },
{ "value": "concerned" }
]
},
{
"type": "choice",
"name": "intensity",
"instructions": "Choose how strongly to show that expression.",
"choices": [
{ "value": "low" },
{ "value": "medium" },
{ "value": "high" }
]
},
{
"type": "choice",
"name": "gesture",
"instructions": "Choose a gesture that fits what you just heard.",
"choices": [
{ "value": "none" },
{ "value": "nod" },
{ "value": "shake" },
{ "value": "lean" }
]
}
]
}
}
답변에 맞춰 캐릭터를 움직이려면 두 번째 트리거를 추가하세요. event_type을 session.output_transcript.delta로 설정하고 Live가 말하는 내용에 어울리는 선택지를 고르도록 요청하세요. 모델과 트리거 ID는 Live가 제공합니다. 전사 트리거는 위임과 독립적으로 실행됩니다.
WebRTC 이벤트를 필터링한다면 decision.event와 설정한 각 트리거에 해당하는 전사 이벤트를 허용하세요. 설정에 따라 session.input_transcript.delta, session.output_transcript.delta 또는 둘 다 허용해야 합니다. Live는 트리거를 발생시킨 전사 이벤트도 허용된 경우에만 해당 트리거의 결과를 전달합니다.
트리거 결과에는 어떤 전사 텍스트 증분이 해당 트리거를 발생시켰는지 표시됩니다. 다음은 decision.event에서 “저 취직했어요!” 예시와 관련된 필드를 발췌한 것입니다.
{
"type": "decision.event",
"delegation_id": null,
"trigger_id": "trg_listening_1",
"source_event_type": "session.input_transcript.delta",
"source_event_id": "evt_input_42",
"event": {
"type": "decision.completed",
"decision": {
"answers": [
{ "type": "choice", "name": "expression", "choice": "happy" },
{ "type": "choice", "name": "intensity", "choice": "medium" },
{ "type": "choice", "name": "gesture", "choice": "nod" }
]
}
}
}
source_event_id로 결과를 해당 전사 텍스트 증분과 연결하세요. Live가 대기 중인 증분을 합칠 수 있으며, 결과가 원래 순서와 다르게 도착할 수 있습니다. 입력과 출력 각각에 대해 관련 결과 중 가장 최신 결과를 적용하고, 입 모양은 오디오에 맞춰 움직이세요.