
OpenAI Realtime API ile Sesli Ajan Oluşturma: 7 Adımlık Üretim Eğitimi (2026)
Test ajanımız bir Twilio çağrısını yanıtladı ve arayan konuşmayı bıraktıktan 1,1 saniye sonra ilk kelimesini söyledi. Bu, gpt-realtime-2 ve semantic_vad ile 40 çağrı üzerinde ölçülen p50 gidiş-dönüş süresidir. Sihir değil. OpenAI Realtime API, konuşmadan konuşmaya işlemi tek bir sokette yapar, böylece yaklaşık 600 ms yapıştırıcı kod ekleyen STT → LLM → TTS aktarımını atlarsınız. Ama varsayılan ayarlar sizi bir saniyeye getirmez. Bu, yayınladığımız 7 adımlık yapım; kod ve gecikme tablosuyla birlikte.
Bu bir yapım eğitimi, kavram açıklaması değil. Önce katmanlı dökümü istiyorsanız, bir yapay zeka sesli ajanının gerçekte ne olduğunu okuyup geri dönün. Aşağıdaki her şey, bir OpenAI API anahtarınız ve bir Node çalışma ortamınız olduğunu varsayar.
Önemli çıkarımlar:
- gpt-realtime-2 konuşmadan konuşmaya işlemi tek sokette yapar, STT/LLM/TTS aktarımı yok, ~600 ms tasarruf.
- Geçici anahtarları sunucu tarafında oluşturun; standart API anahtarınızı asla bir tarayıcıya göndermeyin.
- Twilio'nun medya akışı 8 kHz μ-law'dır; Realtime API için 24 kHz PCM16'ya yeniden örnekleyin.
- Gidiş-dönüşte p50 1,1 s / p95 1,9 s ölçtük. Sözünü kesme,
response.cancelüzerinden çalışır.
7 Adımda Ne İnşa Edeceksiniz
Bu eğitim, 1,5 saniyenin altında yanıt veren, konuşmanın ortasında gerçek bir fonksiyon çağıran ve arayanın sözünü kesmesine izin veren, telefona yanıt veren bir OpenAI Realtime API sesli ajanı kurar. Akış kısadır: bir arayan bir numarayı arar, ses sunucunuza akar, sunucunuz onu tek bir soketle gpt-realtime-2'ye köprüler, model konuşur ve araç çağrıları tetikleyebilir, ses geri akar.
İşte yol; kullanım senaryonuza uyan herhangi bir adımda durabilirsiniz:
- Geçici anahtar oluşturma (sunucu yolu)
- Oturumu açma ve yapılandırma
- Fonksiyon çağırmayı ekleme
- Twilio ile bir telefon numarasına köprüleme
- Sözünü kesme ve kesintileri yönetme
- Gecikmeyi saniye altına ayarlama
- Dağıtma ve üretim için sağlamlaştırma
Üç taşıma katmanı sesi taşır ve seçiminiz sesin nereden geldiğine bağlıdır. Bir tarayıcı doğrudan yakalar (WebRTC), sunucunuzda zaten ham bir akış vardır (WebSocket) veya bir telefon ağı iletir (SIP). Twilio köprüsü için WebSocket kullanacağız ve diğerlerini uydukları yerde belirteceğiz.
Adım 1: Geçici Anahtar Oluşturma (atlayamayacağınız yol)
Standart OpenAI API anahtarınızı asla bir tarayıcıya veya istemci cihazına açmayın. Realtime API tam da bunun için kısa ömürlü geçici anahtarlar verir. Sunucunuz gerçek anahtarınızla POST /v1/realtime/client_secrets'i çağırır, istemciye yaklaşık bir dakikada sona eren bir jeton verir ve istemci bunun yerine onunla bağlanır.
İşte bir tane oluşturan minimal bir Express yolu:
// server.js
import express from "express";
const app = express();
app.get("/session", async (req, res) => {
const r = await fetch("https://api.openai.com/v1/realtime/client_secrets", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
session: { type: "realtime", model: "gpt-realtime-2" },
}),
});
const data = await r.json();
res.json({ client_secret: data.value, expires_at: data.expires_at });
});
app.listen(3000);Tarayıcı /session'ı çağırır, kısa ömürlü gizli anahtarı okur ve onunla Realtime bağlantısını açar. Ajanınız yalnızca sunucu tarafıysa (Adım 4'teki Twilio durumu), istemci aktarımını atlayıp soketi arka uçtan doğrudan standart anahtarla açabilirsiniz. Geçici akış, güvenilmeyen istemcileri korumak için vardır.
Adım 2: Oturumu Açma ve gpt-realtime-2'yi Yapılandırma
Bir bağlantı açın, ardından modeli, ses formatını, sesi ve sıra algılamayı ayarlayan bir session.update gönderin. OpenAI belgeleri, reasoning.effort'u low ile başlatmayı ve yalnızca araç mantığınız daha fazla doğruluk gerektiriyorsa artırmayı önerir, çünkü daha yüksek çaba size gecikme olarak mal olur. Ses, her iki yönde de 24 kHz PCM16 olarak çalışır.
ws.send(JSON.stringify({
type: "session.update",
session: {
type: "realtime",
model: "gpt-realtime-2",
output_modalities: ["audio"],
audio: {
input: { format: "pcm16", sample_rate: 24000 },
output: { format: "pcm16", sample_rate: 24000, voice: "marin" },
},
instructions: "Bir restoran için rezervasyon ajanısın. Kısa ol.",
reasoning: { effort: "low" },
turn_detection: { type: "semantic_vad" },
},
}));Bu soketi hangi taşıma katmanına saracağınız ses kaynağına bağlıdır:
| Taşıma | Ne zaman kullanılır | Ses kaynağı |
|---|---|---|
| WebRTC | Tarayıcı veya mobil uygulama mikrofonu doğrudan yakalar | İstemci cihazı |
| WebSocket | Sunucunuzda zaten ham bir ses akışı var | Sunucu hattı |
| SIP | Telefon ayağını OpenAI'nin halletmesini istersiniz | PSTN / telefon |
Oturumun tam alan listesi ve GA özellik seti için OpenAI Realtime API belgeleri doğruluğun kaynağıdır. WebSocket kullanıyoruz çünkü Twilio bize Adım 4'te ham ses veriyor.
Adım 3: Fonksiyon Çağırmayı Ekleme (ajanın gerçekten bir şey yapabilmesi için)
Eylemde bulunamayan bir sesli ajan, dış sestir. Fonksiyon çağırma, gpt-realtime-2'nin konuşmanın ortasında duraklamasını, kodunuzdan bir şey çalıştırmasını istemesini ve sonuçla konuşmaya devam etmesini sağlar. Oturumda bir araç tanımlarsınız, model onu istediğinde bir function_call_arguments.done olayı yayar, işi çalıştırırsınız ve çıktıyı geri gönderirsiniz.
Aracı tanımlayın, ardından olayı işleyin:
// session.update -> session.tools içinde:
tools: [{
type: "function",
name: "book_reservation",
description: "Belirli bir kişi sayısı ve saat için masa ayırtır.",
parameters: {
type: "object",
properties: {
party_size: { type: "integer" },
time: { type: "string", description: "ISO 8601 tarih/saat" },
},
required: ["party_size", "time"],
},
}]
// çağrının işlenmesi:
if (event.type === "response.function_call_arguments.done") {
const args = JSON.parse(event.arguments);
const result = await bookTable(args); // gerçek mantığınız
ws.send(JSON.stringify({
type: "conversation.item.create",
item: {
type: "function_call_output",
call_id: event.call_id,
output: JSON.stringify(result),
},
}));
ws.send(JSON.stringify({ type: "response.create" })); // sonucu söylemesini sağla
}Araçların sessizce hiç tetiklenmemesinin en yaygın nedeni: function_call_arguments.done'ı dinlememek ve ardından response.create göndermemek. Model çağrıyı üretti, siz onu yok saydınız, arayan sessizlik duyuyor.
Ajanınız birçok araçla uğraşıyorsa, OpenAI Agents SDK buradaki hesabı değiştirdi. 15 Nisan 2026'daki revizyonu, Model Context Protocol'ü (MCP) birinci sınıf hale getirdi ve alt ajan devirlerini bir çalışma zamanı ilkeli haline getirdi. Böylece her aracı tek bir isteme tıkıştırmak yerine, bir yönlendirici ajan bir rezervasyonu bir rezervasyon alt ajanına ve bir faturalandırma sorusunu bir başkasına devredebilir. Agents SDK sesli hızlı başlangıcı, aynı Realtime oturumunu bir RealtimeAgent içine sarar ve kendi orkestrasyon döngünüzü yazmadan size devirler verir.
Adım 4: Bir Telefon Numarasına Köprüleme (Twilio)
Gerçek çağrıları yanıtlamak için sokete bir telefon sağlayıcısı köprülersiniz. Twilio ile gelen bir çağrıyı, sunucunuza bir WebSocket açan bir TwiML <Connect><Stream>'e yönlendirirsiniz ve ses çerçevelerini Twilio ile Realtime API arasında aktarırsınız. SIP alternatiftir. OpenAI Realtime, SIP'i doğrudan kabul eder; bu da sese dokunmanız gerekmiyorsa medya aktarımınızı tamamen kaldırır.
Akışı başlatan TwiML:
<Response>
<Connect>
<Stream url="wss://your-server.com/twilio-stream" />
</Connect>
</Response>Gözden kaçırırsanız bir gününüzü yiyen tuzak şu: Twilio'nun medya akışı 8 kHz μ-law'dır ve Realtime API 24 kHz PCM16 ister. Her iki yönde yeniden örneklersiniz, yoksa bozuk, sincap sesi alırsınız.
// gelen: Twilio (8kHz μ-law base64) -> Realtime (24kHz PCM16)
const pcm16 = upsample(muLawDecode(Buffer.from(msg.media.payload, "base64")), 8000, 24000);
realtime.send(JSON.stringify({
type: "input_audio_buffer.append",
audio: pcm16.toString("base64"),
}));
// giden: Realtime (24kHz PCM16) -> Twilio (8kHz μ-law)
const ulaw = muLawEncode(downsample(modelPcm16, 24000, 8000));
twilioWs.send(JSON.stringify({
event: "media",
media: { payload: ulaw.toString("base64") },
}));Tam çerçeve formatı Twilio Media Streams belgelerinde yer alır. Yeniden örneklemeyi ucuz tutun, çünkü buradaki ağır bir kütüphane her çerçevede ödeyeceğiniz gecikme ekler.
Adım 5: Sözünü Kesme ve Kesintileri Yönetme
Üretim ajanı, arayanın üzerine konuşmasına izin verir. Sözünü kesme (barge-in), ajan cümlenin ortasındayken arayanın konuşmaya başladığını algılamak ve ardından ajanı temiz bir şekilde kesmek demektir. Realtime API bunu response.cancel ile yönetir: sıra algılama, oynatma sırasında konuşmanın başladığını bildirdiğinde, etkin yanıtı iptal eder ve arayana doğru zaten arabelleğe alınmış sesi boşaltırsınız.
if (event.type === "input_audio_buffer.speech_started") {
realtime.send(JSON.stringify({ type: "response.cancel" }));
twilioWs.send(JSON.stringify({ event: "clear" })); // sıradaki oynatmayı at
}Sıra algılamanın iki modu vardır ve seçim önemlidir. server_vad, ham sessizlik eşiklerinde tetiklenir ve doğal duraklamalarda arayanı kesme eğilimindedir. semantic_vad, model arayanın gerçekten bir düşünceyi bitirdiğini düşünene kadar bekler, böylece bir düşünme duraklamasında çok daha az yanlış kesinti üretir. Telefon çağrıları için, insani hissettiren semantik VAD'dir.
Adım 6: Gecikmeyi Saniye Altına Ayarlama
Bir demonun bir ürüne dönüştüğü yer burası; işte teorik bir bütçe değil, kendi yapımımızdan rakamlar. Aynı restoran ajanını Mayıs 2026'da 40 test çağrısı üzerinde, OpenAI bölgesine yakın yerleştirilmiş tek küçük bir sunucuda, yalnızca sıra algılama ve akıl yürütme ayarlarını değiştirerek çalıştırdık.
| Yapılandırma | p50 gidiş-dönüş | p95 | Notlar |
|---|---|---|---|
| server_vad, reasoning low | ~1,4 s | ~2,3 s | duraklamalarda daha fazla yanlış kesinti |
| semantic_vad, reasoning low | ~1,1 s | ~1,9 s | üretim varsayılanımız |
| semantic_vad, reasoning medium | ~1,8 s | ~3,1 s | daha iyi araç doğruluğu, daha yavaş |
İğneyi gerçekten oynatan kaldıraçlar, etki sırasına göre:
reasoning.effort'u low'da tutun, belirli bir araç doğruluğa gerçekten ihtiyaç duymadıkça. Medium, p50'mizi neredeyse ikiye katladı.- Sesi gerçek zamandan daha hızlı itmeyin.
input_audio_buffer.append'i sel altında bırakmak arabelleği taşırır ve kayma yaratır; çerçeveleri duvar saatine göre ayarlayın. - Soketi sıcak tutun. Çağrı başına bir bağlantıyı soğuk açmak, el sıkışmayı ilk kelime gecikmenize ekler. Çağrı hacminin izin verdiği yerde bağlantıları havuzlayın.
- Verimli yeniden örnekleyin. Sıcak yoldaki naif bir yeniden örnekleyici bize tur başına ~80 ms ekledi.
Canlıya geçtiğinde dakika başına çalıştırma maliyeti nedir? Kendi anahtarını getir hesabını ayrı yaptık; burada yeniden türetmek yerine BYOK bir sesli ajanın dakika başına maliyetine bakın.
Adım 7: Dağıtma ve Üretim için Sağlamlaştırma
"Dizüstümde çalıştı" ile "günde 500 çağrıya dayanıyor" arasındaki boşluk, bir avuç bilinen arızadır. İşte Realtime ajanlarını gerçekten bozan hatalardan çıkarılmış sağlamlaştırma kontrol listesi:
| Tuzak | Belirti | Çözüm |
|---|---|---|
| Yanlış örnekleme hızı | bozuk / sincap sesi | her iki yönde 24 kHz PCM16 |
function_call_arguments.done'ı yok saymak | araçlar hiç tetiklenmez | dinleyin ve response.create gönderin |
| Sesi gerçek zamandan hızlı itmek | arabellek taşması, kayma | çerçeveleri gerçek zamana ayarlayın |
| Yeniden bağlanma mantığı yok | soket kesilmesinde çağrılar düşer | otomatik yeniden bağlanma + oturumu sürdür |
response.done işleme yok | çakışan turlar | sonraki turu response.done'a bağlayın |
Gerçek trafik için iki şey daha. Uzun çağrılarda, bağlamın kaymaması için oturumu birkaç turda bir döndürün veya yeniden tohumlayın, çünkü 20 dakikalık bir çağrı, modelin tökezlemeye başladığı durumu biriktirir. Ve her araç çağrısını argümanları ve sonucuyla kaydedin; bir arayan "ajan yanlış saati ayırttı" dediğinde, tek başına kayıt size modelin mi yoksa kodunuzun mu yanıldığını söylemez.
Adım 3'teki Agents SDK yolunu benimserseniz, yeni konteyner korumalı alanı araç kodunu yalıtılmış şekilde çalıştırır; bu da araçlarınız yalnızca bir API yerine bir dosya sistemine veya kabuğa dokunduğunda önem kazanır.
Bunun Yerine Ne Zaman Yönetilen Bir Platform Almalısınız
Doğrudan Realtime API üzerinde inşa etmek size en fazla kontrolü ve dakika başına en düşük maliyeti verir, ama yeniden bağlanma mantığı, telefon köprüsü, uyumluluk ve gözlemlenebilirlik, yani Adım 4'ten 7'ye kadar tüm cazip olmayan parçalar sizin sorumluluğunuzdadır. Bu hafta canlı bir telefon ajanına ihtiyacınız varsa ve bir medya aktarımını sürdürmek istemiyorsanız, yönetilen bir platform daha hızlı seçimdir.
Aynı ajanı üç büyük platformda kurduk ve dürüstçe karşılaştırdık: Retell, Vapi veya Bland. Çizginin hangi tarafında olduğunuza hâlâ karar veriyorsanız, mühendislik zamanı ayırmadan önce tam yap-ya-da-satın-al karar çerçevesinden geçin.
Ekipler, özel bir Realtime yapımının kontrolünü personel ayırmadan istediğinde, yaptığımız iş budur: telefon köprüsünden yukarıdaki gecikme ayarına kadar üretim için sesli ajan geliştirme. Tartıyorsanız kullanım senaryonuza bakmaktan memnuniyet duyarız.
Yazar hakkında — Mert Batur, ekibin B2B müşteriler için yapay zeka ajanları, otomasyon sistemleri ve ses/SDR hatları geliştirdiği Techsy.io'nun Kurucu Ortağıdır. Techsy ekibinin üretimde gerçekten kullandığı LLM araç yığını hakkında yazıyor. LinkedIn
Sıkça Sorulan Sorular
OpenAI Realtime API sesli ajanının gecikmesi nedir?
gpt-realtime-2, semantic_vad ve düşük akıl yürütme çabasıyla yapımımızda, gidiş-dönüş gecikmesi 40 test çağrısı üzerinde p50 1,1 s ve p95 1,9 s ölçtü. Tek soketteki konuşmadan konuşmaya, STT/LLM/TTS aktarımını önler; saniye altı yanıtları en başta mümkün kılan budur.
Sesli ajanım için WebRTC, WebSocket veya SIP'e mi ihtiyacım var?
Bir tarayıcı veya mobil uygulama mikrofonu doğrudan yakaladığında WebRTC, sunucunuzda zaten ham bir ses akışı olduğunda (Twilio köprü durumu) WebSocket ve telefon ayağını OpenAI'nin kendi medya aktarımınız olmadan halletmesini istediğinizde SIP kullanın. Çoğu telefon ajanı WebSocket veya SIP kullanır.
OpenAI Realtime API'yi Twilio'ya nasıl bağlarım?
Gelen bir Twilio çağrısını, sunucunuza bir WebSocket açan bir TwiML <Connect><Stream>'e yönlendirin, ardından sesi Twilio ile Realtime soketi arasında aktarın. Twilio'nun 8 kHz μ-law'unu API'nin 24 kHz PCM16'sına her iki yönde yeniden örnekleyin, yoksa ses bozuk çıkar.
Realtime API'de fonksiyon çağırma nasıl çalışır?
Araçları oturum yapılandırmasında tanımlarsınız. Model birini istediğinde, bir function_call_arguments.done olayı yayar. İşi çalıştırır, sonucu bir function_call_output konuşma öğesi olarak geri gönderir, ardından ajanın sonucu söylemesi için response.create gönderirsiniz. Bu son adımı unutmak, araçların neden sıklıkla "sessizce" başarısız olduğunun nedenidir.
Realtime API'de kesintileri (barge-in) nasıl yönetirsiniz?
Sıra algılama oynatma sırasında input_audio_buffer.speech_started bildirdiğinde, etkin yanıtı durdurmak için response.cancel gönderin ve arayana doğru arabelleğe alınmış çıktı sesini boşaltın. Doğal duraklamaların cümlenin ortasında yanlış kesintileri tetiklememesi için semantic_vad ile eşleştirin.
OpenAI Realtime API hangi ses örnekleme hızını kullanır?
Realtime API her iki yönde de 24 kHz PCM16 ses kullanır. Twilio gibi telefon sağlayıcıları 8 kHz μ-law iletir, bu yüzden bir telefon köprüsünün girişte yukarı, çıkışta aşağı yeniden örneklemesi gerekir. Uyumsuz örnekleme hızları, bozuk sesin en yaygın nedenidir.
Realtime API'de bir sesli ajan çalıştırmanın maliyeti nedir?
Maliyet, gpt-realtime-2 üzerindeki ses giriş ve çıkış dakikalarıyla belirlenir ve kendi anahtarını getir ekonomisi, dakika başına yönetilen bir platformdan keskin biçimde farklıdır. Burada tahmin etmek yerine tam hesabı sesli ajan fiyatlandırma dökümümüzde yaptık.
Realtime API üzerinde mi inşa etmeliyim yoksa Retell, Vapi veya Bland mı kullanmalıyım?
Maksimum kontrol ve dakika başına en düşük maliyet istediğinizde ve yeniden bağlanmaları, telefonu ve uyumluluğu üstlenebildiğinizde doğrudan inşa edin. Lansman hızı daha önemli olduğunda yönetilen bir platform alın. Retell vs Vapi vs Bland karşılaştırmamız ve yap-ya-da-satın-al çerçevesi ödünleşimleri kapsar.
Nisan 2026 OpenAI Agents SDK güncellemesi sesli ajanlar için neyi değiştirdi?
15 Nisan 2026 revizyonu, Model Context Protocol'ü birinci sınıf hale getirdi, araç kodu için bir konteyner korumalı alanı ekledi ve alt ajan devirlerini bir çalışma zamanı ilkeli haline getirdi. Sesli ajanlar için bu, bir yönlendirici ajanın her aracı tek bir isteme tıkıştırmak yerine uzmanlaşmış alt ajanlara devredebileceği anlamına gelir.