Sebelum memulai praktik, pastikan Anda telah memahami konsep dasar pada materi kelas AI Agent & PHP di infokoding.

BAB 23

Troubleshooting AI Agent PHP: Solusi Error Umum

Panduan troubleshooting komprehensif untuk AI Agent PHP: mengatasi Error 401 Unauthorized, 429 Rate Limit, Timeout, tool tidak dipanggil, MCP gagal koneksi, JSON tidak valid.

Terakhir diperbarui:

TL;DR: Panduan Cepat Diagnosis Error AI Agent PHP

  • Error 401 Unauthorized: Kunci API di .env salah atau memiliki spasi tersembunyi.
  • Error 429 Rate Limit: Melebihi kuota TPM/RPM; tangani dengan exponential backoff dan sliding window.
  • cURL Timeout 504: Inferensi agen melebihi 30 detik; naikkan CURLOPT_TIMEOUT dan gunakan async queue.
  • MCP Gagal Terkoneksi: Masalah pada transport JSON-RPC stdio atau path eksekusi binary PHP.
  • Context Length Exceeded: Token prompt melebihi batas model; atasi dengan context sliding window.

Apa Solusi Terbaik untuk Troubleshooting Error AI Agent di PHP?

Direct Answer:Troubleshooting AI Agent PHP berfokus pada isolasi kegagalan pada 5 titik kritis: validasi variabel $_ENV['OPENAI_API_KEY'] untuk mencegah HTTP 401, penanganan jeda $delaySec via exponential backoff pada HTTP 429, konfigurasi opsi CURLOPT_TIMEOUT dan CURLOPT_CONNECTTIMEOUT pada cURL error 28, pemeriksaan stream descriptor proc_open() pada McpServer, serta pemangkasan array $history pada exception ContextLengthExceeded.

Dalam panduan ini, setiap kendala teknis dilengkapi akar penyebab (*root cause*), potongan kode penanganan defensif, konfigurasi telemetri Monolog JSON, serta matriks perbaikan cepat yang diselaraskan dengan dokumentasi resmi platform AI.

Tabel Cepat Diagnosis & Solusi Error AI Agent PHP

Tabel Cepat Solusi Error AI Agent PHP
Kode Error / MasalahAkar Penyebab UtamaLangkah Solusi CepatKomponen Terkait
Error 401 UnauthorizedAPI Key salah, kedaluwarsa, atau terdapat spasi di .envTrimming string .env dan regenerate key di OpenAI DashboardOpenAIClient / Environment
Error 429 Too Many RequestsKuota RPM/TPM limit akun habis atau lonjakan requestGunakan Exponential Backoff dengan Jitter & sliding windowAPI Gateway / Rate Limiter
cURL 28 / HTTP 504 TimeoutRespons ReAct loop memakan waktu > timeout socket cURLNaikkan CURLOPT_TIMEOUT ke 120s atau delegasikan ke Redis QueuePHP-FPM / Worker Supervisor
MCP Server Gagal TerkoneksiPath command STDIO salah atau izin eksekusi script ditolakVerifikasi proc_open transport pipe dan pasang error guardMcpClient / Model Context Protocol
Tool Tidak Dipanggil AIDeskripsi tool terlalu ambigu atau tidak sesuai queryPerjelas docstring tools schema dan set tool_choice: autoMcpServer / System Prompt
JSON Parsing Syntax ErrorOutput LLM memuat teks markdown di luar blok JSONEkstraksi regex ```json...``` dan fallback raw string arrayResponse Parser Helper
Context Length ExceededTotal token dialog history melebihi kapasitas konteksTerapkan Token Sliding Window & Context Pruning HelperDatabaseMemory / Tokenizer
Diagram Alur: AI Agent PHP Troubleshooting & Decision Matrix
WebP Lossless • 107 KB • Schema Ready
Diagram alur keputusan troubleshooting error AI Agent PHP: penanganan Error 401, 429, cURL Timeout, kegagalan MCP, dan Context Length Exceeded
Gambar 23.1: Matriks Diagnosis Masalah — Alur percabangan penanganan error dari sisi API, transport protokol, hingga kapasitas token.

Konfigurasi Monolog JSON Telemetri Error AI Agent

