DEBI PRAHARADIKA
← Back to Blog Index
Generative AI2026-08-1035 min read

Membangun AI Agent Menggunakan Function Calling / Tool Use pada Backend PHP dan Go

Large Language Model (LLM) pada dasarnya buta terhadap sistem internal Anda. Maka pelajari bagaimana cara memberikan 'tangan' kepada AI melalui arsitektur Function Calling dengan menggunakan PHP dan Golang.

"The next leap in AI isn't just about models knowing more, it's about models doing more. Agents that can take actions in the real world are the future." — Andrew Ng, AI Pioneer

Di masa lalu, berinteraksi dengan Large Language Model (LLM) seperti GPT-4, Gemini atau Claude ibaratnya berbicara dengan seorang jenius yang terkunci di balik sebuah dinding. Mereka tahu segalanya tentang dunia hingga batas data pelatihannya, namun mereka buta sama sekali terhadap basis data perusahaan Anda hari ini. Dengan hadirnya fitur Function Calling (atau Tool Use) maka dinding tersebut telah runtuh. Dengan fitur ini, kita bisa memberikan "tangan" kepada LLM untuk berinteraksi dengan sistem internal kita, mulai dari menarik laporan penjualan, hingga mengirim email ke klien. Namun, untuk menyerahkan kunci database kepada AI secara langsung bukan solusi teraman karena menyebabkan bobolnya keamanan (Security Nightmare). Maka inilah peran Software Engineering diperlukan untuk memitigasinya. Kami akan berbagi pengalaman merancang AI Agent yang aman dengan meletakkan PHP dan Golang (Go) sebagai Middleware Guardrails.


1. Arsitektur Function Calling

Bagaimana cara kerja Function Calling pada suatu sistem? LLM tidak pernah tidak akan mengeksekusi kode secara langsung. Mereka hanya mengembalikan teks berformat JSON yang menginstruksikan pada sistem untuk mengeksekusinya.

Diagram Arsitektur Function Calling AI Agent yang menampilkan siklus instruksi JSON dari LLM ke Backend lalu kembali ke LLM

Siklus Eksekusinya adalah sebagai berikut:

  1. Definisi Fungsi: Backend kita mengirimkan prompt ke LLM beserta daftar fungsi yang tersedia (misal: get_sales_data(period)).
  2. LLM Memutuskan: Saat pengguna bertanya "Berapa penjualan kuartal ini?", LLM menyadari ia tidak tahu jawabannya, tapi ia tahu ada alat (get_sales_data) yang bisa digunakan.
  3. LLM Merespons dengan JSON: Alih-alih menjawab dengan teks biasa, LLM merespons dengan JSON: {"name": "get_sales_data", "arguments": {"period": "Q3 2026"}}.
  4. Eksekusi Backend: Backend kita (PHP/Go) menangkap JSON ini, memvalidasinya, lalu mengeksekusi query SQL ke database.
  5. Injeksi Hasil: Backend mengirimkan hasil query SQL (dalam bentuk teks) kembali ke LLM.
  6. Jawaban Final: LLM membaca hasil query tersebut, lalu merangkainya menjadi jawaban natural berbahasa manusia.

2. Mengapa Mengeksekusinya di Level Backend (PHP/Go)?

Beberapa orang mencoba mengeksekusi Function Calling langsung dari sisi Frontend (JavaScript/React) yang memanggil layanan pihak ketiga. Ini sangat berbahaya.

Kami di perusahaan menetapkan standar bahwa semua Tool Use harus dijembatani oleh Backend (baik menggunakan PHP Laravel maupun Golang ataupun NodeJS). Alasannya adalah

  • Otorisasi dan Validasi (Guardrails): LLM bisa berhalusinasi dan mencoba menghapus data (DROP TABLE). Backend bertugas menolak parameter JSON yang tidak masuk akal atau mencoba membobol batas akses pengguna (Tenant Isolation).
  • Kerahasiaan Kredensial: API Keys database dan pihak ketiga harus tetap tersembunyi dengan aman di dalam server environment.

