Selam, agent'ı start komutu ile başlatıp <https:/...
# ask-ai
a
Selam, agent'ı start komutu ile başlatıp https://agents-playground.livekit.io/ burada test edebilir miyim?
t
Thanks for reaching out, İbrahim. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Selam — sorunuz için teşekkürler. Sorunuza yanıt veriyorum: evet, LiveKit Agent’ı
start
komutuyla başlatabilirsiniz, ancak Agents Playground ile doğrudan test etmek için
start
doğru seçenek değildir. Kısa özet: •
start
: Üretim (production) amaçlıdır ve Playground ile doğrudan etkileşime girmez. •
dev
: Geliştirme ve test içindir; Agents Playground (https://agents-playground.livekit.io/) üzerinden test yapmak istiyorsanız ajanınızı bu modda çalıştırmanız gerekir. Test adımları (özet): 1. Ajanı
dev
modunda başlatın:
Copy code
uv run agent.py dev
1. Tarayıcıda https://agents-playground.livekit.io/ adresine gidin ve LiveKit Cloud projenizle oturum açın. 2. Ajanınız otomatik olarak odalara katılacak ve Playground üzerinden etkileşimli olarak test edebileceksiniz. Eğer isterseniz, şu bilgileri paylaşırsanız yardımcı olacak daha spesifik adımlar veya hata giderme önerileri verebilirim: • Hangi işletim sistemi / ortamda çalışıyorsunuz? • Ajanı başlatırken aldığınız herhangi bir hata mesajı var mı? • LiveKit Cloud projenizin ayarlarında özel bir yapılandırma var mı? Sources: Voice AI quickstart | LiveKit Documentation
a
dev ile çalıştııroyurm https://agents-playground.livekit.io/ ile token oluşturdum bağlanıyorum ama agent odaya katılmıyor bir türlü
t
Selam — mesajını ve yaşadığın sorunu anladım: agent’ı
dev
modunda çalıştırıyorsun, Playground’da token ile bağlanıyorsun fakat agent odaya katılmıyor. Aşağıda kısa, uygulanabilir kontrol adımları ve hangi bilgileri paylaşırsan daha hızlı yardımcı olabileceğim yer alıyor. Hemen kontrol etmen gerekenler • Agent gerçekten
dev
modunda mı çalışıyor? ◦ Terminalde
uv run agent.py dev
(veya Node ise
pnpm dev
) komutunu çalıştırdığını doğrula. ◦ Terminalde hata veya “listening for jobs” gibi loglar görünüyor mu? •
agent_name
kullanıyor musun? ◦ Eğer kodunda
@server.rtc_session(agent_name="...")
gibi bir kullanım varsa agent yalnızca açıkça dispatch edildiğinde odaya katılır. Bu durumda token ile otomatik katılmaz. ◦ Eğer
agent_name
yoksa (yani
@server.rtc_session()
), agent yeni odalara otomatik katılır. • Token oluştururken agent dispatch ekledin mi? ◦ Sadece kullanıcı token’ı odaya sokar; agent’ı dispatch etmek için token’a
RoomConfiguration
içinde
agents=[RoomAgentDispatch(...)]
gibi bir yapı eklemelisin. Aksi halde agent dispatch edilmez. • Ortam değişkenleri doğru mu? ◦
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
,
LIVEKIT_URL
değerlerinin doğru ve güncel olduğundan emin ol. • Oda adını doğru mu kullandın? ◦ Oda isimlerinde küçük/büyük harf duyarlılığı veya boşluk/özel karakter farkı olabilir. Hızlı test/çözüm önerileri 1. Geçici olarak
agent_name
parametresini kaldırıp agent’ı tüm odalara katılacak şekilde başlat: ◦ Böylece Playground’da oluşturduğun oda geldiğinde agent otomatik katılmalı. 1. Token üretirken agent dispatch ekle (Python örneği):
Copy code
from livekit.api import AccessToken, RoomConfiguration, RoomAgentDispatch

   token = (
       AccessToken()
       .with_identity("user123")
       .with_grants(VideoGrants(room_join=True, room="your-room-name"))
       .with_room_config(
           RoomConfiguration(
               agents=[RoomAgentDispatch(agent_name="test-agent", metadata='{"user":"123"}')]
           )
       )
       .to_jwt()
   )
1. CLI ile manuel dispatch (varsa): ◦
lk dispatch create --room your-room-name --agent-name test-agent
Ne paylaşırsan daha detaylı yardımcı olurum • Agent kodundan ilgili kısım (
rtc_session
decorator ve
agent_name
kullanımı) • Token üretme yönteminin kodu veya açıklaması • Çalıştırdığın komut (tam olarak ne yazdın terminale) • Terminal log çıktılarından ilgili satırlar • Oda adı (gizli tutmak istiyorsan maskelenmiş versiyon) Paylaşırsan adım adım birlikte inceleyip agent’ın odalara katılmasını sağlayalım. Sources: Agent dispatch | LiveKit Documentation | Voice AI quickstart | LiveKit Documentation
a
Eğer kodunda
@server.rtc_session(agent_name="...")
gibi bir kullanım varsa agent yalnızca açıkça dispatch edildiğinde odaya katılır. Bu durumda token ile otomatik katılmaz. Evet var: test-agent agent'ın adı. Sadece kullanıcı token’ı odaya sokar; agent’ı dispatch etmek için token’a
RoomConfiguration
içinde
agents=[RoomAgentDispatch(...)]
gibi bir yapı eklemelisin. Aksi halde agent dispatch edilmez. Bunu nasıl yapacağım? Sadece lk token create ile token oluşturuyorum
t
Teşekkürler — durumu netleştirdin: agent adı
test-agent
ve şu an tokenları
lk token create
ile üretiyorsun. Kısa ve net cevap: •
lk token create
komutu agent dispatch eklemeyi desteklemez. Bu yüzden sadece bu CLI ile token oluştursan bile agent otomatik olarak odaya katılmaz. • Agent adı belirtildiği için (
@server.rtc_session(agent_name="test-agent")
) agent’ın odaya katılması için açık bir dispatch yapılması gerekir. Ne yapabilirsin (iki yol) 1) Programatik olarak token oluşturup agent dispatch eklemek (önerilen) • SDK/HTTP API kullanarak token oluştururken
RoomConfiguration
içine
agents=[RoomAgentDispatch(...)]
eklemen gerekir. Bu token hem kullanıcıyı odaya sokar hem de `test-agent`i dispatch eder. • Örnek (Python, kısa):
Copy code
from livekit import api
from livekit.api import RoomAgentDispatch, RoomConfiguration

