Rekayasa Balik Claude Code Agent Teams: Arsitektur dan Protokol

Terjemahan mesin Artikel asli.

Banner for Rekayasa Balik Claude Code Agent Teams: Arsitektur dan Protokol

isi

Pendahuluan

Claude Code (v2.1.47) hadir dengan fitur eksperimental bernama Agent Teams: beberapa sesi Claude Code berkoordinasi untuk mengerjakan pekerjaan bersama melalui topologi pemimpin dan anggota tim. Saya sedang mengembangkan Hive, sebuah orkestrator pemrograman multiagen dengan tujuan serupa tetapi arsitektur yang sangat berbeda, jadi saya ingin memahami cara kerja pendekatan Anthropic di balik layar.

Artikel ini mendokumentasikan temuan saya melalui:

  1. Membaca dokumentasi resmi
  2. Memeriksa artefak nyata yang ditinggalkan di disk oleh sesi tim sebelumnya
  3. Meminta Claude menganalisis biner Claude Code (v2.1.47) untuk mengetahui detail implementasinya (hah!)

Daftar Isi

1. Gambaran Umum Arsitektur

Sebuah tim agen terdiri dari empat komponen:

Komponen Peran
Pemimpin tim Sesi utama Claude Code yang membuat tim dan menjalankan anggota tim
Anggota tim Instans Claude Code yang terpisah, masing-masing dengan jendela konteks sendiri
Daftar tugas Butir pekerjaan bersama yang disimpan sebagai berkas JSON tersendiri di disk
Kotak surat Berkas kotak masuk untuk setiap agen guna mengirimkan pesan

Seluruh lapisan koordinasinya berbasis berkas. Sistem berkas di ~/.claude/ menjadi satu-satunya landasan koordinasi:

~/.claude/
├── teams/{team-name}/
│   ├── config.json                  # team membership registry
│   └── inboxes/{agent-name}.json    # per-agent mailbox
└── tasks/{team-name}/
    ├── .lock                        # flock() for concurrent task claiming
    ├── .highwatermark               # auto-increment counter
    ├── 1.json                       # individual task files
    ├── 2.json
    └── ...

Desain ini pada dasarnya terdesentralisasi. Pemimpin hanyalah sesi Claude lain dengan alat tambahan (TeamCreate, TeamDelete, SendMessage). Tidak ada proses latar belakang. Koordinasi terbentuk melalui akses berkas bersama.

Dalam sesi aktif, jika Anda meminta Claude membentuk tim untuk mengerjakan suatu tugas lalu menjalankan perintah berikut di jendela lain, Anda dapat mengamati perubahan sistem berkas secara langsung.

watch -n 0.5 'tree ~/.claude/teams/ 2>/dev/null; echo "---"; tree ~/.claude/tasks/ 2>/dev/null'

Misalnya, dengan prompt berikut:

can you spawn an agent team to examine this codebase?
  - have one look for bugs
  - have one look for complexity
  - have one look for good things to call out and play devil's advocate against the other two agents

Saya mengamati hal ini:

teams
└── code-review
    ├── config.json
    └── inboxes
        ├── bug-hunter.json
        ├── complexity-analyst.json
        ├── devils-advocate.json
        └── team-lead.json

Konfigurasi Tim

Konfigurasi tim di ~/.claude/teams/{team-name}/config.json berisi array members yang dibaca anggota tim untuk menemukan satu sama lain:

{
  "members": [
    { "name": "team-lead", "agentId": "abc-123", "agentType": "leader" },
    {
      "name": "researcher",
      "agentId": "def-456",
      "agentType": "general-purpose"
    }
  ]
}

Nama menjadi mekanisme pengalamatan utama (UUID ada, tetapi tidak digunakan untuk perutean). Semua pengiriman pesan dan penugasan menggunakan field name.

2. Daftar Tugas Bersama

Format Berkas

Setiap tugas disimpan sebagai berkas JSON tersendiri di ~/.claude/tasks/{team-name}/. Berikut contoh nyata dari sesi sebelumnya:

{
  "id": "1",
  "subject": "Hunt for bugs across the codebase",
  "description": "...",
  "activeForm": "Hunting for bugs",
  "owner": "bug-hunter",
  "status": "completed",
  "blocks": [],
  "blockedBy": []
}

Skema tugas:

Field Tipe Deskripsi
id string ID numerik, bertambah otomatis melalui .highwatermark
subject string Judul berbentuk perintah (misalnya, "Jalankan pengujian")
description string Persyaratan terperinci dan kriteria penerimaan
activeForm string Bentuk present continuous untuk tampilan spinner ("Sedang menjalankan pengujian")
status string pending → in_progress → completed (atau deleted)
blocks string[] ID tugas yang terhalang oleh tugas ini
blockedBy string[] ID tugas yang harus selesai sebelum tugas ini dapat dimulai

Kontrol Konkurensi

Dua berkas khusus menyediakan koordinasi:

  • .lock: Berkas berukuran 0 byte yang digunakan untuk eksklusi mutual pada tingkat sistem berkas (flock()). Ada di seluruh 42 direktori tugas yang saya amati di komputer saya.
  • .highwatermark: Berisi satu bilangan bulat (misalnya, "3", "13"). Nilainya adalah ID tugas berikutnya yang tersedia untuk penomoran otomatis.

Pengambilan Tugas

Pengambilan tugas menggunakan penguncian berkas untuk mencegah kondisi balapan. Anggota tim mengutamakan urutan dari ID terendah. Tugas dengan array blockedBy yang tidak kosong tidak dapat diambil sampai semua tugas yang menghalanginya berada dalam status akhir.

Pengamatan: Sebagian Besar Direktori Tugas Kosong

Dari 42 direktori tugas di komputer saya, hanya 5 yang benar-benar berisi berkas JSON tugas. Sebanyak 37 sisanya hanya berisi .lock dan .highwatermark. Ini kemungkinan berarti tugas dibersihkan setelah selesai, atau direktori tersebut berasal dari sesi ketika Claude menggunakan daftar tugas internal (tersedia sejak peluncuran fitur daftar tugas) tanpa memecahnya menjadi berkas subtugas.

3. Komunikasi Antaragen

Pola Kotak Surat

Setiap agen memiliki berkas array JSON di ~/.claude/teams/{team-name}/inboxes/{agent-name}.json. Berikut kotak masuk nyata dari sesi sebelumnya ketika pemimpin tim memberikan pekerjaan kepada controlplane-agent:

[
  {
    "from": "team-lead",
    "text": "{\"type\":\"task_assignment\",\"taskId\":\"1\",\"subject\":\"Phase 2: Control-plane - remove participants/presence\",\"description\":\"Remove multiplayer code from the control-plane package...\",\"assignedBy\":\"team-lead\",\"timestamp\":\"2026-02-18T02:37:16.890Z\"}",
    "timestamp": "2026-02-18T02:37:16.890Z",
    "read": false
  }
]

Perhatikan pengodean JSON-di-dalam-JSON: field text merupakan string JSON yang berisi objek pesan yang telah diserialisasi. Amplop luarnya memiliki field from, text, timestamp, dan read.

Jenis Pesan

Field type di dalam payload text mendukung:

Jenis Arah Tujuan
task_assignment pemimpin → anggota Memberikan tugas dengan detail lengkap
message siapa pun → siapa pun Pesan langsung kepada satu penerima
broadcast pemimpin → semua Pesan yang sama kepada setiap anggota tim
shutdown_request pemimpin → anggota Meminta penghentian secara tertib
shutdown_response anggota → pemimpin Menyetujui atau menolak penghentian
plan_approval_request anggota → pemimpin Mengajukan rencana untuk ditinjau
plan_approval_response pemimpin → anggota Menyetujui atau menolak dengan umpan balik
idle_notification anggota → pemimpin Dikirim otomatis saat giliran anggota tim berakhir

Mekanisme Pengiriman

