Membangun Sistem Multiagen

1. Pengantar

Di lab ini, Anda akan melampaui chatbot sederhana dan membangun sistem multi-agen terdistribusi.

Meskipun satu LLM dapat menjawab pertanyaan, kompleksitas dunia nyata sering kali memerlukan peran khusus. Anda tidak meminta engineer backend untuk mendesain UI, dan Anda tidak meminta desainer untuk mengoptimalkan kueri database. Demikian pula, kita dapat membuat agen AI khusus yang berfokus pada satu tugas dan berkoordinasi satu sama lain untuk menyelesaikan masalah yang kompleks.

Anda akan membuat Sistem Pembuatan Kursus yang terdiri dari:

  • Researcher Agent: Menggunakan google_search untuk menemukan informasi terbaru.
  • Agen Penilai (Judge Agent): Mengkritik kualitas dan kelengkapan riset.
  • Agen Pembuat Konten: Mengubah riset menjadi kursus terstruktur.
  • Agen Pengelola: Mengelola alur kerja dan komunikasi antara spesialis ini.

Yang akan Anda pelajari

  • Tentukan agen yang menggunakan alat (peneliti) yang dapat menelusuri web.
  • Terapkan output terstruktur dengan Pydantic untuk hakim.
  • Menghubungkan ke agen jarak jauh menggunakan protokol Agent-to-Agent (A2A).
  • Buat LoopAgent untuk membuat feedback loop antara peneliti dan juri.
  • Jalankan sistem terdistribusi secara lokal menggunakan ADK.
  • Deploy sistem multi-agen ke Google Cloud Run.
  • Menggunakan model Gemma di GPU Cloud Run untuk agen pembuat konten.

Yang Anda butuhkan

  • Browser web seperti Chrome
  • Project Google Cloud yang mengaktifkan penagihan

2. Prinsip Arsitektur dan Orkestrasi

Pertama, mari kita pahami cara kerja agen ini bersama-sama. Kami sedang membangun Pipeline Pembuatan Kursus.

Desain Sistem

Diagram Arsitektur

Mengorkestrasi dengan Agen

Agen standar (seperti Peneliti) berfungsi. Agen Pengelola (seperti LoopAgent atau SequentialAgent) mengelola agen lain. Mereka tidak memiliki alatnya sendiri; "alat" mereka adalah delegasi.

  1. LoopAgent: Ini bertindak seperti loop while dalam kode. Agen ini menjalankan urutan agen berulang kali hingga suatu kondisi terpenuhi (atau iterasi maksimum tercapai). Kami menggunakannya untuk Loop Riset:
    • Peneliti menemukan info.
    • Juri mengkritiknya.
    • Jika Judge menampilkan "Fail", EscalationChecker akan memungkinkan loop berlanjut.
    • Jika Judge mengatakan "Pass", EscalationChecker akan menghentikan loop.
  2. SequentialAgent: Tindakan ini seperti eksekusi skrip standar. Agen ini menjalankan agen satu per satu. Kita menggunakannya untuk Pipeline Tingkat Tinggi:
    • Pertama, jalankan Research Loop (hingga selesai dengan data yang baik).
    • Kemudian, jalankan Content Builder (untuk menulis kursus).

Dengan menggabungkannya, kita membuat sistem yang andal yang dapat mengoreksi diri sendiri sebelum menghasilkan output akhir.

3. Penyiapan

Penyiapan project

Buat Project Google Cloud

  1. Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
  2. Pastikan penagihan diaktifkan untuk project Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project.

Mulai Cloud Shell

Cloud Shell adalah lingkungan command line yang berjalan di Google Cloud yang telah dilengkapi dengan alat yang diperlukan.

  1. Klik Activate Cloud Shell di bagian atas konsol Google Cloud.
  2. Setelah terhubung ke Cloud Shell, verifikasi autentikasi Anda:
    gcloud auth list
    
  3. Pastikan project Anda dikonfigurasi:
    gcloud config get project
    
  4. Jika project Anda tidak ditetapkan seperti yang diharapkan, tetapkan project:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

Penyiapan Lingkungan

  1. Buka Cloud Shell: Klik ikon Activate Cloud Shell di kanan atas Konsol Google Cloud.