token = (
    api.AccessToken(api_key="YOUR_KEY", api_secret="YOUR_SECRET", identity="user123")
    .with_grants(api.VideoGrants(room_join=True, room="my-room"))
    .with_room_config(
        RoomConfiguration(
            agents=[RoomAgentDispatch(agent_name="test-agent", metadata='{"user":"123"}')]
        )
    )
    .to_jwt()
)
print(token)
• İstersen Node.js veya Go örneğini de gönderirim. 2) CLI ile ayrı bir dispatch işlemi yapmak (hızlı alternatif) • Kullanıcı tokenını ayrı oluşturup odaya bağlandıktan sonra veya öncesinde, agent’ı manuel dispatch edebilirsin:
Copy code
lk dispatch create --agent-name test-agent --room my-room --metadata '{"user_id":"12345"}'
• Bu komut agent’ı belirtilen odaya atar; kullanıcı token ile odaya bağlanınca agent da odada olur. Eğer istersen birini adım adım yapalım • Hangi dili kullanıyorsun (Python/Node/Go)? O dil için tam, kopyala-yapıştır çalışacak örnek vereyim. • Veya CLI ile manuel dispatch denemek istersen oda adını söyle, gerekli
lk
komutunu tam şeklinde veririm. • Ayrıca terminal loglarını paylaşırsan (agent dev modunda çalışırken) birlikte kontrol ederiz. Hangi yolu tercih ediyorsun? Benimle dilini söyle, örneği hemen gönderirim. Sources: Agent dispatch | LiveKit Documentation
a
dev'de veya connect'de stt, tts ve llm'in tftf'yi göremiyorum. O yüzden start ile yapmak istemiştim nasıl görürüm bıunları
t
Selam — sorununu anladım:
dev
veya
connect
modunda STT, TTS ve LLM çıktısını (ve özellikle TTFT/TTFB gibi metrikleri) göremiyorsun ve bu yüzden
start
ile denemek istemişsin. Kısa cevap ve kesin yol haritası aşağıda. Özet (kısa) •
start
modu üretim içindir; interaktif test çıktıları genelde görünmez. Bu yüzden
start
ile denemek problemi çözmez. • STT, TTS ve LLM çıktıları ve TTFT/TTFB metrikleri en rahat şekilde
console
(lokal mock) veya
dev
modunda ve bir frontend (ör. Agents Playground) ile görülebilir. • Eğer agent kodunda
agent_name = "test-agent"
varsa, agent sadece açıkça dispatch edildiğinde odaya katılır; bu da test akışını etkileyebilir. Ne kontrol etmen gerekiyor (adım adım) 1) Hangi modda çalışıyorsun? • Test için: önce
console
ile yerelde deneyip log/transkript çıktısını gör. ◦ Komut:
uv run agent.py console
• Gerçek ortam testi için:
uv run agent.py dev
ve Agents Playground kullan. 2) Frontend kullanıyor musun? • STT transkriptleri, TTS ses çıkışı ve LLM yanıtı genelde frontende (Agents Playground veya kendi frontend’in) görünür. Sadece agent terminaline bakmak bazen yeterli olmayabilir. • Öneri: https://agents-playground.livekit.io/ adresine bağlan ve aynı LiveKit projesi ile oturum aç. 3) Agent konfigürasyonunda
text_output
etkin mi? • Oturum başlatılırken
RoomOptions(text_output=True)
veya benzeri bir ayar olması gerekiyor ki transkript/LLM metin çıktıları toplanıp gönderilsin. 4) Agent gerçekten dispatch ediliyor mu? • Eğer kodda
@server.rtc_session(agent_name="test-agent")
varsa agent otomatik katılmaz. Ya token ile
RoomConfiguration
içinde agent dispatch eklemelisin ya da CLI ile manuel dispatch yap: ◦ Manuel dispatch (CLI):
lk dispatch create --agent-name test-agent --room my-room --metadata '{"user_id":"12345"}'
5) Metrikleri görmek: • TTFT/TTFB gibi metrikler, çalışır bir oturum ve gerçek LLM/TTS çağrıları olduğunda toplanır.
dev
modunda metrik olaylarını dinleyerek görebilirsin: ◦ Örneğin
MetricsCollected
olayını dinle ve logla. Hızlı problemlere dayalı çözümler • Hiçbir şey görünmüyorsa: büyük olasılıkla ya frontend yok ya da agent dispatch edilmemiş. • Eğer
dev
modunda çalışıyor ama frontende hiçbir çıktı gelmiyorsa: .env değişkenlerini (
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
,
LIVEKIT_URL
) ve agent loglarını kontrol et. • Konsolda hızlı test istiyorsan:
console
modu ile transkripsiyon ve TTS çıktısını gör. Bana söyleyince adım adım yardımcı olabilirim • Hangi modu kullandın şu anda? (
console
,
dev
veya
start
) • Agents Playground mu yoksa kendi frontend’in mi kullanılıyor? • Agent kodundan şu kısımları paylaşırsan hızlıca bakarım:
@server.rtc_session(...)
dekoratörü satırı ve varsa `RoomOptions`/başlatma ayarları. •
dev
çalıştırırken terminal logunda hangi mesajlar görünüyor? (özellikle hata veya “listening for jobs” vb.) Tercih ettiğin yolu söyle: hızlı bir
console
testiyle mi ilerleyelim, yoksa
dev
+ Playground’da agent dispatch akışını mı beraber kurup kontrol edelim? Sources: Simple Call Answering Agent | LiveKit Documentation | Voice AI quickstart | LiveKit Documentation | Agents playground | LiveKit Documentation | Server options | LiveKit Documentation | Agents (Node.js) | livekit/livekit_composite | DeepWiki
a
MetricsCollected
Bunları loglayacağım basit kodu yazar mısın?
t
Harika — MetricsCollected olayını loglamak istediğini anladım. Aşağıda LiveKit Agent oturumundan gelen metrikleri (ör. TTFT, TTFB, duration, token sayıları) basitçe konsola yazdıracak, doğrudan kullanabileceğin bir Python örneği var. Agent koduna kolayca ekleyebilirsin. Not: Bu örnekte
session
senin
AgentSession
örneğin olmalı;
dev
veya
console
modunda çalışırken bu olaylar tetiklenir.
Copy code
import asyncio
from datetime import datetime