Direct Answer:Perekaman log terstruktur pada AI Agent PHP dikonfigurasi menggunakan driver Monolog\Logger dengan JsonFormatter untuk menyimpan konteks lengkap variabel $httpCode, durasi eksekusi $latencyMs, payload argumen $toolPayload, dan metadata $sessionId ke dalam format JSON baris tunggal yang siap diekspor ke Elasticsearch atau Datadog.

Berikut adalah contoh implementasi logger Monolog siap produksi untuk menangkap kejadian 401, 429, dan cURL timeout:

AgentDiagnosticLogger.php (Monolog JSON Formatter)
<?php

namespace App\Logging;

use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\JsonFormatter;
use Throwable;

class AgentDiagnosticLogger
{
    private Logger $logger;

    public function __construct(string $logPath = '/home/infokoding/infocoding/writable/logs/ai_agent_error.log')
    {
        $this->logger = new Logger('ai_agent_telemetry');

        // 1. Handler file rotasi harian dengan retensi 14 hari
        $handler = new RotatingFileHandler($logPath, 14, Logger::DEBUG);

        // 2. Format output sebagai JSON baris tunggal (NDJSON) untuk agregator log
        $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES, true);
        $handler->setFormatter($formatter);

        $this->logger->pushHandler($handler);
    }

    /**
     * Mencatat detail kegagalan API LLM (401, 429, Timeout) dengan konteks JSON lengkap.
     */
    public function logApiFailure(string $endpoint, int $httpCode, string $rawError, array $extraContext = []): void
    {
        $payload = array_merge([
            'timestamp'   => date('Y-m-d H:i:s'),
            'environment' => $_ENV['CI_ENVIRONMENT'] ?? 'production',
            'endpoint'    => $endpoint,
            'http_code'   => $httpCode,
            'error_raw'   => $rawError,
        ], $extraContext);

        if ($httpCode === 401) {
            $this->logger->critical('LLM_AUTH_FAILED: Kunci API tidak valid atau kedaluwarsa.', $payload);
        } elseif ($httpCode === 429) {
            $this->logger->warning('LLM_RATE_LIMITED: Batas kuota TPM/RPM tercapai, memicu retry.', $payload);
        } elseif ($httpCode === 0 || $httpCode === 504) {
            $this->logger->error('LLM_SOCKET_TIMEOUT: Sambungan cURL terputus sebelum agen selesai merespons.', $payload);
        } else {
            $this->logger->error('LLM_UNEXPECTED_ERROR: Terjadi anomali pada pemanggilan LLM.', $payload);
        }
    }
}

Error 401 Unauthorized (API Key Tidak Valid)

Direct Answer:Error 401 Unauthorized terjadi saat kredensial $_ENV['OPENAI_API_KEY'] yang disematkan pada header Authorization: Bearer tidak dikenali oleh gateway OpenAI, memiliki karakter spasi tersembunyi, atau telah dinonaktifkan menurut panduan Dokumentasi Resmi OpenAI Error Codes.
HTTP Response Body
{"error": {"code": "invalid_api_key", "message": "Incorrect API key provided: sk-proj-***"}}

Gunakan snippet validasi format kredensial berikut sebelum request dikirim:

validateApiKeyPrefix.php
<?php
// Validasi sanitasi kunci API OpenAI sebelum runtime
function validateApiKeyPrefix(string $apiKey): string
{
    $cleanKey = trim($apiKey);
    if (!str_starts_with($cleanKey, 'sk-')) {
        throw new \InvalidArgumentException("Format API Key tidak valid. Kunci harus diawali 'sk-'.");
    }
    return $cleanKey;
}

Error 429 Too Many Requests (Rate Limit & Kuota)

Direct Answer:Error 429 Too Many Requests menandakan agen Anda melampaui batas kecepatan kuota $requestsPerMinute (RPM) atau $tokensPerMinute (TPM) yang diizinkan pada tier akun sesuai spesifikasi Anthropic Rate Limits & Tiering Guide.
HTTP Response Body
{"error": {"code": "rate_limit_exceeded", "message": "You exceeded your current quota, please check your plan."}}

Solusi tangguh menggunakan Exponential Backoff dengan Jitter:

executeWithExponentialBackoff.php
<?php

function executeWithExponentialBackoff(callable $callback, int $maxRetries = 3): mixed
{
    for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
        try {
            return $callback();
        } catch (\Throwable $e) {
            if (str_contains($e->getMessage(), '429') && $attempt < $maxRetries) {
                // Formula: 2^attempt + random jitter (0-1 detik)
                $delaySec = (2 ** $attempt) + (random_int(100, 1000) / 1000);
                usleep((int)($delaySec * 1_000_000));
                continue;
            }
            throw $e;
        }
    }
    throw new \RuntimeException("Batas maksimum retry tercapai.");
}

cURL Timeout dan 504 Gateway Timeout

Direct Answer:Timeout cURL error 28 dan HTTP 504 Gateway Timeout terjadi ketika durasi siklus loop $agentLoop memakan waktu lebih lama daripada konstanta CURLOPT_TIMEOUT di PHP atau direktif fastcgi_read_timeout di Nginx.

Optimasi parameter timeout cURL client:

curl_timeout_config.php
<?php
// Konfigurasi timeout cURL optimal untuk agen multi-tools
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_CONNECTTIMEOUT => 10,  // Maksimal 10 detik untuk handshake
    CURLOPT_TIMEOUT        => 120, // 120 detik untuk proses ReAct loop penuh
    CURLOPT_TCP_KEEPALIVE  => 1,
]);

MCP Server Gagal Terkoneksi (Model Context Protocol)

Direct Answer:Kegagalan koneksi McpServer terjadi akibat kesalahan path binary $binaryPath pada proc_open(), penolakan hak akses berkas, atau ketidaksesuaian format JSON-RPC 2.0 merujuk ke Spesifikasi Resmi Model Context Protocol (MCP).

Berikut adalah penyebab spesifik dan snippet penanganan koneksi MCP defensif di PHP:

  • Penyebab 1 (Binary Path): Path command PHP atau Node.js tidak absolut sehingga gagal dieksekusi oleh proc_open() di lingkungan Nginx/PHP-FPM.
  • Penyebab 2 (STDIO Buffer Deadlock): Pipe stream terblokir (*deadlock*) karena buffer STDERR penuh sebelum STDOUT sempat dibaca.
  • Penyebab 3 (Invalid JSON-RPC Response): Output MCP Server memuat teks peringatan PHP non-JSON (seperti *Deprecated notices*).
SafeMcpTransport.php
<?php

namespace App\MCP;

use RuntimeException;

class SafeMcpTransport
{
    /**
     * Membuka koneksi STDIO ke server MCP secara aman dengan error guard.
     */
    public static function executeMcpCommand(string $binaryPath, string $serverScript, array $jsonPayload): array
    {
        // 1. Pastikan path executable absolut
        if (!file_exists($binaryPath)) {
            throw new RuntimeException("Binary runtime tidak ditemukan: {$binaryPath}");
        }

        $cmd = escapeshellcmd("{$binaryPath} {$serverScript}");
        $descriptors = [
            0 => ['pipe', 'r'], // STDIN
            1 => ['pipe', 'w'], // STDOUT
            2 => ['pipe', 'w'], // STDERR
        ];

        $process = proc_open($cmd, $descriptors, $pipes);
        if (!is_resource($process)) {
            throw new RuntimeException("Gagal menginisialisasi sub-process MCP Server.");
        }

        // 2. Kirim pesan JSON-RPC
        fwrite($pipes[0], json_encode($jsonPayload) . "\n");
        fclose($pipes[0]);

        // 3. Baca STDOUT & tangkap STDERR
        $output = stream_get_contents($pipes[1]);
        $errors = stream_get_contents($pipes[2]);
        fclose($pipes[1]);
        fclose($pipes[2]);

        $exitCode = proc_close($process);
        if ($exitCode !== 0 || empty($output)) {
            throw new RuntimeException("MCP Server crash dengan exit code {$exitCode}. Detail: {$errors}");
        }

        $decoded = json_decode($output, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new RuntimeException("Respons MCP Server bukan JSON-RPC valid: " . substr($output, 0, 100));
        }

        return $decoded;
    }
}