Mendapatkan Kode Awal

  1. Buat clone repositori awal ke direktori utama Anda:Pindah ke direktori utama Anda
      cd ~
    
    Clone hanya kode yang diperlukan untuk codelab ini dari folder Demo DevRel Google Cloud.
    git clone --depth 1 --filter=blob:none --sparse https://github.com/GoogleCloudPlatform/devrel-demos.git temp-repo && cd temp-repo && git sparse-checkout set agents/multi-agent-system && cd .. && mv temp-repo/agents/multi-agent-system . && rm -rf temp-repo
    
    Pindah ke folder yang berisi kode untuk Codelab ini
    cd multi-agent-system
    
  2. Aktifkan API: Jalankan perintah berikut untuk mengaktifkan layanan Google Cloud yang diperlukan:
    gcloud services enable \
        run.googleapis.com \
        artifactregistry.googleapis.com \
        cloudbuild.googleapis.com \
        aiplatform.googleapis.com \
        compute.googleapis.com
    
  3. Buka folder ini di editor Anda.
    cloudshell edit .
    

Menyiapkan Lingkungan

  1. Siapkan variabel lingkungan.Kita akan membuat file .env untuk menyimpan variabel ini sehingga Anda dapat memuat ulang dengan mudah jika sesi Anda terputus.
    cat <<EOF > .env
    export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
    export GOOGLE_CLOUD_LOCATION=europe-west4
    export GOOGLE_GENAI_USE_VERTEXAI=true
    EOF
    
  2. Sumber variabel lingkungan:
    source .env
    

4. 🕵️ Agen Peneliti

Agen Peneliti

Peneliti adalah seorang spesialis. Satu-satunya tugasnya adalah menemukan informasi. Untuk melakukannya, alat ini memerlukan akses ke alat: Google Penelusuran.

Mengapa harus memisahkan Peneliti?

Pembahasan Mendalam: Mengapa tidak satu agen saja yang melakukan semuanya?

Agen kecil yang fokus lebih mudah dievaluasi dan di-debug. Jika risetnya buruk, Anda dapat mengulangi perintah Peneliti. Jika pemformatan kursus buruk, Anda dapat melakukan iterasi pada Pembuat Konten. Dalam perintah "lakukan semuanya" yang monolitik, memperbaiki satu hal sering kali merusak hal lain.

  1. Jika Anda bekerja di Cloud Shell, jalankan perintah berikut untuk membuka editor Cloud Shell:
    cloudshell workspace .
    
  2. Buka agents/researcher/agent.py.
  3. Tinjau kode berikut yang menentukan agen researcher:
    # ... existing imports ...
    
    # Define the Researcher Agent
    researcher = Agent(
        name="researcher",
        model=MODEL,
        description="Gathers information on a topic using Google Search.",
        instruction="""
        You are an expert researcher. Your goal is to find comprehensive and accurate information on the user's topic.
        Use the `google_search` tool to find relevant information.
        Summarize your findings clearly.
        If you receive feedback that your research is insufficient, use the feedback to refine your next search.
        """,
        tools=[google_search],
    )
    
    root_agent = researcher
    

Konsep Utama: Penggunaan Alat

Perhatikan bahwa kita meneruskan tools=[google_search]. ADK menangani kompleksitas dalam mendeskripsikan alat ini ke LLM. Saat model memutuskan bahwa ia memerlukan informasi, model akan membuat panggilan alat terstruktur, ADK akan mengeksekusi fungsi Python google_search, dan mengirimkan hasilnya kembali ke model.

5. ⚖️ Agen Hakim

Agen Penilaian

Peneliti bekerja keras, tetapi LLM bisa jadi malas. Kami memerlukan Penilai untuk meninjau pekerjaan tersebut. Hakim menerima riset dan memberikan penilaian Lulus/Tidak Lulus terstruktur.

Output Terstruktur

