AI Genel Çalışma Rehberi

Blog / Proje

Spotify A2A Buddy: Multi-Agent Sistemlere Pratik Bir Giriş

Spotify Logo OpenAI Logo

Geçen hafta A2A ve ACP protokollerini teorik olarak incelemiştik. Peki bu protokoller gerçek bir uygulamada nasıl çalışıyor? Bugün sizinle Spotify A2A Buddy projesini paylaşacağım - sesli komutlarla Spotify'ı kontrol eden, OpenAI'nin GPT-4o ve Whisper API'lerini kullanan, ve tüm bu işlemleri Google'ın A2A protokolü üzerinden koordine eden bir multi-agent sistemi.

Bu yazıda sadece "şöyle bir şey yaptık" demekle kalmayacağız. Agent'ların birbirleriyle nasıl mesajlaştığını, A2A paketlerinin içeriğini ve tüm akışı sequence diagram'lar üzerinden adım adım göreceğiz.


TL;DR - Hızlı Bakış


1. Neden Böyle Bir Proje?

A2A protokolünü öğrenmenin en iyi yolu onu kullanmak. Ama basit bir "hello world" yerine, gerçek dünyada işe yarar bir şey yapmak istedim.

Senaryo şu:

Basit gibi görünüyor ama arkasında 5 farklı agent'ın koordineli çalışması gerekiyor.


2. Mimari: 5 Agent, 1 Hedef

Projedeki her agent'ın belirli bir uzmanlığı var:

🎯 OrchestratorAgent

🗣️ SpeechAgent

💬 ConversationAgent

😊 SentimentAgent

🎵 SpotifyAgent


3. A2A Protokolü: Agent'lar Nasıl Konuşuyor?

Her agent kendini sisteme bir Agent Card ile tanıtıyor. Bu kart, agent'ın ne yapabildiğini (skills) ve nasıl ulaşılacağını (endpoint) belirtiyor.

SpotifyAgent'ın Agent Card'ı:

{
  "name": "SpotifyAgent",
  "description": "Controls Spotify playback and music recommendations",
  "version": "1.0.0",
  "url": "http://localhost:3000/api/a2a/agents/SpotifyAgent",
  "skills": [
    { "id": "play_music", "name": "Play Music" },
    { "id": "pause_music", "name": "Pause" },
    { "id": "play_by_mood", "name": "Play by Mood" }
  ]
}

Sistem başladığında her agent kendini A2A Protocol Handler'a kaydediyor:

[A2A] [PROTOCOL] Agent registered: OrchestratorAgent {skills: [coordinate_agents, manage_sessions]}
[A2A] [PROTOCOL] Agent registered: SpotifyAgent {skills: [play_music, pause_music, play_by_mood...]}
[A2A] [PROTOCOL] Agent registered: ConversationAgent {skills: [parse_intent, generate_response]}
[A2A] [PROTOCOL] Agent registered: SentimentAgent {skills: [analyze_sentiment, get_mood_history]}
[A2A] [PROTOCOL] Agent registered: SpeechAgent {skills: [transcribe_audio, generate_speech]}

4. Akış: "Play Queen" Dediğimde Ne Oluyor?

İşte tüm sistemin sequence diagram'ı. Her adımı ayrı ayrı inceleyelim:

sequenceDiagram autonumber participant User as 🎤 User participant Browser as 🌐 Browser participant Bus as 📨 MessageBus participant Speech as 🗣️ SpeechAgent participant Conv as 💬 ConversationAgent participant Sent as 😊 SentimentAgent participant Spot as 🎵 SpotifyAgent participant Whisper as OpenAI Whisper participant GPT as GPT-4o participant TTS as TTS-1-HD participant SpotifyAPI as Spotify API User->>Browser: 🗣️ "Play Queen" Browser->>Browser: VAD detects speech (level > 0.02) Browser->>Browser: 1500ms silence → send audio Browser->>Bus: WebSocket: audio (base64 WAV) Bus->>Speech: audio:received Speech->>Whisper: POST /v1/audio/transcriptions Whisper-->>Speech: {text: "Play Queen"} Speech->>Bus: speech:transcribed Bus->>Conv: speech:transcribed Conv->>GPT: POST /v1/chat/completions (tools) GPT-->>Conv: tool_call: play_specific_music({query: "Queen"}) Conv->>Bus: spotify:command + sentiment:analyze par Parallel Execution Bus->>Spot: spotify:command Spot->>SpotifyAPI: GET /search?q=Queen SpotifyAPI-->>Spot: 20 tracks Spot->>SpotifyAPI: PUT /me/player/play SpotifyAPI-->>Spot: 204 OK and Bus->>Sent: sentiment:analyze Sent->>GPT: Analyze mood GPT-->>Sent: {mood: "neutral", energy: "medium"} end Spot->>Bus: spotify:result Bus->>Conv: Generate response Conv->>Bus: response:ready Bus->>Speech: response:ready Speech->>Bus: client:echo_suppress Speech->>TTS: POST /v1/audio/speech TTS-->>Speech: MP3 audio Speech->>Bus: client:audio Bus->>Browser: audio (MP3) Browser->>User: 🔊 "Now playing Bohemian Rhapsody by Queen"