Tool Tidak Dipanggil oleh AI

Direct Answer:Tool tidak dipanggil terjadi akibat deskripsi fungsi $docstring yang kurang jelas, skema parameters.jsonSchema yang tidak valid, atau ketiadaan instruksi pada parameter $systemPrompt.

Tips perbaikan: Paksa pemanggilan tool spesifik menggunakan tool_choice: {"type": "function", "function": {"name": "target_tool"}} jika task bersifat wajib.

Token Habis (Context Length Exceeded)

Direct Answer:Exception context_length_exceeded terjadi saat akumulasi token dari array $messages dan output $toolResults melampaui kapasitas jendela konteks model gpt-4o (128.000 token).
HTTP Response Body
{"error": {"code": "context_length_exceeded", "message": "This model maximum context length is 128000 tokens..."}}

Potongan kode Context Sliding Window Pruning:

pruneConversationContext.php
<?php
// Pemangkas riwayat percakapan otomatis berbasis sliding window
function pruneConversationContext(array $history, int $maxAllowedTurns = 8): array
{
    if (count($history) <= $maxAllowedTurns) {
        return $history;
    }
    // Ambil N pesan terakhir untuk menjaga batas konteks token
    return array_slice($history, -$maxAllowedTurns);
}

FAQ: Tanya Jawab Error Utama AI Agent PHP

1. Bagaimana cara mengatasi Error 401 Unauthorized pada AI Agent PHP?

Ringkasan Jawaban:Periksa apakah ada karakter spasi atau newline tersembunyi di file .env Anda, pastikan key diawali sk-, dan lakukan verifikasi ulang di platform dashboard OpenAI bahwa API Key tersebut belum dicabut atau kedaluwarsa.

Gunakan fungsi trim($_ENV["OPENAI_API_KEY"]) saat memuat kredensial ke class client untuk menghindari karakter whitespace yang tidak sengaja terbawa.

2. Apa langkah penanganan terbaik saat terkena Error 429 Rate Limit?

Ringkasan Jawaban:Terapkan algoritma Exponential Backoff dengan Jitter agar request melakukan jeda waktu bertahap (misal: 2 detik, 4 detik, 8 detik) sebelum mencoba ulang, serta pasang rate limiting lokal di aplikasi Anda.

Jika batas akun sering terlampaui di lingkungan produksi, pertimbangkan untuk menaikkan Tier akun OpenAI Anda dari Tier 1 ke Tier 2/3.

3. Mengapa koneksi MCP Server sering gagal pada lingkungan web server PHP-FPM?

Ringkasan Jawaban:Karena environment web server PHP-FPM sering kali tidak memiliki variabel PATH shell yang sama dengan CLI. Gunakan selalu absolute path (misal: /usr/bin/php atau /usr/bin/node) saat memanggil proc_open.

Pastikan juga direktori kerja memiliki izin baca-tulis yang memadai untuk user www-data atau user virtualhost terkait.

4. Bagaimana mencegah cURL Timeout pada AI Agent yang memiliki banyak tools?

Ringkasan Jawaban:Naikkan CURLOPT_TIMEOUT ke 120 detik, aktifkan fastcgi_read_timeout 120s pada konfigurasi Nginx, atau pisahkan eksekusi task panjang ke sistem asynchronous queue worker (seperti Redis + Supervisor).

Dengan async queue, browser pengguna tidak akan terkena blocking HTTP 504 saat agen mengeksekusi banyak tool secara berurutan.

Key Takeaways: Rangkuman Troubleshooting AI Agent PHP
  • Logging Forensik adalah Kunci: Catat setiap tool call dan error response ke log terstruktur Monolog untuk mempercepat investigasi bug.
  • Resiliensi Transaksi API: Lindungi endpoint dengan retry exponential backoff, timeout proporsional, dan circuit breaker.
  • Kontrol Batas Memori: Gunakan sliding window context pruning agar memori dialog tidak pernah memicu token overflow.
RA

Rusmawan Abdullah Sani

Lead Software Engineer & System Architect

Praktisi pengembangan backend PHP modern, arsitektur AI Agent, microservices, dan otomasi server Linux. Terhubung melalui profil LinkedIn.