# Örnek async handler: MetricsCollected olayını loglar
async def handle_metrics_collected(event):
    m = event.metrics
    now = datetime.utcnow().isoformat()
    print(f"[MetricsCollected] {now}")
    # Örnek alanlar; agent/session kitaplığına göre isimler küçük farklılık gösterebilir
    print(f"  Source: {getattr(event, 'source', 'unknown')}")
    print(f"  TTFT: {getattr(m, 'ttft', 'N/A')} s")
    print(f"  TTFB: {getattr(m, 'ttfb', 'N/A')} s")
    print(f"  Duration: {getattr(m, 'duration', 'N/A')} s")
    print(f"  Prompt tokens: {getattr(m, 'prompt_tokens', 'N/A')}")
    print(f"  Completion tokens: {getattr(m, 'completion_tokens', 'N/A')}")
    print(f"  Timestamp: {getattr(m, 'timestamp', 'N/A')}")
    print("-" * 40)

# session: AgentSession örneği (kendi kodunda zaten oluşturulmuş olmalı)
# session.on ile event adını ve handler'ı kaydet
# Event adlandırması kullandığın SDK sürümüne göre değişebilir; örnek: "metrics_collected" veya AgentSessionEventTypes.MetricsCollected
def attach_metrics_logger(session):
    try:
        # Eğer SDK string event isimleri kullanıyorsa:
        session.on("metrics_collected", handle_metrics_collected)

        # Veya enum/const kullanılıyorsa (örnek kullanım, SDK'na uyarlayın):
        # from livekit.agents import AgentSessionEventTypes
        # session.on(AgentSessionEventTypes.MetricsCollected, handle_metrics_collected)

        print("MetricsCollected handler eklendi.")
    except Exception as e:
        print("MetricsCollected handler eklenirken hata:", e)
Nasıl entegre edersin • Agent oturumunu başlattıktan sonra (
session
oluşturulduktan hemen sonra)
attach_metrics_logger(session)
çağrısını yap. •
dev
modunda gerçek çağrılar yapıldığında veya
console
modunda mock çağrılarla, terminalde metrik loglarını göreceksin. İstersen ben: • Kullandığın agent SDK sürümü/isimleri (ör.
livekit.agents
vs başka) ile örneği tam olarak uyarlayayım. • Node.js örneğine de çevireyim (eğer Node kullanıyorsan). Hangi dili/sürümü kullanıyorsun? Hemen uyarlayıp gönderirim. Sources: LLM Metrics | LiveKit Documentation | TTS Metrics | LiveKit Documentation | STT Metrics | LiveKit Documentation | VAD Metrics | LiveKit Documentation
a
{"message": "RealtimeModel metrics", "level": "INFO", "name": "livekit.agents", "model_name": "gemini-live-2.5-flash-native-audio", "model_provider": "Vertex AI", "ttft": -1.0, "input_tokens": 5810, "cached_input_tokens": 0, "input_text_tokens": 5202, "input_cached_text_tokens": 0, "input_image_tokens": 0, "input_cached_image_tokens": 0, "input_audio_tokens": 608, "input_cached_audio_tokens": 0, "output_tokens": 46, "output_text_tokens": 46, "output_audio_tokens": 0, "output_image_tokens": 0, "total_tokens": 5856, "tokens_per_second": 102.52, "pid": 129, "job_id": "AJ_XgKqbxTfVoLc", "room_id": "RM_YVpXykHGKUUd", "timestamp": "2026-02-15T191803.021074+00:00"} Bunları livekitin kendisi gösteriyordu ya aslında ya onu istiyorum ben
t
Anladım — paylaştığın JSON log örneği (RealtimeModel metrics) tam olarak LiveKit’in gösterdiği türden metrikler: TTFT, token sayıları, vs. ve senin istediğin, bunları LiveKit’in kendi arayüzünde görmektin. Kısa cevap ve yapman gerekenler aşağıda. Özet • Evet — LiveKit bu metrikleri kendi UI’sinde görselleştiriyor (Agent Observability / Agent Insights). • Bu görünümü almak için: a. LiveKit Cloud kullanıyor olmalısın (self‑hosted bunu sunmuyor). b. Project/Session kayıt( recording ) ve Observability açık olmalı. c. Agent oturumu
record=True
ile başlatılmalı veya proje ayarından kaydı etkinleştirmelisin. • Sonrasında LiveKit Cloud Dashboard → ilgili room → “Agent insights”/Observability bölümünde TTFT, TTFB, token sayıları, timeline ve senkronize logları görürsün. Yapman gerekenler — adım adım 1) LiveKit Cloud’da proje ayarları • Dashboard’a gir → Project Settings → Data and Privacy (veya Recording / Observability) bölümünü aç. • “Record sessions” ve “Enable Agent Observability” seçeneklerini aktif hale getir. 2) Agent oturumunda kayıtı etkinleştir • Agent kodunda AgentSession/başlatma kısmında
record=True
ayarla:
Copy code
session = AgentSession(..., record=True)
• Eğer kodda
record=False
ise observability verisi toplanmaz. 3) Agent’ı deploy / çalıştır ve oturumu oluştur •
dev
modunda test et:
uv run agent.py dev
• Agent’in odaya katıldığını ve job’ların tetiklendiğini doğrula (terminal logları “listening for jobs” vb). 4) Dashboard’dan izle • LiveKit Cloud’a gir, ilgili room’u aç. • “Agent insights” veya “Observability” sekmesini seç. • Timeline’da audio + transcript + turn bazlı trace, TTFT/TTFB, token sayıları ve eş zamanlı logları göreceksin. Eğer self‑hosted kullanıyorsan • Bu yerleşik Agent Observability şu an sadece LiveKit Cloud’da mevcut. Self‑hosted isen, aynı görselliği elde etmek için: ◦
MetricsCollected
olaylarını dinleyip (kodda) bu metrikleri bir telemetry servisine (Prometheus/Grafana, Loki, Datadog vb.) gönderip dashboard oluşturman gerekir. ◦ İstersen sana örnek Grafana panosu veya Prometheus export kodu gösterebilirim. Hızlı doğrulama / yardım için bana gönder • Projeyi LiveKit Cloud’da mı kullanıyorsun yoksa self‑hosted mi? • Agent kodundan ilgili kısım (AgentSession oluşturma /
record
ayarı) varsa paylaş — hızlıca kontrol edip düzeltilmesi gereken kısmı söyleyeyim. • Dashboard’da ilgili room’u açtığında hangi sekmeleri görüyorsun? “Agent insights” görünmüyor mu yoksa boş mu? İstersen şimdi: • LiveKit Cloud kullanıyorsan seni adım adım yönlendirip hangi ayarı açacağımızı tam gösteririm. • Self‑hosted isen hemen bir örnek ile
MetricsCollected
verilerini Prometheus/Grafana’a nasıl aktaracağına dair kod ve dashboard örneği verebilirim. Hangi ortamdasın (Cloud mı self‑hosted?) söyle, hemen ilerleyelim. Sources: Streamline troubleshooting with Agent Observability | Streamline troubleshooting with Agent Observability | Streamline troubleshooting with Agent Observability | examples/voice_agents | livekit/livekit_composite | DeepWiki | TTS Metrics | LiveKit Documentation
a
selfhosted çalışıyorum
t
Teşekkürler — self‑hosted kullandığını not ettim. LiveKit Cloud’daki yerleşik “Agent Observability” görselleştirmesi self‑hosted dağıtımlarda mevcut değil. Ancak aynı veriyi alıp kendinize ait gerçek‑zamanlı gösterge panosu kurabilirsiniz. Aşağıda en pratik ve uygulanabilir seçenekleri, adım adım ne yapman gerektiğini ve kullanabileceğin örnek kodları veriyorum. Kısa özet • LiveKit Cloud: built‑in Agent Insights (timeline, TTFT, TTFB, token sayıları) mevcut. • Self‑hosted: bu UI yok; ama
MetricsCollected
olaylarını dinleyip bu metrikleri Prometheus/Grafana, OpenTelemetry, Loki vb. sistemlere göndererek benzer bir gösterge panosu oluşturabilirsin. • Aşağıda önerilen akış: Agent içinde metrikleri yakala → uygun exporter ile telemetry sistemine gönder → Grafana/Loki ile görselleştir. Önerilen seçenekler (tercihe göre) • Hızlı & yaygın: Prometheus + Grafana (metrikler sayısal; TTFT, TTFB, token sayıları vs.) • Log odaklı: Loki + Grafana (detaylı JSON log’lar, timeline aramaları) • Tam izleme: OpenTelemetry → Jaeger/Tempo + Prometheus + Grafana (trace + metrics) • Basit: Doğrudan JSON log dosyalarına yazıp `jq`/kibana/elk ile incele (geçici) Adım adım uygulama (Prometheus + Grafana örneği) 1) MetricsCollected olaylarını yakala (örnek: Python) • Agent oturumunu oluşturduğun yerde event handler ekle. • Handler içinde metrikleri Prometheus client ile güncelle. 2) Prometheus exporter çalıştır: • Agent ile aynı host veya sidecar olarak bir HTTP endpoint aç (ör. :8000/metrics). • Prometheus bu endpoint’i scrape edecek. 3) Grafana’da dashboard oluştur: • TTFT, TTFB, tokens per call, calls/sec, error rate gibi paneller kur. Python örneği (Prometheus exporter) — doğrudan kopyala/yapıştır
Copy code
# metrics_exporter.py
from prometheus_client import start_http_server, Gauge, Counter
import asyncio
import time
from datetime import datetime