3. Implementasi PHP dan Golang

Dalam arsitektur terdistribusi atau polyglot, kami sering memposisikan PHP (terutama framework mainstream seperti Laravel) sebagai API Gateway atau Orchestrator utama. Fleksibilitas manipulasi array pada PHP sangat memudahkan developer saat harus merangkai prompt dan mendefinisikan schema JSON yang kompleks. Sementara itu, Golang difokuskan sebagai microservice independen atau worker yang berkinerja tinggi di belakang layar untuk mengeksekusi pencarian data yang intensif. Berikut tahapan-tahapan implementasinya:

Tahap 1: PHP Mendefinisikan Tool ke LLM

Di sisi PHP, kita memberikan tugas dan daftar fungsi apa saja yang boleh dipakai oleh LLM.

<?php

use Langchain\Tools\Tool;
use Langchain\ChatModels\OpenAIChat; // Anda bisa dengan mudah menggantinya ke ClaudeChat / GeminiChat
use Langchain\Agents\InitializeAgent;

// 1. Mendefinisikan Tool menggunakan Object-Oriented Class
class GetSalesDataTool extends Tool
{
    public string $name = 'get_sales_data';
    public string $description = 'Mendapatkan total data penjualan berdasarkan kuartal (contoh: Q3 2026).';

    // Metode ini akan otomatis tereksekusi oleh LangChain jika LLM memanggil Tool ini
    protected function _call(string $period): string
    {
        // Lempar beban eksekusi ke Microservice Golang via API internal
        $httpClient = new HttpClient();
        $result = $httpClient->post('http://golang-service-internal/execute-tool', [
            'json' => [
                'function' => $this->name,
                'arguments' => json_encode(['period' => $period])
            ]
        ]);

        // Hasil string dari Golang (Database) akan langsung ditangkap
        return $result->getBody()->getContents(); 
    }
}

// 2. Inisialisasi Model LLM (Bebas Lock-in Vendor)
$llm = new OpenAIChat(['model_name' => 'gpt-4o', 'temperature' => 0]);

// 3. Menggabungkan Tool dan LLM ke dalam satu entitas Agent
$tools = [new GetSalesDataTool()];
$agent = InitializeAgent::initializeAgentExecutor($tools, $llm, 'chat-conversational-react-description');

// 4. Eksekusi Agent
// TAHAP AKHIR: LangChain secara otomatis menangani siklus:
// Pertanyaan -> Deteksi Tool -> Eksekusi PHP (melempar ke Go) -> Kembalikan hasil ke LLM -> Cetak Jawaban
$response = $agent->run("Berapa penjualan untuk Q3 2026?");

echo $response; // Output: "Total penjualan untuk Q3 2026 adalah $1,250,000."

Tahap 2: Golang Bertindak sebagai Eksekutor dan Guardrail

Berikut logika di sisi Golang saat API internalnya menerima perintah JSON dari servis PHP kita:

package agent

import (
	"encoding/json"
	"fmt"
	"log"
)

// Struktur instruksi Tool Call yang dikirimkan oleh servis PHP
type ToolCallRequest struct {
	FunctionName string `json:"function"`
	Arguments    string `json:"arguments"` // Berisi JSON String dari parameter
}

// Argumen spesifik yang diputuskan oleh LLM
type SalesArguments struct {
	Period string `json:"period"`
}

// Handler untuk mengeksekusi fungsi lokal
func ExecuteAgentTool(request *ToolCallRequest) string {
	if request.FunctionName == "get_sales_data" {
		var args SalesArguments
		
		// Validasi dan parsing argumen dari LLM
		err := json.Unmarshal([]byte(request.Arguments), &args)
		if err != nil {
			return "Error: Format argumen dari LLM tidak valid."
		}

		// GUARDRAIL: Pastikan argumen sesuai dengan kebijakan keamanan
		if args.Period == "" {
			return "Error: Periode wajib diisi."
		}

		// Eksekusi fungsi internal (misal: query ke PostgreSQL)
		log.Printf("[AI-AGENT] Executing get_sales_data for period: %s", args.Period)
		result := fetchSalesFromDatabase(args.Period) 
		
		return result // Hasil ini akan dikirim kembali ke LLM via PHP
	}

	return "Error: Fungsi tidak ditemukan di sistem."
}