5. Adım Adım: Her Aşamada Ne Oluyor?

Adım 1-3: Ses Algılama (Browser)

Tarayıcı, mikrofondan gelen ses seviyesini sürekli izliyor. Ses seviyesi 0.02 threshold'unu geçtiğinde kayda başlıyor, 1.5 saniye sessizlik olunca kaydı gönderiyor.

// Browser'daki VAD (Voice Activity Detection)
onAudioProcess(event) {
  const level = Math.max(...audioData.map(Math.abs));
  
  if (level > 0.02) {  // Ses var!
    this.isRecording = true;
    this.audioChunks.push(audioData);
  }
  
  // 1500ms sessizlik → gönder
  if (silenceDuration > 1500) {
    this.sendAudio();  // WebSocket ile server'a
  }
}

Adım 4-7: Speech-to-Text (SpeechAgent)

SpeechAgent, gelen ses verisini OpenAI Whisper API'ye gönderiyor:

[SPEECH_AGENT] Processing 207480 bytes of audio
[SPEECH_AGENT] Transcribed: "Play Queen"
[BUS] Event: speech:transcribed

Adım 8-11: Intent Detection (ConversationAgent)

ConversationAgent, GPT-4o'nun Function Calling özelliğini kullanarak kullanıcının ne istediğini anlıyor:

// GPT-4o'ya gönderilen request
{
  "model": "gpt-4o",
  "messages": [
    {"role": "system", "content": "You are a music assistant..."},
    {"role": "user", "content": "Play Queen"}
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "play_specific_music",
        "parameters": {"query": {"type": "string"}}
      }
    },
    {
      "type": "function", 
      "function": {
        "name": "play_mood_music",
        "parameters": {"mood": {"type": "string"}}
      }
    }
  ]
}

GPT-4o'nun cevabı:

{
  "tool_calls": [{
    "function": {
      "name": "play_specific_music",
      "arguments": "{\"query\": \"Queen\"}"
    }
  }]
}

Log çıktısı:

[CONVERSATION_AGENT] Function called: play_specific_music {"query":"Queen"}
[CONVERSATION_AGENT] Intent detected {"intent":"play_music","query":"Queen","confidence":0.95}
[CONVERSATION_AGENT] Routing: play_music (confidence: 0.95)

Adım 12-17: Spotify Çalma (SpotifyAgent)

SpotifyAgent şu adımları takip ediyor:

1. Device kontrolü:

[SPOTIFY_AGENT] API Call: GET /me/player/devices
[SPOTIFY_AGENT] Available devices: [{"name":"Music Buddy Web Player","active":false}]
[SPOTIFY_AGENT] Transferring playback to device: xxx

2. Şarkı arama:

[SPOTIFY_AGENT] API Call: GET /search?q=Queen&type=track&limit=20
[SPOTIFY_AGENT] API Response: 200

3. Çalma:

[SPOTIFY_AGENT] API Call: PUT /me/player/play
[SPOTIFY_AGENT] Playing 20 tracks starting with: Bohemian Rhapsody

Adım 18-24: Sesli Yanıt (SpeechAgent)

Son olarak SpeechAgent, TTS-1-HD ile sesli yanıt oluşturuyor. Ama önce echo suppression devreye giriyor - yoksa kendi sesimizi tekrar algılardık!

[BUS] Event: client:echo_suppress
[SPEECH_AGENT] Generating speech: "Now playing Bohemian Rhapsody by Queen..."
[BUS] Event: client:audio

6. A2A Paket Örnekleri

Sistemde hem MessageBus (dahili) hem A2A REST API (harici) kullanılıyor. İşte A2A ile nasıl task gönderilir:

Agent Discovery (Sistemdeki agent'ları keşfetme)

GET /.well-known/agent.json HTTP/1.1
Host: localhost:3000

Yanıt:

{
  "name": "OrchestratorAgent",
  "description": "Coordinates all agents and manages user sessions",
  "skills": [
    {"id": "coordinate_agents", "name": "Coordinate"},
    {"id": "manage_sessions", "name": "Sessions"},
    {"id": "list_agents", "name": "List Agents"}
  ]
}

Task Gönderme (JSON-RPC 2.0)

POST /api/a2a/tasks/send HTTP/1.1
Content-Type: application/json
 
{
  "skillId": "play_by_mood",
  "input": {"mood": "happy", "energy": "high"},
  "sessionId": "user-session-123"
}

Yanıt:

{
  "jsonrpc": "2.0",
  "result": {
    "id": "task_a1b2c3d4e5f6",
    "skillId": "play_by_mood",
    "state": "completed",
    "output": {
      "success": true,
      "track": {"name": "Happy", "artist": "Pharrell Williams"},
      "queuedTracks": 20
    }
  }
}

Sentiment Analizi

POST /api/a2a/rpc HTTP/1.1
Content-Type: application/json
 
{
  "jsonrpc": "2.0",
  "id": "req-001",
  "method": "tasks/send",
  "params": {
    "skillId": "analyze_sentiment",
    "input": {"text": "Bugün stresli bir günüm oldu, rahatlatıcı müzik lazım"}
  }
}

Yanıt:

{
  "jsonrpc": "2.0",
  "result": {
    "output": {
      "mood": "stressed",
      "intensity": 0.7,
      "energy_level": "low",
      "secondary_mood": "tired",
      "music_recommendation": "ambient, chill, lo-fi",
      "confidence": 0.92
    }
  }
}

7. Hibrit Mimari: MessageBus + A2A

Neden hem MessageBus hem A2A kullanıyoruz?

MessageBus avantajları:

A2A Protocol avantajları:

Kullanım senaryoları:


8. Performans: 7 Saniyede Müzik

Tüm akışın timeline'ı:

T+0ms: Kullanıcı konuşmaya başlıyor

T+1500ms: Sessizlik algılandı, ses gönderiliyor

T+2600ms: Whisper transkripsiyonu tamamlandı

T+3500ms: GPT-4o function call sonucu geldi

T+4400ms: Spotify playback başladı (müzik çalıyor!)

T+7100ms: TTS sesli yanıtı oynatılıyor

Toplam: ~7 saniye (ses girişinden müzik + sesli yanıta)


9. Kurulum ve Deneme

Projeyi denemek isterseniz:

Gereksinimler:

Kurulum:

git clone https://github.com/cuneytm/SpotifyA2ABuddy.git
cd SpotifyA2ABuddy
npm install
cp .env.example .env
# .env dosyasını düzenle: OPENAI_API_KEY, SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET
npm run auth  # Spotify ile bir kez giriş yap
npm start

Tarayıcıda http://localhost:3000 açın ve konuşmaya başlayın!


10. Öğrenilen Dersler

Bu projeyi yaparken edindiğim bazı önemli dersler:

1. Echo Suppression şart: Sistem sesli yanıt verirken mikrofonu kapatmazsanız, kendi sesinizi algılar ve döngüye girer.

2. Device management zor: Spotify Web Playback SDK ile çalışırken device transfer'ı önemli. ensureDeviceActive() fonksiyonu hayat kurtarıyor.

3. Function Calling > regex parsing: GPT-4o'nun Function Calling özelliği, intent detection için regex'lerden çok daha güvenilir.

4. 20 şarkılık queue buffer: Kullanıcı "sonraki" dediğinde anlık arama yapmak yerine önceden 20 şarkı kuyruğa almak UX'i çok iyileştiriyor.

5. Hibrit mimari mantıklı: Her şey için A2A kullanmak overhead yaratır. Dahili iletişim için MessageBus, harici entegrasyon için A2A ideal kombinasyon.


Sonuç

A2A protokolü, multi-agent sistemler için güçlü bir standart sunuyor. Ama sadece protokolü bilmek yetmiyor - onu gerçek bir uygulamada kullanarak öğrenmek gerekiyor.

Spotify A2A Buddy, 5 agent'ın nasıl koordineli çalışabileceğini gösteren pratik bir örnek. Ses tanıma, doğal dil anlama, duygu analizi ve müzik çalma gibi farklı yetenekleri olan agent'lar, A2A sayesinde standart bir şekilde iletişim kuruyor.

Projeyi fork edip üzerinde oynamanızı şiddetle tavsiye ederim. Belki yeni bir agent eklersiniz (hava durumu?), belki farklı bir müzik servisi entegre edersiniz. Önemli olan, multi-agent sistemlerin nasıl çalıştığını hands-on deneyimlemek.


Kaynaklar

GitHub Reposu:

İlgili Makaleler:

Resmi Kaynaklar:


Son güncelleme: 4 Ocak 2026