Pembahasan Mendalam: Untuk mengotomatiskan alur kerja, kita memerlukan output yang dapat diprediksi. Ulasan teks yang bertele-tele sulit diuraikan secara terprogram. Dengan menerapkan skema JSON (menggunakan Pydantic), kita memastikan bahwa Judge menampilkan boolean pass atau fail yang dapat diandalkan oleh kode kita.

  1. Buka agents/judge/agent.py.
  2. Tinjau kode berikut yang menentukan skema JudgeFeedback dan agen judge.
    # 1. Define the Schema
    class JudgeFeedback(BaseModel):
        """Structured feedback from the Judge agent."""
        status: Literal["pass", "fail"] = Field(
            description="Whether the research is sufficient ('pass') or needs more work ('fail')."
        )
        feedback: str = Field(
            description="Detailed feedback on what is missing. If 'pass', a brief confirmation."
        )
    
    # 2. Define the Agent
    judge = Agent(
        name="judge",
        model=MODEL,
        description="Evaluates research findings for completeness and accuracy.",
        instruction="""
        You are a strict editor.
        Evaluate the 'research_findings' against the user's original request.
        If the findings are missing key info, return status='fail'.
        If they are comprehensive, return status='pass'.
        """,
        output_schema=JudgeFeedback,
        # Disallow delegation because it should only output the schema
        disallow_transfer_to_parent=True,
        disallow_transfer_to_peers=True,
    )
    
    root_agent = judge
    

Konsep Utama: Membatasi Perilaku Agen

Kami menetapkan disallow_transfer_to_parent=True dan disallow_transfer_to_peers=True. Hal ini memaksa Hakim untuk hanya menampilkan JudgeFeedback terstruktur. Agen ini tidak dapat memutuskan untuk "melakukan chat" dengan pengguna atau mendelegasikan tugas kepada agen lain. Hal ini menjadikannya komponen deterministik dalam alur logika kita.

6. ✍️ Agen Pembuat Konten

Pembuat Konten

Content Builder adalah penulis kreatif. Tim ini akan mengambil riset yang disetujui dan mengubahnya menjadi kursus. Aplikasi ini menggunakan model Gemma yang disajikan oleh Cloud Run.

Pertama, mari kita lihat layanan Cloud Run yang menghosting model

  1. Buka ollama_backend/Dockerfile
  2. Di sini, Anda dapat melihat cara Dockerfile menggunakan image Ollama, memproses permintaan di port 8080, dan menyimpan model yang diminta di folder /model.
FROM ollama/ollama:latest

# Listen on all interfaces, port 8080 (Cloud Run default)
ENV OLLAMA_HOST 0.0.0.0:8080

# Store model weight files in /models
ENV OLLAMA_MODELS /models

⚙️ Saat men-deploy, Anda akan menetapkan konfigurasi berikut:

  • GPU: NVIDIA L4 dipilih karena rasio harga dan performanya yang sangat baik untuk workload inferensi. L4 menyediakan memori GPU 24 GB dan operasi tensor yang dioptimalkan, sehingga ideal untuk model parameter 270M seperti Gemma
  • Memori: Memori sistem 16 GB untuk menangani pemuatan model, operasi CUDA, dan pengelolaan memori Ollama
  • CPU: 8 core untuk penanganan I/O dan tugas praproses yang optimal
  • Serentak: 4 permintaan per instance menyeimbangkan throughput dengan penggunaan memori GPU
  • Waktu tunggu: 600 detik untuk mengakomodasi pemuatan model awal dan pengaktifan penampung

Sekarang, mari kita lihat agen Content Builder yang menggunakan model Gemma.

  1. Buka agents/content_builder/agent.py.
  2. Tinjau kode berikut yang menentukan agen content_builder.
# the `ollama-gemma-gpu` Cloud Run service URL which hosts the Gemma model
target_url = os.environ.get("OLLAMA_API_BASE")

# ... existing code ...

# (Note: We use 'ollama/gemma3:270m' to align with ADK's expected prefix)
gemma_model_name = os.environ.get("GEMMA_MODEL_NAME", "gemma3:270m")
model = LiteLlm(
    model=f"ollama_chat/{gemma_model_name}",
    api_base=target_url
)