# Prometheus metric tanımları
TTFT = Gauge('agent_ttft_seconds', 'Time to first token', ['agent_name', 'room_id', 'model'])
TTFB = Gauge('agent_ttfb_seconds', 'Time to first byte (TTS)', ['agent_name', 'room_id', 'model'])
DURATION = Gauge('agent_duration_seconds', 'Processing duration', ['agent_name', 'room_id', 'model'])
INPUT_TOKENS = Gauge('agent_input_tokens', 'Input tokens', ['agent_name', 'room_id', 'model'])
OUTPUT_TOKENS = Gauge('agent_output_tokens', 'Output tokens', ['agent_name', 'room_id', 'model'])
TOTAL_TOKENS = Gauge('agent_total_tokens', 'Total tokens', ['agent_name', 'room_id', 'model'])
REQUESTS = Counter('agent_requests_total', 'Total inference requests', ['agent_name', 'model', 'status'])

# Basit metrics logger / handler
async def handle_metrics_collected(event):
    m = event.metrics
    labels = {
        'agent_name': getattr(event, 'agent_name', 'unknown'),
        'room_id': getattr(event, 'room_id', 'unknown'),
        'model': getattr(event, 'model_name', getattr(m, 'model_name', 'unknown'))
    }
    # Safely al (bazı alanlar eksik olabilir)
    try:
        if getattr(m, 'ttft', None) is not None and m.ttft >= 0:
            TTFT.labels(**labels).set(m.ttft)
        if getattr(m, 'ttfb', None) is not None and m.ttfb >= 0:
            TTFB.labels(**labels).set(m.ttfb)
        if getattr(m, 'duration', None) is not None:
            DURATION.labels(**labels).set(m.duration)
        if getattr(m, 'input_tokens', None) is not None:
            INPUT_TOKENS.labels(**labels).set(m.input_tokens)
        if getattr(m, 'output_tokens', None) is not None:
            OUTPUT_TOKENS.labels(**labels).set(m.output_tokens)
        if getattr(m, 'total_tokens', None) is not None:
            TOTAL_TOKENS.labels(**labels).set(m.total_tokens)

        # Basit request sayacı (hata durumu da varsa 'status' label'ı ver)
        REQUESTS.labels(agent_name=labels['agent_name'], model=labels['model'], status='ok').inc()
    except Exception as e:
        # Hata sayacı
        REQUESTS.labels(agent_name=labels['agent_name'], model=labels['model'], status='error').inc()
        print("Metrics handler error:", e)

def attach_metrics_exporter(session, port=8000):
    # Prometheus exporter'ı başlat
    start_http_server(port)
    print(f"Prometheus exporter started on :{port}")
    # SDK event kaydı. SDK event ismi sürüme göre değişir: "metrics_collected" veya enum kullan
    session.on("metrics_collected", lambda ev: asyncio.create_task(handle_metrics_collected(ev)))
    print("MetricsCollected handler attached.")
Nasıl entegre edilir 1. Agent kodunda AgentSession oluşturduktan sonra
attach_metrics_exporter(session, port=8000)
çağr. 2. Prometheus konfigürene şu scrape job’u ekle:
Copy code
scrape_configs:
  - job_name: 'livekit_agents'
    static_configs:
      - targets: ['<agent-host>:8000']
