DIPERBARUI: 2026-11-06
[A1-M3]Menengahā± 35 Mnt Baca + 50 Mnt Praktik

Mekanisme Tool Calling & Integrasi Fungsi Eksternal

Membongkar Cara LLM Menerjemahkan Bahasa Alami Menjadi Pemanggilan Fungsi JSON Deterministik

BAGIKAN MODUL:
[KONTRAK HASIL BELAJAR // A1-M3]Standar Kompetensi Industri
ā± 35 Mnt Bacaā€¢āš” 50 Mnt Praktik•Lulus: ≄ 80/100 Poin

01. Target Pembelajar & Prasyarat

Developer pemula-menengah, praktisi otomasi, dan pembangun produk yang ingin menghubungkan LLM dengan database atau API dunia nyata.

02. Kompetensi Konseptual (Level 1–2)

  • āœ“Menjelaskan mengapa LLM murni tidak pernah mengeksekusi fungsi atau memanggil API secara langsung di server model.
  • āœ“Memetakan siklus pertukaran 4 pesan (user -> assistant [tool_calls] -> tool [observation] -> assistant [final]) beserta peran pengikat tool_call_id.

03. Kompetensi Praktis & Artefak Nyata (Level 3–4)

  • āœ“Mengonfigurasi definisi skema fungsi menggunakan JSON Schema yang ketat (required, enum, additionalProperties: false).
  • āœ“Mengimplementasikan Agent Execution Loop di Node.js yang menangkap sinyal tool_calls, memvalidasi argumen, menjalankan fungsi lokal/API, dan mengembalikan hasil observasi ke model.
Artefak yang Dibangun: Skrip mandiri `agent-tool-runner.mjs` (Node.js ES Module) yang mengotomasi pengecekan katalog layanan dan perhitungan estimasi proyek.

04. Aplikasi Nyata & Verifikasi

Penerapan Industri: Arsitektur inti di balik asisten triase prospek WhatsApp, agen pengecek status pesanan e-commerce, dan bot operasional internal.

Metode Verifikasi: Menjalankan skrip melalui terminal untuk 3 skenario uji (pertanyaan harga tunggal, perbandingan multi-paket, dan penolakan parameter tidak valid) serta memeriksa jejak JSON pada setiap putaran loop.

[BAGIAN 01 // MASALAH & URGENSI ARSITEKTURAL]

Mengapa Subjek Ini Krusial dalam Rekayasa Nyata?

Pelajari protokol Tool Calling dua arah: dari deklarasi JSON Schema fungsi, sinyal tool_calls, eksekusi di sisi host, hingga observasi balik ke model.

Dalam lingkungan produksi, kegagalan memahami batas-batas arsitektur sistem sering kali menyebabkan bug yang sulit dilacak, pemborosan biaya komputasi, atau antarmuka yang lambat bagi pengguna.

[BAGIAN 02 // MEKANISME DI BALIK LAYAR]

Bagaimana Sistem Sebenarnya Bekerja di Tingkat Protokol

Ilusi Eksekusi: Mengapa LLM Membutuhkan Jembatan Runtime

Banyak pemula mengira bahwa ketika sebuah agen AI memeriksa stok barang di database atau mengirim email, model di cloud itulah yang membuka koneksi jaringan. Ini adalah ilusi visual. Model bahasa pada hakikatnya tidak memiliki akses soket jaringan keluar ke infrastruktur internal Anda.

Yang terjadi sebenarnya adalah sebuah protokol delegasi: model mendeteksi kebutuhan data, menghentikan penulisan kalimat biasa, dan mengeluarkan perintah pemanggilan alat (tool call) dalam format JSON. Aplikasi runtime Anda bertindak sebagai 'tangan dan kaki' yang mengeksekusi perintah tersebut dan menyuapkan fakta hasilnya kembali ke konteks model.

PRINSIP KEAMANAN // AIR-GAPPED REASONING

Jangan pernah menggunakan eval() untuk menjalankan fungsi berdasarkan teks nama alat dari model. Gunakan pemetaan eksplisit (dictionary lookup) terhadap fungsi yang terdaftar.

Siklus 5 Tahap Protokol Tool Calling

1. Deklarasi Skema: Aplikasi mengirimkan deskripsi alat melalui parameter `tools`.

2. Keputusan Model: Model memutuskan memanggil alat dan mengeluarkan `tool_calls` dengan `id` unik.

3. Eksekusi Runtime: Aplikasi mem-parsing argumen, memvalidasi keamanan, dan menjalankan fungsi lokal.

4. Observasi: Hasil dikemas ke dalam pesan ber-role `tool` dengan `tool_call_id` yang cocok.

5. Sintesis Akhir: Model membaca hasil observasi dan menyusun jawaban akurat bagi pengguna.

[DIAGRAM TEKNIS SVG INTERAKTIF // DIAG-04]

Diagram Sekuens Protokol Tool Calling 5 Tahap

LANGKAH 1 DARI 5
ENTITAS AKTIF:Aplikasi Host -> LLM
01
02
03
04
05

Aplikasi mengirim pesan pengguna bersama array spesifikasi fungsi (JSON Schema).

[LIVE PAYLOAD INSPECTOR]JSON 2026
{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "cek_detail_layanan",
        "parameters": {
          "type": "object",
          "properties": {
            "kode_paket": {
              "type": "string"
            }
          }
        }
      }
    }
  ]
}
[BAGIAN 03 // MATRIKS KESALAHPAHAMAN]

Koreksi Asumsi Umum vs Realitas Rekayasa

ƗASUMSI KELIRU

ā€œModel AI mengeksekusi kode database secara langsung di dalam server model.ā€

āœ“REALITAS SISTEM

Model hanya mengeluarkan teks JSON terstruktur yang meminta fungsi dipanggil. Runtime kitalah yang mengeksekusi fungsi di server lokal.

ƗASUMSI KELIRU

ā€œArgumen JSON yang dikeluarkan model pasti selalu benar sesuai skema.ā€

āœ“REALITAS SISTEM

Model tetap bersifat probabilistik; runtime wajib memvalidasi tipe data argumen sebelum menjalankan aksi kritis.

[BAGIAN 04 // LABORATORIUM PRAKTIS & KODE]

Implementasi Langkah-demi-Langkah

Hasil akhir yang diharapkan: Skrip Node.js mandiri yang mampu melayani kueri harga dan perhitungan bundel layanan Z-Automation secara otonom.

STRUKTUR PROYEK DIREKOMENDASIKAN:
lab-a1-m3/
└── agent-tool-runner.mjs

1Membuat Skrip Agent Tool Runner

Kode lengkap dengan registri fungsi lokal dan emulator penalaran terstruktur.

agent-tool-runner.mjs•javascript
āœ“Tested Successfully
LINGKUNGAN TERUJI: Node.js v20.10.0205 BARIS KODE
1// agent-tool-runner.mjs
2// Status: āœ“ Tested Successfully (Node.js v20+)
3
4const KATALOG_Z_AUTOMATION = {
5 "landing-roas": { nama: "Landing Page High-ROAS", hargaRp: 1500000, estimasiHari: 5, fitur: ["Copywriting Konversi", "Integrasi Pixel", "Kecepatan < 1.5s"] },
6 "corporate-3d": { nama: "Corporate WebGL & 3D Experience", hargaRp: 5500000, estimasiHari: 14, fitur: ["Three.js Custom Scene", "CMS Katalog", "Optimasi SEO SSR"] },
7 "ai-agent-crm": { nama: "Otomasi AI Agent WhatsApp & CRM", hargaRp: 3500000, estimasiHari: 7, fitur: ["Hermes Reasoning", "OpenClaw Webhook", "Human-in-the-Loop"] }
8};
9
10const EXECUTABLE_TOOLS = {
11 cek_detail_layanan({ kode_paket }) {
12 const paket = KATALOG_Z_AUTOMATION[kode_paket];
13 if (!paket) {
14 return { sukses: false, error: `Kode paket '${kode_paket}' tidak ditemukan. Pilihan valid: ${Object.keys(KATALOG_Z_AUTOMATION).join(", ")}` };
15 }
16 return { sukses: true, data: paket };
17 },
18
19 hitung_estimasi_bundel({ daftar_kode_paket, diskon_persen = 0 }) {
20 if (!Array.isArray(daftar_kode_paket) || daftar_kode_paket.length === 0) {
21 return { sukses: false, error: "Parameter 'daftar_kode_paket' harus berupa array yang tidak kosong." };
22 }
23 if (typeof diskon_persen !== "number" || diskon_persen < 0 || diskon_persen > 30) {
24 return { sukses: false, error: "Diskon hanya diizinkan antara 0% hingga 30%." };
25 }
26 let subtotal = 0;
27 const rincian = [];
28 for (const kode of daftar_kode_paket) {
29 const item = KATALOG_Z_AUTOMATION[kode];
30 if (!item) return { sukses: false, error: `Paket '${kode}' tidak valid di dalam bundel.` };
31 subtotal += item.hargaRp;
32 rincian.push({ kode, nama: item.nama, hargaRp: item.hargaRp });
33 }
34 const potongan = Math.round(subtotal * (diskon_persen / 100));
35 return {
36 sukses: true,
37 rincian,
38 subtotalRp: subtotal,
39 diskonPersen: diskon_persen,
40 totalAkhirRp: subtotal - potongan
41 };
42 }
43};
44
45const TOOL_DEFINITIONS = [
46 {
47 type: "function",
48 function: {
49 name: "cek_detail_layanan",
50 description: "Mengambil informasi harga resmi, estimasi waktu pengerjaan, dan fitur dari paket layanan Z-Automation.",
51 parameters: {
52 type: "object",
53 properties: {
54 kode_paket: {
55 type: "string",
56 enum: ["landing-roas", "corporate-3d", "ai-agent-crm"],
57 description: "Kode unik paket layanan yang ditanyakan pengguna."
58 }
59 },
60 required: ["kode_paket"],
61 additionalProperties: false
62 }
63 }
64 },
65 {
66 type: "function",
67 function: {
68 name: "hitung_estimasi_bundel",
69 description: "Menghitung total biaya gabungan dari beberapa paket layanan beserta potongan diskon resmi.",
70 parameters: {
71 type: "object",
72 properties: {
73 daftar_kode_paket: {
74 type: "array",
75 items: { type: "string", enum: ["landing-roas", "corporate-3d", "ai-agent-crm"] },
76 description: "Daftar kode paket yang ingin digabungkan."
77 },
78 diskon_persen: {
79 type: "number",
80 description: "Persentase diskon (0 hingga 30). Gunakan 10 untuk bundel 2 paket atau lebih."
81 }
82 },
83 required: ["daftar_kode_paket"],
84 additionalProperties: false
85 }
86 }
87 }
88];
89
90async function panggilModelPenalaran(messages, tools) {
91 const pesanTerakhir = messages[messages.length - 1];
92
93 if (pesanTerakhir.role === "user") {
94 const teks = pesanTerakhir.content.toLowerCase();
95 if (teks.includes("gabung") || (teks.includes("corporate") && teks.includes("agent"))) {
96 return {
97 role: "assistant",
98 content: null,
99 tool_calls: [
100 {
101 id: "call_hermes_901",
102 type: "function",
103 function: {
104 name: "hitung_estimasi_bundel",
105 arguments: JSON.stringify({
106 daftar_kode_paket: ["corporate-3d", "ai-agent-crm"],
107 diskon_persen: 10
108 })
109 }
110 }
111 ]
112 };
113 }
114 return {
115 role: "assistant",
116 content: null,
117 tool_calls: [
118 {
119 id: "call_hermes_101",
120 type: "function",
121 function: {
122 name: "cek_detail_layanan",
123 arguments: JSON.stringify({ kode_paket: "ai-agent-crm" })
124 }
125 }
126 ]
127 };
128 }
129
130 if (pesanTerakhir.role === "tool") {
131 const hasilObservasi = JSON.parse(pesanTerakhir.content);
132 if (!hasilObservasi.sukses) {
133 return {
134 role: "assistant",
135 content: `Maaf, terjadi kendala saat memeriksa data: ${hasilObservasi.error}`
136 };
137 }
138 if (hasilObservasi.totalAkhirRp) {
139 return {
140 role: "assistant",
141 content: `Berdasarkan perhitungan sistem katalog kami, bundel **${hasilObservasi.rincian.map(r => r.nama).join(" + ")}** memiliki subtotal Rp${hasilObservasi.subtotalRp.toLocaleString("id-ID")}. Dengan diskon bundel ${hasilObservasi.diskonPersen}%, total investasi akhir Anda adalah **Rp${hasilObservasi.totalAkhirRp.toLocaleString("id-ID")}**.`
142 };
143 }
144 const d = hasilObservasi.data;
145 return {
146 role: "assistant",
147 content: `Paket **${d.nama}** tersedia dengan biaya **Rp${d.hargaRp.toLocaleString("id-ID")}** (estimasi pengerjaan ${d.estimasiHari} hari kerja), mencakup fitur: ${d.fitur.join(", ")}.`
148 };
149 }
150}
151
152async function jalankanAgen(pertanyaanPengguna) {
153 const MAX_TURNS = 5;
154 const messages = [
155 {
156 role: "system",
157 content: "Anda adalah Agen Konsultan Teknis Z-Automation. Jangan pernah menebak harga layanan. Selalu gunakan fungsi alat yang tersedia untuk mengambil data akurat."
158 },
159 { role: "user", content: pertanyaanPengguna }
160 ];
161
162 console.log(`\n=============================================================`);
163 console.log(`[USER INPUT]: "${pertanyaanPengguna}"`);
164 console.log(`=============================================================`);
165
166 for (let turn = 1; turn <= MAX_TURNS; turn++) {
167 console.log(`\n--- [PUTARAN LOOP #${turn}] Mengirim ${messages.length} pesan ke Model ---`);
168 const responsAsisten = await panggilModelPenalaran(messages, TOOL_DEFINITIONS);
169 messages.push(responsAsisten);
170
171 if (!responsAsisten.tool_calls || responsAsisten.tool_calls.length === 0) {
172 console.log(`\n[FINAL AGENT RESPONSE]:\n${responsAsisten.content}`);
173 return responsAsisten.content;
174 }
175
176 for (const toolCall of responsAsisten.tool_calls) {
177 const namaFungsi = toolCall.function.name;
178 const raWArgs = toolCall.function.arguments;
179 console.log(`[SIGNAL DARI MODEL] Meminta eksekusi fungsi: ${namaFungsi}`);
180 console.log(`[PAYLOAD ARGUMEN JSON]: ${raWArgs}`);
181
182 let hasilEksekusi;
183 try {
184 const argumenTerurai = JSON.parse(raWArgs);
185 const fn = EXECUTABLE_TOOLS[namaFungsi];
186 if (!fn) throw new Error(`Fungsi '${namaFungsi}' tidak terdaftar.`);
187 hasilEksekusi = fn(argumenTerurai);
188 } catch (err) {
189 hasilEksekusi = { sukses: false, error: err.message };
190 }
191
192 console.log(`[OBSERVASI WORKER]: ${JSON.stringify(hasilEksekusi)}`);
193
194 messages.push({
195 role: "tool",
196 tool_call_id: toolCall.id,
197 name: namaFungsi,
198 content: JSON.stringify(hasilEksekusi)
199 });
200 }
201 }
202}
203
204await jalankanAgen("Berapa biaya dan fitur paket otomasi AI Agent WhatsApp?");
205await jalankanAgen("Jika saya gabung pembuatan website Corporate 3D dengan AI Agent, berapa total biayanya?");
KEPUTUSAN ARSITEKTURAL UTAMA:
• Mengikat observasi dengan tool_call_id yang cocok: Model bahasa membutuhkan ID unik untuk memetakan hasil fungsi ke permintaan spesifik, terutama saat beberapa fungsi dipanggil sekaligus (Parallel Tool Calling).
PERINTAH EKSEKUSI TERMINAL:
$ node agent-tool-runner.mjs
OUTPUT YANG DIHARAPKAN:
Paket Otomasi AI Agent WhatsApp & CRM tersedia dengan biaya Rp3.500.000...
Total investasi akhir bundel Corporate 3D + AI Agent: Rp8.100.000 (setelah diskon 10%).
[BAGIAN 05 // PANDUAN TROUBLESHOOTING & TANTANGAN]

Mengantisipasi Masalah Umum & Tantangan Ekstensi

Pesan Error: Invalid tool_call_id in tool message
Penyebab: ID pada pesan role: tool berbeda dengan ID yang dikeluarkan asisten
Solusi Eksak: Pastikan tool_call_id: toolCall.id diteruskan persis tanpa perubahan.
⚔ TANTANGAN EKSTENSI MANDIRI:

Tambahkan paket baru 'undangan-vip' ke dalam katalog dan verifikasi respons kuerinya.

[RUBRIK EVALUASI KOMPETENSI 100 POIN // A1-M3]

Uji Kompetensi Mandiri & Verifikasi Hasil

Standar kelulusan Z-Automation mewajibkan skor minimum 80 / 100 Poin dengan komponen Implementasi Praktis minimal 21 / 35 Poin (60%). Jawab soal diagnostik dan centang hasil pengujian praktis Anda.

BAGIAN A // PERTANYAAN DIAGNOSTIK KONSEPTUAL & TEKNIS (40 POIN)

01.Mengapa pesan balasan dari worker wajib menyertakan properti tool_call_id?

02.Di mana letak bahaya jika fungsi alat dijalankan menggunakan eval(toolCall.function.name + '(' + args + ')')?

BAGIAN B // DAFTAR PERIKSA HASIL IMPLEMENTASI PRAKTIS (35 POIN — MIN. 21 POIN)

Centang item di bawah ini hanya jika Anda telah menjalankan kode di komputer Anda dan mengamati output yang benar:

Lanjutkan Menggulir
untuk Eksplorasi
Edukasi & Lab
Halaman Selanjutnya