Jalur penulisan: Pengirim menambahkan entri baru ke berkas array JSON kotak masuk penerima.

Jalur pembacaan: Penerima memeriksa berkas kotak masuknya sendiri secara berkala. Pesan baru disisipkan sebagai giliran percakapan sintetis (tampil seolah-olah dikirim oleh pengguna).

Siaran: Secara harfiah menulis pesan yang sama ke berkas kotak masuk setiap anggota tim. Biaya token bertambah secara linear seiring ukuran tim.

Komunikasi hanya berupa penambahan isi berkas + pembacaan berkas. Latensi antara pengiriman dan penerimaan bergantung pada interval pemeriksaan penerima.

Visibilitas DM Antaranggota

Ketika seorang anggota tim mengirim DM kepada anggota lain, ringkasan singkatnya disertakan dalam notifikasi idle yang diterima pemimpin. Ini memungkinkan pemimpin mengetahui kolaborasi antaranggota tanpa melihat isi pesan lengkapnya.

4. Pembuatan dan Siklus Hidup Agen

Cara Anggota Tim Dibuat

Setiap anggota tim merupakan proses CLI claude yang terpisah. Pemimpin menjalankannya melalui alat Task dengan parameter team_name dan name. Variabel lingkungan ditetapkan pada proses yang dijalankan:

  • CLAUDE_CODE_TEAM_NAME: ditetapkan otomatis pada anggota tim yang dijalankan
  • CLAUDE_CODE_PLAN_MODE_REQUIRED: ditetapkan ke true jika persetujuan rencana diperlukan

Inisialisasi Konteks

Anggota tim memuat konteks proyek yang sama seperti sesi baru pada umumnya:

  • Berkas CLAUDE.md dari direktori kerja
  • Server MCP
  • Skill
  • Prompt awal dari pemimpin

Riwayat percakapan pemimpin TIDAK ikut dibawa. Setiap anggota tim memulai dari awal dengan hanya prompt awal sebagai konteks.

Implementasi Internal

Dari analisis biner Claude Code v2.1.47, konteks anggota tim dikelola melalui AsyncLocalStorage dengan field berikut:

  • agentId, agentName, teamName
  • parentSessionId, color
  • planModeRequired

Fungsi internal utama:

  • isTeammate() / isTeamLead(): deteksi peran
  • waitForTeammatesToBecomeIdle(): primitif sinkronisasi untuk pemimpin
  • getTeammateContext() / setDynamicTeamContext(): pengelolaan konteks saat eksekusi

Deteksi Idle

Setelah setiap giliran LLM, anggota tim secara otomatis masuk ke status idle dan mengirim idle_notification kepada pemimpin. Ini adalah status istirahat normal, bukan kondisi kesalahan atau tidak adanya aktivitas yang berkepanjangan. Mengirim pesan kepada anggota tim yang idle akan mengaktifkannya kembali (siklus pemeriksaan berikutnya mengambil pesan dari kotak masuk).

Protokol Penghentian

  1. Pemimpin mengirim shutdown_request kepada anggota tim
  2. Anggota tim dapat menyetujui (keluar secara tertib) atau menolak (melanjutkan pekerjaan dengan memberikan penjelasan)
  3. Pembersihan tim melalui TeamDelete menghapus ~/.claude/teams/{team-name}/ dan ~/.claude/tasks/{team-name}/
  4. Pembersihan gagal jika masih ada anggota tim yang aktif; mereka harus dihentikan terlebih dahulu

Pewarisan Izin

Anggota tim mewarisi mode izin pemimpin saat dijalankan. Jika pemimpin menjalankan --dangerously-skip-permissions, semua anggota tim juga demikian. Mode masing-masing dapat diubah setelah dijalankan, tetapi tidak dapat dikonfigurasi per anggota saat pertama kali dijalankan.

5. Gerbang Kualitas dan Hook

Agent Teams terintegrasi dengan sistem hook Claude Code untuk menegakkan standar kualitas:

Hook TeammateIdle