1. Grafana’da Prometheus datasource ekle; örnek paneller oluştur: ◦ TTFT (avg/min/max): avg(agent_ttft_seconds) by (agent_name) ◦ Token kullanımı: sum(agent_total_tokens) by (agent_name) Alternatif: Log bazlı (Loki) veya OpenTelemetry • Eğer JSON log’ları zaten üretiyorsan, Loki’ye gönderip Grafana’da zaman çizelgesi + log detay paneli oluşturabilirsin. • OpenTelemetry kullanıyorsan traces + metrics toplayıp Tempo/Jaeger + Prometheus ile daha zengin izleme kurabilirsin. Ek notlar / pratik ipuçları • Metrik isimlerini ve label’ları iyi seç; yüksek cardinality’den kaçının (ör. kullanıcı id’sini label yapma). • TTFT bazen -1 veya None olabilir (henüz token gelmemiş). Filtrele veya grafikte ignore et. • Eğer agent’ları container olarak çalıştırıyorsan exporter’ı sidecar container olarak da deploy edebilirsin. • Logları da koru: timeline araması için log + metrics ikilisi en faydalısıdır. Sonraki adım — nasıl yardım edeyim? • Hangi dili kullanıyorsun: Python, Node.js veya Go? (Yukarı örnek Python.) • Zaten Prometheus/Grafana kullanıyor musun yoksa sıfırdan mı kuracağız? • Agent kodundan
AgentSession
başlatma kısmını paylaşırsan, sana tam çalışır halde bir entegrasyon snippet’i hazırlayıp verebilirim (sidecar veya aynı process, tercihine göre). Hangisini istersin? Python örneğini Node/Go’ya çevireyim ya da Prometheus/Grafana konfigürasyon dosyalarını hazır çıkarayım.
a
asyncio.create_task kullan diyo hata veriyor .on yerine
t
Harika — sorunu netleştirdin:
.on(...)
ile event aboneliği yaparken asenkron handler’ı doğrudan vermek hata veriyor çünkü
.on
senkron bir callable bekliyor. Çözüm: senkron bir wrapper içinden
asyncio.create_task(...)
ile asenkron handler’ı arka planda başlatmak. Aşağıda doğrudan kopyala-yapıştır kullanabileceğin, eksiksiz ve basit bir Python örneği var. Bu örnek: •
MetricsCollected
olayını dinliyor, • asenkron
handle_metrics
fonksiyonunu
asyncio.create_task
ile çalıştırıyor, • Prometheus exporter ekleme isteğine uygun olarak (isteğe bağlı) console’a log da yazıyor. Kod (örnek, Python):
Copy code
import asyncio
from datetime import datetime

# Bu örnekte event nesnesinin .metrics alanı olduğunu varsayıyoruz.
# SDK sürümüne göre event isimleri/alanlar değişebilir; gerekirse uyarlayalım.

async def handle_metrics(event):
    """Asenkron iş yapan gerçek handler"""
    m = event.metrics
    now = datetime.utcnow().isoformat()
    # Güvenli erişim için getattr kullanıyoruz (bazı alanlar olmayabilir)
    ttft = getattr(m, "ttft", None)
    ttfb = getattr(m, "ttfb", None)
    duration = getattr(m, "duration", None)
    input_tokens = getattr(m, "input_tokens", None)
    output_tokens = getattr(m, "output_tokens", None)

    # Burada istediğin işlemi yap: DB'ye yaz, Prometheus'a gönder, dosyaya logla vb.
    print(f"[Metrics] {now} room={getattr(event, 'room_id', 'unknown')} model={getattr(event, 'model_name', 'unknown')}")
    if ttft is not None:
        print(f"  TTFT: {ttft}s")
    if ttfb is not None:
        print(f"  TTFB: {ttfb}s")
    if duration is not None:
        print(f"  Duration: {duration}s")
    if input_tokens is not None or output_tokens is not None:
        print(f"  Tokens - in: {input_tokens} out: {output_tokens}")
    # Örnek: bekleyip async I/O yapma
    await asyncio.sleep(0)  # placeholder, gerçek async iş burada olabilir

def metrics_wrapper(event):
    """.on(...) için senkron wrapper — asenkron handler'ı arka planda çalıştırır."""
    try:
        asyncio.create_task(handle_metrics(event))
    except RuntimeError:
        # Eğer event loop yoksa (ör. module import sırasında), loop başlat veya logla
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.create_task(handle_metrics(event))

def attach_metrics_listener(session):
    """
    session: SDK'daki AgentSession veya ilgili nesne.
    .on event kayıt yöntemi SDK'ya göre farklı olabilir (string veya enum).
    Örnek: session.on("metrics_collected", metrics_wrapper)
    veya component bazında: session.llm.on("metrics_collected", metrics_wrapper)
    """
    # Örnek: genel oturum event'i
    try:
        session.on("metrics_collected", metrics_wrapper)
        print("MetricsCollected handler eklendi (wrapper ile).")
    except Exception as e:
        print("Handler eklenirken hata:", e)
Kullanım: 1. Agent oturumu oluşturduktan hemen sonra
attach_metrics_listener(session)
çağr. 2.
dev
veya
console
modunda test ederken event tetiklendiğinde arka planda
handle_metrics
çalışacak ve log/işlem yapılacaktır. Notlar ve küçük ipuçları •
.on
bazen component bazında olabilir (ör.
session.llm.on(...)
,
session.tts.on(...)
,
session.stt.on(...)
). Hangi component’in event verdiğini SDK dokümanına göre kontrol et. •
asyncio.create_task
çağrısı, mevcut event loop içinde çalıştırır. Eğer wrapper bir thread içinde veya event loop yokken çağrılıyorsa
RuntimeError
alırsın; örnekte bunun için basit bir fallback ekledim. • Eğer metrikleri Prometheus’a göndereceksek
handle_metrics
içinde Prometheus client güncellemesi yap; bu da asenkron olarak güvenli çalışır. • TTFT bazen -1 veya None olabilir — bunu filtrele veya grafikte ignore et. İstersen hemen: • Kullandığın SDK sürümünü ve event aboneliğini nasıl yapmaya çalıştığını paylaş; kodu tam olarak senin ortamına göre uyarlayıp test edilebilir bir snippet atayım. • Prometheus/Grafana entegrasyonu istersen,
handle_metrics
içinde örnek Prometheus güncellemesi ile tam entegrasyon kodu vereyim. Hangi yolu istersin — doğrudan loglayalım mı yoksa Prometheus’a export eden tam örneği mi hazırlayayım? Sources: LLM Metrics | LiveKit Documentation | STT Metrics | LiveKit Documentation | TTS Metrics | LiveKit Documentation | VAD Metrics | LiveKit Documentation | Agents (Node.js) | livekit/livekit_composite | DeepWiki
a
attach_metrics_listener(session)
t
Harika — isteğin net:
attach_metrics_listener(session)
fonksiyonunu tam çalışan bir örnek içinde görmek istiyorsun; nerede çağrılacağını,
session
oluşturma ve eventlerin nasıl bağlanacağını gösteren eksiksiz bir Python örneği vereyim. Bu örnek self‑hosted ortamda çalışacak şekilde
asyncio.create_task
ile asenkron handler’ları arka planda çalıştırır ve konsola log basar. İstersen bu örneği Prometheus/Grafana exporter eklemesiyle de genişletebilirim. Aşağıdaki tam örnek: • Agent oturumunu oluşturur (örnek bir AgentSession/Session placeholder kullandım — kendi SDK kullanımına göre ufak isim uyarlamaları gerekebilir). •
attach_metrics_listener(session)
çağrısını doğru yerde yapar. •
metrics_collected
olayını senkron wrapper +
asyncio.create_task
ile işler. Not: SDK sürümüne göre event isimleri
metrics_collected
veya enum/const olabilir; eğer session.llm, session.tts, session.stt gibi alt bileşenler varsa onlara bağlamak daha doğru olabilir. Gerekirse ben senin kullandığın SDK sürümüne göre uyarlayayım. Kod (tam örnek):
Copy code
import asyncio
from datetime import datetime