func fetchSalesFromDatabase(period string) string {
	// Simulasi hasil query
	return fmt.Sprintf("Total penjualan untuk %s adalah $1,250,000", period)
}

Penjelasan: Pada blok ExecuteAgentTool di Golang, kita tidak langsung percaya argumen yang diberikan LLM. Maka kita melakukan unmarshal dan memasang guardrail. Ini adalah lapisan keamanan penting dalam implementasi aplikasi skala Enterprise.


4. Desain Antarmuka Pengguna (UI)

Ketika AI sedang mengeksekusi fungsi di belakang layar, delay bisa memakan waktu beberapa detik. Untuk mencegah pengguna berasumsi bahwa aplikasi sedang hang, rancangan antarmuka pengguna (UI) harus menampilkan status eksekusi fungsi secara jelas.

UI Dashboard Internal menampilkan AI Assistant yang sedang berinteraksi dengan pengguna. Terdapat blok terminal mini yang mengindikasikan bahwa AI sedang mengeksekusi fungsi fetch_sales_data secara internal

Alih-alih sekadar menampilkan ikon loading berputar, praktik terbaik kami adalah memperlihatkan "Terminal Mini" atau "Log Eksekusi". Ketika AI memanggil fungsi get_sales_data, UI akan memunculkan status: > Executing function... > Querying database.... Transparansi ini membangun kepercayaan psikologis yang sangat tinggi dari sisi klien terhadap kapabilitas AI Anda.


5. Peran LangChain PHP

Saat implementasi, mungkin Anda akan menyadari satu rintangan besar: bagaimana jika suatu hari perusahaan memutuskan untuk bermigrasi dari OpenAI (GPT-4) ke Google (Gemini) atau Anthropic (Claude)? Seperti yang telah dibahas sebelumnya, setiap penyedia LLM memiliki struktur payload JSON yang benar-benar berbeda untuk mendefinisikan Function Calling.

Di sinilah LangChain PHP berfungsi, LangChain PHP adalah sebuah framework yang menyederhanakan kompleksitas berbagai model LLM ke dalam satu sintaks standar yang seragam. LangChain PHP juga berfungsi sebagai abstraksi ekosistem, yang merangkum kompleksitas berbagai model LLM ke dalam satu sintaks standar yang seragam.

Dengan menggunakan LangChain PHP, Anda cukup mendefinisikan Tool atau Function menggunakan kelas (Class) PHP. Di belakangnya, framework inilah yang akan mengambil alih tugas menerjemahkan definisi fungsi Anda kedalam format spesifik milik OpenAI, struktur spesifik Claude, ataupun format Gemini secara otomatis. Ini adalah best practice bagi perusahaan yang ingin membangun solusi AI yang handal dan terbebas dari ketergantungan pada satu vendor (Vendor Lock-in).


Model Generative AI tak lebih dari sekadar mesin canggih jika tidak dihubungkan dengan dunia nyata. Fitur Function Calling / Tool Use adalah jembatan penghubung di mana Software dapat bertindak secara otonom berdasarkan niat (intent) pengguna.

Namun, di tengah euforia ini, ketegasan arsitektural di sisi Backend (menggunakan PHP, Go, atau bahasa pemrograman lainnya) adalah cara untuk menjaga agar agen otonom ini tetap terkendali, aman, dan bekerja semata-mata di dalam koridor otoritas yang kita berikan.

Tetap semangat belajar, bereksplorasi, dan jangan pernah berhenti membangun hal-hal yang luar biasa!