Dipicu saat anggota tim akan masuk ke status idle. Kode keluar 2 mengirim stderr sebagai umpan balik dan mencegah status idle, sehingga anggota tim terus bekerja.

{
  "hook_event_name": "TeammateIdle",
  "teammate_name": "researcher",
  "team_name": "my-project"
}

Hook TaskCompleted

Dipicu saat tugas sedang ditandai selesai. Kode keluar 2 mencegah penyelesaian dan mengirimkan kembali stderr sebagai umpan balik.

{
  "hook_event_name": "TaskCompleted",
  "task_id": "task-001",
  "task_subject": "Implement user authentication",
  "task_description": "Add login and signup endpoints",
  "teammate_name": "implementer",
  "team_name": "my-project"
}

Hook ini dipicu dalam dua situasi: (1) ketika agen mana pun secara eksplisit menandai tugas sebagai selesai melalui TaskUpdate, atau (2) ketika anggota tim agen mengakhiri gilirannya dengan tugas yang masih berlangsung.

Jenis Penangan Hook

Jenis Deskripsi
command Skrip shell. JSON pada stdin, kode keluar untuk keputusan.
prompt Evaluasi LLM satu giliran. Mengembalikan {ok, reason}.
agent Subagen dengan beberapa giliran dan alat baca. Hingga 50 giliran.

6. Ekonomi Token

Tim agen menggunakan sekitar 7× lebih banyak token daripada sesi standar saat anggota tim berjalan dalam mode perencanaan. Setiap anggota tim mempertahankan jendela konteks lengkapnya sendiri sebagai instans Claude yang terpisah.

Acuan Dasar

  • Rata-rata penggunaan Claude Code: ~$6/pengembang/hari
  • Tim agen: tambahan di atas penggunaan dasar, kurang lebih sebanding dengan ukuran tim

7. Ringkasan Arsitektur

Dimensi Claude Code Agent Teams
Landasan koordinasi Berkas datar (~/.claude/tasks/, ~/.claude/teams/)
Format tugas Satu berkas JSON per tugas + .lock untuk pengambilan
Pengiriman pesan Berkas kotak masuk JSON (penambahan + pemeriksaan berkala)
Siklus hidup agen Proses CLI yang mengelola dirinya sendiri
Isolasi pekerjaan Direktori kerja bersama
Strategi penggabungan Tidak ada (agen menyunting berkas secara langsung)
Percobaan ulang/eskalasi Manual (pemimpin memutuskan, atau pengguna turun tangan)
Topologi Pemimpin + anggota sejajar, pengiriman pesan antaranggota
Penjadwalan Pengambilan mandiri (anggota tim mengambil tugas berikutnya)
Persistensi status Hanya berkas; tidak ada pelanjutan kembali anggota tim dalam proses
Gerbang kualitas Hook shell (TeammateIdle, TaskCompleted)
Pelacakan token Hanya per sesi, tanpa agregasi antaragen
Deteksi kemacetan Manual (pengguna menyadari anggota tim berhenti)
Kontrol konkurensi Implisit (ukuran tim = jumlah anggota tim)
Model dependensi blocks/blockedBy pada berkas tugas

Sumber

Dokumentasi Resmi

Artefak di Disk (Claude Code v2.1.47)

Diamati di /Users/tau/.claude/:

  • Direktori tim dengan berkas config.json dan inboxes/{agent-name}.json
  • Direktori tugas dengan .lock, .highwatermark, dan berkas JSON tersendiri untuk setiap tugas
  • Contoh pesan penugasan dari team-lead kepada cp-agent, dengan stempel waktu 2026-02-18T02:37:16.890Z

Analisis Biner

Biner Claude Code v2.1.47. Fungsi internal yang diidentifikasi melalui analisis string: getTeamName, getAgentName, getAgentId, isTeammate, isTeamLead, waitForTeammatesToBecomeIdle, getTeammateContext, setDynamicTeamContext, createTeammateContext. Field konteks AsyncLocalStorage: agentId, agentName, teamName, parentSessionId, color, planModeRequired.

Basis Kode Hive