# --- Basit metrics handler'ları ---
async def handle_llm_metrics(event):
    m = event.metrics
    now = datetime.utcnow().isoformat()
    print(f"[LLM Metrics] {now} room={getattr(event, 'room_id', 'unknown')} model={getattr(event, 'model_name', 'unknown')}")
    print(f"  TTFT: {getattr(m, 'ttft', 'N/A')}")
    print(f"  Duration: {getattr(m, 'duration', 'N/A')}")
    print(f"  Prompt tokens: {getattr(m, 'prompt_tokens', 'N/A')}")
    print(f"  Completion tokens: {getattr(m, 'completion_tokens', 'N/A')}")
    print("-" * 40)
    await asyncio.sleep(0)  # placeholder for async I/O (DB, exporter, vb.)

async def handle_tts_metrics(event):
    m = event.metrics
    now = datetime.utcnow().isoformat()
    print(f"[TTS Metrics] {now} room={getattr(event, 'room_id', 'unknown')}")
    print(f"  TTFB: {getattr(m, 'ttfb', 'N/A')}")
    print(f"  Duration: {getattr(m, 'duration', 'N/A')}")
    print("-" * 40)
    await asyncio.sleep(0)

async def handle_stt_metrics(event):
    m = event.metrics
    now = datetime.utcnow().isoformat()
    print(f"[STT Metrics] {now} room={getattr(event, 'room_id', 'unknown')}")
    print(f"  Duration: {getattr(m, 'duration', 'N/A')}")
    print("-" * 40)
    await asyncio.sleep(0)

# --- Wrapper'lar: .on(...) sync callable beklediği için asyncio.create_task kullanıyoruz ---
def attach_metrics_listener(session):
    """
    session: AgentSession nesnesi (kendi SDK'na göre isim farklı olabilir).
    Bu fonksiyon session üzerinde metrics event'lerini dinler.
    """
    # Eğer SDK component bazlı event veriyorsa session.llm/tts/stt kullan:
    try:
        # LLM metrics
        session.llm.on("metrics_collected", lambda ev: asyncio.create_task(handle_llm_metrics(ev)))
    except Exception:
        # Eğer session.llm yoksa genel event üzerinden dinle
        try:
            session.on("llm_metrics_collected", lambda ev: asyncio.create_task(handle_llm_metrics(ev)))
        except Exception:
            pass

    # TTS metrics
    try:
        session.tts.on("metrics_collected", lambda ev: asyncio.create_task(handle_tts_metrics(ev)))
    except Exception:
        try:
            session.on("tts_metrics_collected", lambda ev: asyncio.create_task(handle_tts_metrics(ev)))
        except Exception:
            pass

    # STT metrics
    try:
        session.stt.on("metrics_collected", lambda ev: asyncio.create_task(handle_stt_metrics(ev)))
    except Exception:
        try:
            session.on("stt_metrics_collected", lambda ev: asyncio.create_task(handle_stt_metrics(ev)))
        except Exception:
            pass

    print("attach_metrics_listener: handler'lar eklendi.")

# --- Tam bir örnek giriş noktası (entrypoint) ---
async def main():
    """
    Burada session oluşturma yerini kendi agent koduna göre uyarla.
    Örneğin:
      - session = AgentSession(...) 
      - veya agent = MyAgent(...) ve agent.session
    """
    # --- Placeholder: kendi SDK ile değiştir ---
    # from livekit.agents import AgentSession
    # session = AgentSession(...) 
    session = create_fake_session_for_example()  # sadece örnek, kendi session'ını kullan

    # Metrics listener'ı ekle
    attach_metrics_listener(session)

    # Start / connect agent session; kendi kodunda bu farklı olabilir
    # Ör: await session.start(...) veya await agent.run(...)
    try:
        await session.start()  # kendi SDK çağrınla değiştir
    except AttributeError:
        # Eğer örnek session fake ise, sadece bekle
        print("Session.start() çağrısı örnek için atlandı.")

    # Örnek: sonsuz bekle (gerçek agent çalışırken event'ler tetiklenecek)
    while True:
        await asyncio.sleep(60)

# --- Örnek placeholder session (sadece demo, gerçek kodunda kaldır) ---
class FakeEvent:
    def __init__(self, metrics, room_id="RM_demo", model_name="demo-model"):
        self.metrics = metrics
        self.room_id = room_id
        self.model_name = model_name

class FakeMetrics:
    def __init__(self, ttft=None, ttfb=None, duration=None, prompt_tokens=None, completion_tokens=None):
        self.ttft = ttft
        self.ttfb = ttfb
        self.duration = duration
        self.prompt_tokens = prompt_tokens
        self.completion_tokens = completion_tokens

class FakeComponent:
    def __init__(self):
        self._handlers = {}

    def on(self, event_name, handler):
        self._handlers.setdefault(event_name, []).append(handler)

    # test için event tetikle
    def emit(self, event_name, ev):
        for h in self._handlers.get(event_name, []):
            h(ev)