# 5. Define the Agent
content_builder = Agent(
    name="content_builder",
    model=model,
    description="Transforms research findings into a structured course.",
    instruction="""
    You are an expert course creator.
    Take the approved 'research_findings' and transform them into a well-structured, engaging course module.

    **Formatting Rules:**
    1. Start with a main title using a single `#` (H1).
    2. Use `##` (H2) for main section headings. These will be used for the Table of Contents.
    3. Use `###` (H3) for sub-sections within main sections.
    4. Use bullet points and clear paragraphs.
    5. Maintain a professional but engaging tone.

    **Structure Requirements:**
    - Begin with a brief Introduction section explaining what the learner will gain.
    - Organize content into 3-5 main sections with clear headings.
    - Include Key Takeaways at the end as a bulleted summary.
    - Keep each section focused and concise.

    Ensure the content directly addresses the user's original request.
    Do not include any preamble or explanation outside the course content itself.
    """,
)

root_agent = content_builder

Konsep Utama: Penerapan Konteks

Anda mungkin bertanya-tanya: "Bagaimana Pembuat Konten mengetahui apa yang ditemukan Peneliti?" Di ADK, agen dalam pipeline berbagi session.state. Nanti, di Orchestrator, kita akan mengonfigurasi Peneliti dan Penilai untuk menyimpan outputnya ke status bersama ini. Perintah Pembuat Konten secara efektif memiliki akses ke histori ini.

7. 🎻 Orchestrator

Agen Orchestrator

Orchestrator adalah pengelola tim multi-agen kami. Tidak seperti agen spesialis (Peneliti, Penilai, Pembuat Konten) yang melakukan tugas tertentu, tugas Orchestrator adalah mengoordinasikan alur kerja dan memastikan informasi mengalir dengan benar di antara mereka.

🌐 Arsitektur: Agent-to-Agent (A2A)

Arsitektur A2A

Di lab ini, kita akan membangun sistem terdistribusi. Daripada menjalankan semua agen dalam satu proses Python, kita men-deploy-nya sebagai microservice independen. Hal ini memungkinkan setiap agen diskalakan secara independen dan gagal tanpa membuat seluruh sistem error.

Untuk mewujudkan hal ini, kami menggunakan protokol Agent-to-Agent (A2A).

A2A Protocol

Pembahasan Mendalam: Dalam sistem produksi, agen berjalan di server yang berbeda (atau bahkan cloud yang berbeda). Protokol A2A menciptakan cara standar bagi agen untuk saling menemukan dan berkomunikasi melalui HTTP. RemoteA2aAgent adalah klien ADK untuk protokol ini.

  1. Buka agents/orchestrator/agent.py.
  2. Tinjau cara kode berikut yang menentukan koneksi.
    # ... existing code ...
    
    # Connect to the Researcher (Localhost port 8001)
    researcher_url = os.environ.get("RESEARCHER_AGENT_CARD_URL", "http://localhost:8001/a2a/agent/.well-known/agent-card.json")
    researcher = RemoteA2aAgent(
        name="researcher",
        agent_card=researcher_url,
        description="Gathers information using Google Search.",
        # IMPORTANT: Save the output to state for the Judge to see
        after_agent_callback=create_save_output_callback("research_findings"),
        # IMPORTANT: Use authenticated client for communication
        httpx_client=create_authenticated_client(researcher_url)
    )
    
    # Connect to the Judge (Localhost port 8002)
    judge_url = os.environ.get("JUDGE_AGENT_CARD_URL", "http://localhost:8002/a2a/agent/.well-known/agent-card.json")
    judge = RemoteA2aAgent(
        name="judge",
        agent_card=judge_url,
        description="Evaluates research.",
        after_agent_callback=create_save_output_callback("judge_feedback"),
        httpx_client=create_authenticated_client(judge_url)
    )
    
    # Content Builder (Localhost port 8003)
    content_builder_url = os.environ.get("CONTENT_BUILDER_AGENT_CARD_URL", "http://localhost:8003/a2a/agent/.well-known/agent-card.json")
    content_builder = RemoteA2aAgent(
        name="content_builder",
        agent_card=content_builder_url,
        description="Builds the course.",
        httpx_client=create_authenticated_client(content_builder_url)
    )
    

8. 🛑 Pemeriksa Eskalasi

Loop memerlukan cara untuk berhenti. Jika Hakim mengatakan "Lulus", kita harus segera keluar dari loop dan beralih ke Pembuat Konten.