class FakeSession:
    def __init__(self):
        self.llm = FakeComponent()
        self.tts = FakeComponent()
        self.stt = FakeComponent()

    async def start(self):
        # örnek: çalıştıktan sonra periyodik test event'i gönder
        await asyncio.sleep(1)
        # test metrics
        m1 = FakeMetrics(ttft=0.12, duration=1.3, prompt_tokens=120, completion_tokens=30)
        self.llm.emit("metrics_collected", FakeEvent(m1))
        await asyncio.sleep(1)
        m2 = FakeMetrics(ttfb=0.25, duration=0.8)
        self.tts.emit("metrics_collected", FakeEvent(m2))
        await asyncio.sleep(1)
        m3 = FakeMetrics(duration=0.6)
        self.stt.emit("metrics_collected", FakeEvent(m3))

def create_fake_session_for_example():
    return FakeSession()

# --- Çalıştır ---
if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("Çıkış yapılıyor.")
Ne yapman gerektiği, özet: • Kendi agent kodunda
session
nesnesini oluşturduktan hemen sonra
attach_metrics_listener(session)
çağır. • Eğer SDK’da
session.llm
,
session.tts
,
session.stt
gibi alt bileşenler varsa onlara bağla; yoksa global
session.on("metrics_collected", ...)
şeklinde bağlan. • Handler içinde async I/O (DB, Prometheus exporter, HTTP çağrısı) yapacaksan
async def
kullan ve wrapper ile
asyncio.create_task(...)
çağır. İstersen ben: • Bu örneği doğrudan kullandığın SDK sürümüne (tam import/isimlerle) göre uyarlayayım. •
handle_*
fonksiyonları içine Prometheus client ekleyip tam exporter örneği verip
prometheus_client.start_http_server(8000)
ile scrape edilebilir hale getireyim. Hangi SDK sürümünü / AgentSession oluşturma kodunu kullanıyorsun? Ona göre tam sürümü hemen hazırlarım. Sources: TTS Metrics | LiveKit Documentation | STT Metrics | LiveKit Documentation | VAD Metrics | LiveKit Documentation | Agents (Node.js) | livekit/livekit_composite | DeepWiki
a
çalıştı fakat room ve model unknown geliyor hep
t
Harika — handler çalıştı ama
room
ve
model
hep "unknown" görünüyor. Bu genelde event nesnesinin beklediğimiz alanları taşımamasından veya doğru yerden okumamamamızdan kaynaklanır. Aşağıda nedenleri, nasıl kontrol edip düzelteceğin ve doğrudan kullanabileceğin güncellenmiş kod var. Neden "unknown" görünüyor? • Event nesnesi SDK sürümüne göre farklı yapıda olabilir; örneğin
event.room_id
yerine
event.context.room_id
veya
event.job.room_id
olabilir. • Model bilgisi her metrics event’inde direkt gelmeyebilir; bazen
event.model_name
, bazen
event.metrics.model_name
, bazen metadata içinde bulunur. • Event’i oluşturan component (LLM/TTS/STT) ile session/room ilişkisi ayrı tutuluyorsa, bağlam (context) ile birlikte taşınmalıdır. Eğer bağlam gönderilmiyorsa wrapper tarafında ek metadata sağlaman gerekir. Ne yapacağız? 1. Event objesinin tüm alanlarını loglayıp yapıyı göreceğiz (inspect). 2. Bulduğumuz alanlara göre güvenli (fallback) okuma yapacağız: birkaç olası yer kontrol edilecek. 3. Güncellenmiş wrapper ile doğru room/model değerlerini alacağız. Önce: Event yapısını görmek için hızlı inspect fonksiyonu Aşağıyı çalıştırıp bir metrics event tetiklediğinde terminalde hangi alanların geldiğini gönderir misin? (Tek seferlik; sonrasında kaldırabiliriz.)
Copy code
def inspect_event(event):
    print("=== EVENT INSPECT ===")
    # En yaygın alanlar
    for attr in ["room_id", "room", "model_name", "model", "agent_name", "context", "job", "metadata"]:
        if hasattr(event, attr):
            print(f"{attr}: {getattr(event, attr)}")
    # Tüm __dict__ (varsa)
    try:
        print("__dict__:", event.__dict__)
    except Exception:
        pass
    # metrics alt yapısı
    try:
        m = event.metrics
        print("metrics.__dict__:", getattr(m, "__dict__", str(m)))
    except Exception:
        pass
    print("=====================")
Güncellenmiş güvenli reader + attach fonksiyonu Bu versiyon birden fazla yerde arama yapar:
event.room_id
,
event.context.room_id
,
event.job.room_id
,
event.metadata['room_id']
, ve model için
event.model_name
,
event.metrics.model_name
,
event.metadata['model_name']
gibi yerlere bakar.
Copy code
import asyncio
from datetime import datetime

def _get_room_id_from_event(event):
    # Olası yerleri sırayla kontrol et
    candidates = []
    if hasattr(event, "room_id"):
        candidates.append(getattr(event, "room_id"))
    if hasattr(event, "room"):
        # bazen room objesi veya adı gelebilir
        candidates.append(getattr(event, "room"))
    # context veya job içinde olabilir
    if hasattr(event, "context") and event.context:
        try:
            candidates.append(getattr(event.context, "room_id", None))
            candidates.append(getattr(event.context, "room", None))
        except Exception:
            pass
    if hasattr(event, "job") and event.job:
        try:
            candidates.append(getattr(event.job, "room_id", None))
        except Exception:
            pass
    # metadata dict içinde olabilir
    try:
        meta = getattr(event, "metadata", None) or {}
        if isinstance(meta, dict):
            candidates.append(meta.get("room_id"))
            candidates.append(meta.get("room"))
    except Exception:
        pass

    # Döndürülebilir ilk dolu değer
    for c in candidates:
        if c not in (None, "", "unknown"):
            return str(c)
    return "unknown"

def _get_model_from_event(event):
    candidates = []
    if hasattr(event, "model_name"):
        candidates.append(getattr(event, "model_name"))
    if hasattr(event, "model"):
        candidates.append(getattr(event, "model"))
    # metrics içinde olabilir
    try:
        m = getattr(event, "metrics", None)
        if m is not None:
            candidates.append(getattr(m, "model_name", None))
            candidates.append(getattr(m, "model", None))
    except Exception:
        pass
    # metadata
    try:
        meta = getattr(event, "metadata", None) or {}
        if isinstance(meta, dict):
            candidates.append(meta.get("model_name"))
            candidates.append(meta.get("model"))
    except Exception:
        pass

    for c in candidates:
        if c not in (None, "", "unknown"):
            return str(c)
    return "unknown"

async def handle_metrics(event):
    m = getattr(event, "metrics", None)
    room = _get_room_id_from_event(event)
    model = _get_model_from_event(event)
    now = datetime.utcnow().isoformat()

    print(f"[Metrics] {now} room={room} model={model}")
    if m is not None:
        print(f"  TTFT: {getattr(m, 'ttft', 'N/A')}")
        print(f"  TTFB: {getattr(m, 'ttfb', 'N/A')}")
        print(f"  Duration: {getattr(m, 'duration', 'N/A')}")
        print(f"  Input tokens: {getattr(m, 'input_tokens', 'N/A')}")
        print(f"  Output tokens: {getattr(m, 'output_tokens', 'N/A')}")
    else:
        print("  metrics: None")
    print("-" * 40)
    await asyncio.sleep(0)

def attach_metrics_listener(session):
    # component bazlı bağlan (varsa)
    try:
        session.llm.on("metrics_collected", lambda ev: asyncio.create_task(handle_metrics(ev)))
    except Exception:
        try:
            session.on("llm_metrics_collected", lambda ev: asyncio.create_task(handle_metrics(ev)))
        except Exception:
            pass

    try:
        session.tts.on("metrics_collected", lambda ev: asyncio.create_task(handle_metrics(ev)))
    except Exception:
        try:
            session.on("tts_metrics_collected", lambda ev: asyncio.create_task(handle_metrics(ev)))
        except Exception:
            pass

    try:
        session.stt.on("metrics_collected", lambda ev: asyncio.create_task(handle_metrics(ev)))
    except Exception:
        try:
            session.on("stt_metrics_collected", lambda ev: asyncio.create_task(handle_metrics(ev)))
        except Exception:
            pass

    # fallback: genel metrics_collected
    try:
        session.on("metrics_collected", lambda ev: asyncio.create_task(handle_metrics(ev)))
    except Exception:
        pass

    print("attach_metrics_listener: handlers attached.")
Sonraki adımlar (hangi bilgiyi paylaşmalısın) • Lütfen bir metrics event üretip yukarıdaki
inspect_event(event)
fonksiyonunu çalıştırıp çıktısını paylaş (veya event.dict içeriğini). Böylece tam alan isimlerini görüp kodu kesinlikle uyarlayabilirim. • SDK sürümünü söyle (ör. livekit-agents vX.Y veya package versiyon). Bu, event alan adlarını doğrulamak için önemli. • Eğer event yapısı metadata ile geliyor ise, token/dispatch oluştururken metadata içine
room_id
veya
model_name
eklemek daha sağlam bir çözüm sağlar — istersen buna nasıl ekleyeceğini de gösteririm. Hemen yardımcı olayım: önce inspect çıktısını paylaşır mısın? Ona göre
_get_room_id_from_event
ve
_get_model_from_event
fonksiyonlarını kesin doğru alanlarla güncelleyeyim.
a
start yapıp test edebileceği mbir yer var mı dev veya console değil de?
t
Selam — güzel ve net soru:
start
(production) modunda çalışan agent’ı doğrudan LiveKit’in Playground gibi interaktif bir yerde test edebileceğin hazır bir ortam yok.
start
üretim amaçlı çalışır ve etkileşimli frontend/Playground ile otomatik olarak görünür olmayabilir. Ancak
start
modunda çalışan bir agent’ı test etmenin birkaç pratik yolu ve önerisi var — aşağıda kısa, uygulanabilir seçenekleri paylaşıyorum ve hangisini tercih ettiğini soruyorum. Kısa özet •
start
için özel, hazır bir “Playground” yok.
dev
ve
console
test amaçlı daha uygun. •
start
modunda test etmek için production benzeri bir client/oda oluşturup agent’ı dispatch etmen veya doğrudan odaya katılmasını sağlaman gerekiyor. • Aşağıda 3 pratik yöntem var: hızlı frontend ile test, CLI ile manuel dispatch, ya da test ortamı (staging) oluşturma. Seçenekler ve adımlar 1) Hızlı HTML/JS client ile test (en hızlı ve kontrol edilmesi kolay) • Basit bir web sayfası ile LiveKit’a bağlanıp
room
oluştur/katıl: ◦ Kullanıcı token’ı oluştur (dev için veya production key ile). ◦ Tarayıcıda mikrofonu aç ve odaya katıl. • Agent`start` modunda kâtip/servis olarak çalışıyorsa, agent’ın odaya katılması için explicit dispatch gerekiyorsa token veya dispatch API ile agent’ı odaya gönder. • Bu yöntemle gerçek ses/girdi ile
start
modundaki davranışı görebilirsin. 2) CLI ile manuel dispatch (doğrudan agent’ı odaya atmak) • Eğer
lk
CLI yüklüyse: ◦
lk dispatch create --agent-name test-agent --room my-room --metadata '{"...": "..."}'
• Bu, production agent’ı hedef odaya dispatch eder. Sonrasında bir client ile odaya bağlanıp agent ile etkileşimi görebilirsin. 3) Staging ortamı: production’a çok yakın ama test için güvenli • Production ile aynı konfigürasyona sahip bir “staging” LiveKit sunucusu/cluster’ı kur. • Agent’ı
start
olarak burada deploy et ve gerçek world testlerini yap. • Avantaj: gerçek koşullarda test, ama prod verilerine veya trafiğine karışmaz. Göz önünde bulundurman gerekenler •
start
modunda agent genelde container/process olarak çalışır; logs ve telemetri ile izleyebilirsin (metrics/loglar genelde tek kaynak). • Eğer agent kodunda
agent_name
tanımlıysa, odaya katılması için explicit dispatch gerekir. Token yalnızca kullanıcıyı odaya sokar. •
start
modunda interaktif debug zor olabilir; bu yüzden staging veya kısa süreli dev modunda çoğu testi yapmak daha pratiktir. Hangi yardımı istersin? • Hemen bir örnek HTML/JS client istersen, sana kopyala‑yapıştır çalışacak örnek token oluşturma + client kodu verebilirim. •
lk dispatch create
komutu ile nasıl dispatch yapılacağını adım adım göstereyim mi? • Yoksa staging ortamı kurma (docker/k8s örneği) ile ilgili rehber ister misin? Tercihini söyle, hemen adım adım yardımcı olayım.