Logika Kustom dengan BaseAgent

Pembahasan Mendalam: Tidak semua agen menggunakan LLM. Terkadang Anda memerlukan logika Python sederhana. BaseAgent memungkinkan Anda menentukan agen yang hanya menjalankan kode. Dalam hal ini, kita memeriksa status sesi dan menggunakan EventActions(escalate=True) untuk memberi sinyal LoopAgent agar berhenti.

  1. Masih di agents/orchestrator/agent.py.
  2. Tinjau kode berikut, tinjau masukan hakim, dan lanjutkan ke langkah berikutnya jika sudah siap
    class EscalationChecker(BaseAgent):
        """Checks the judge's feedback and escalates (breaks the loop) if it passed."""
    
        async def _run_async_impl(
            self, ctx: InvocationContext
        ) -> AsyncGenerator[Event, None]:
            # Retrieve the feedback saved by the Judge
            feedback = ctx.session.state.get("judge_feedback")
            print(f"[EscalationChecker] Feedback: {feedback}")
    
            # Check for 'pass' status
            is_pass = False
            if isinstance(feedback, dict) and feedback.get("status") == "pass":
                is_pass = True
            # Handle string fallback if JSON parsing failed
            elif isinstance(feedback, str) and '"status": "pass"' in feedback:
                is_pass = True
    
            if is_pass:
                # 'escalate=True' tells the parent LoopAgent to stop looping
                yield Event(author=self.name, actions=EventActions(escalate=True))
            else:
                # Continue the loop
                yield Event(author=self.name)
    
    escalation_checker = EscalationChecker(name="escalation_checker")
    

Konsep Utama: Alur Kontrol melalui Peristiwa

Agen tidak hanya berkomunikasi dengan teks, tetapi juga dengan Peristiwa. Dengan menghasilkan peristiwa dengan escalate=True, agen ini mengirimkan sinyal ke induknya (LoopAgent). LoopAgent diprogram untuk menangkap sinyal ini dan menghentikan loop.

9. 🔁 Siklus Riset

Loop Riset

Kita memerlukan loop umpan balik: Riset -> Menilai -> (Gagal) -> Riset -> ...

  1. Di agents/orchestrator/agent.py.
  2. Tinjau cara kode berikut menentukan definisi research_loop.
    research_loop = LoopAgent(
        name="research_loop",
        description="Iteratively researches and judges until quality standards are met.",
        sub_agents=[researcher, judge, escalation_checker],
        max_iterations=3,
    )
    

Konsep Utama: LoopAgent

LoopAgent berganti-ganti sub_agents secara berurutan.

  1. researcher: Menemukan data.
  2. judge: Mengevaluasi data.
  3. escalation_checker: Memutuskan apakah akan yield Event(escalate=True). Jika escalate=True terjadi, loop akan berhenti lebih awal. Jika tidak, proses akan dimulai ulang di peneliti (hingga max_iterations).

10. 🔗 Pipeline Akhir

Pipeline Akhir

Menyatukan semuanya....

  1. Di agents/orchestrator/agent.py.
  2. Tinjau cara root_agent ditentukan di bagian bawah file.
    root_agent = SequentialAgent(
        name="course_creation_pipeline",
        description="A pipeline that researches a topic and then builds a course from it.",
        sub_agents=[research_loop, content_builder],
    )
    

Konsep Utama: Komposisi Hierarkis

Perhatikan bahwa research_loop itu sendiri adalah agen (LoopAgent). Kita memperlakukannya seperti sub-agen lainnya di SequentialAgent. Komposisi ini memungkinkan Anda membangun logika yang kompleks dengan menyusun pola sederhana (loop di dalam urutan, urutan di dalam perute, dll.).

11. 🚀 Deploy ke Cloud Run

Kita akan men-deploy setiap agen sebagai layanan terpisah di Cloud Run, termasuk layanan Cloud Run untuk UI pembuat kursus dan layanan Cloud Run yang menggunakan GPU untuk model Gemma.

Memahami Konfigurasi Deployment

Saat men-deploy agen ke Cloud Run, kami meneruskan beberapa variabel lingkungan untuk mengonfigurasi perilaku dan konektivitasnya:

  • GOOGLE_CLOUD_PROJECT: Memastikan agen menggunakan project Google Cloud yang benar untuk panggilan Vertex AI dan logging.
  • GOOGLE_GENAI_USE_VERTEXAI: Memberi tahu framework agen (ADK) untuk menggunakan Vertex AI dalam inferensi model, bukan memanggil Gemini API secara langsung.
  • [AGENT]_AGENT_CARD_URL: Hal ini sangat penting untuk Orchestrator. Pernyataan ini memberi tahu Orchestrator tempat menemukan agen jarak jauh. Dengan menyetel ini ke URL Cloud Run yang di-deploy (khususnya jalur kartu agen), kita memungkinkan Pengelola menemukan dan berkomunikasi dengan Peneliti, Penilai, dan Pembuat Konten melalui internet.

Untuk men-deploy semua agen ke layanan Cloud Run, jalankan skrip berikut.

Pertama, pastikan skrip dapat dieksekusi.

chmod u+x ~/multi-agent-system/deploy.sh

Catatan Proses ini akan memerlukan waktu beberapa menit untuk dijalankan karena setiap layanan di-deploy secara berurutan.

~/multi-agent-system/deploy.sh

12. Buat kursus.

Buka situs Course Creator. Layanan Cloud Run Course Creator adalah layanan terakhir yang di-deploy dari skrip. Anda dapat mengidentifikasi URL ke pembuat kursus sebagai https://course-creator-..run.app, yang harus berupa baris output akhir dari skrip deployment.

Kemudian, ketik ide kursus, misalnya "aljabar linear".

Agen Anda akan mulai mengerjakan kursus Anda.

Pipeline Akhir

13. Pembersihan

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam codelab ini, ikuti langkah-langkah berikut untuk menghapus layanan dan image container Anda.

1. Menghapus Layanan Cloud Run

Cara paling efisien untuk membersihkan adalah dengan menghapus layanan yang Anda deploy ke Cloud Run.

# Delete the main agent and app services
gcloud run services delete researcher content-builder judge orchestrator course-creator \
    --region $REGION --quiet

# Delete the GPU backend (Ollama)
gcloud run services delete ollama-gemma-gpu \
    --region $OLLAMA_REGION --quiet

2. Menghapus Image Artifact Registry

Saat Anda menggunakan flag --source untuk men-deploy, Google Cloud membuat repositori di Artifact Registry untuk menyimpan image container Anda. Untuk menghapus repositori ini dan menghemat biaya penyimpanan, hapus repositori:

gcloud artifacts repositories delete cloud-run-source-deploy --location us-east4 --quiet

3. Menghapus File dan Lingkungan Lokal

Untuk menjaga kebersihan lingkungan Cloud Shell, hapus folder project dan konfigurasi lokal:

cd ~
rm -rf multi-agent-system

4. (Opsional) Menghapus Project

Jika Anda membuat project hanya untuk codelab ini, Anda dapat memastikan tidak ada penagihan lebih lanjut dengan mematikan project itu sendiri melalui Halaman Kelola Resource.

14. Selamat!

Anda telah berhasil membangun dan men-deploy sistem multi-agen terdistribusi yang siap produksi.

Yang telah Anda capai

  • Menguraikan Tugas yang Kompleks: Alih-alih menggunakan satu perintah besar, kami membagi tugas menjadi beberapa peran khusus (Periset, Penilai, Pembuat Konten).
  • Menerapkan Kontrol Kualitas: Kami menggunakan LoopAgent dan Judge terstruktur untuk memastikan hanya informasi berkualitas tinggi yang mencapai langkah terakhir.
  • Dibuat untuk Produksi: Dengan menggunakan protokol Agent-to-Agent (A2A) dan Cloud Run, kami membuat sistem di mana setiap agen adalah microservice yang independen dan dapat diskalakan. Cara ini jauh lebih andal daripada menjalankan semuanya dalam satu skrip Python.
  • Orkestrasi: Kami menggunakan SequentialAgent dan LoopAgent untuk menentukan pola alur kontrol yang jelas. *. GPU Cloud Run: Men-deploy model Gemma ke GPU Cloud Run