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

BAB 23

Troubleshooting Error Umum AI Agent

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:

Error yang Paling Sering Terjadi

  1. Error 401 Unauthorized — API Key tidak valid
  2. Error 429 Too Many Requests — Rate limit tercapai
  3. cURL Timeout — Koneksi lambat atau server lambat merespons
  4. Tool tidak dipanggil — Deskripsi tool tidak cukup jelas
  5. MCP gagal terkoneksi — Konfigurasi MCP Server salah
  6. JSON tidak valid — Respons AI tidak dalam format yang diharapkan
  7. Token habis — Input + output melebihi context window

Error 401 Unauthorized

{"error": {"code": "invalid_api_key", "message": "Incorrect API key provided"}}

Penyebab: API Key salah, expired, atau tidak memiliki permission.

Solusi:

  1. Pastikan tidak ada spasi atau newline di sekitar API Key dalam file .env.
  2. Generate API Key baru di dashboard OpenAI jika sudah expired.
  3. Verifikasi format: Key harus dimulai dengan sk-.
  4. Cek apakah API Key sudah memiliki akses ke model yang digunakan.
// Debug: Tampilkan 10 karakter pertama key (jangan tampilkan full key!)
echo "Key prefix: " . substr($_ENV['OPENAI_API_KEY'], 0, 10) . "...\n";

Error 429 Too Many Requests

{"error": {"code": "rate_limit_exceeded", "message": "You exceeded your current quota"}}

Penyebab: Melebihi RPM (Requests Per Minute) atau TPM (Tokens Per Minute) limit tier Anda.

Solusi:

// Implementasi exponential backoff
function chatWithRetry(OpenAIClient $client, array $messages, int $maxRetries = 3): array
{
    for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
        try {
            return $client->chat($messages);
        } catch (\RuntimeException $e) {
            if (str_contains($e->getMessage(), '429') && $attempt < $maxRetries) {
                $delay = (2 ** $attempt) + random_int(0, 1000) / 1000; // Exponential + jitter
                echo "Rate limit. Retry dalam {$delay}s...\n";
                sleep((int) $delay);
                continue;
            }
            throw $e;
        }
    }
    throw new \RuntimeException('Max retries tercapai');
}

cURL Timeout

Penyebab: Respons AI membutuhkan waktu lama (terutama untuk task kompleks dengan banyak tool calls).

Solusi:

// Naikkan timeout untuk agent yang kompleks
CURLOPT_TIMEOUT => 120, // 2 menit untuk agent dengan banyak tools

// Atau gunakan async queue (lihat Bab 20)
// Untuk Nginx, tambahkan ke konfigurasi:
// fastcgi_read_timeout 120;

Tool Tidak Dipanggil oleh AI

Penyebab: Deskripsi tool tidak cukup jelas atau tidak relevan dengan pertanyaan user.

Solusi:

  1. Perbaiki deskripsi tool — buat lebih spesifik dan tambahkan contoh use case.
  2. Gunakan tool_choice: "required" jika Anda yakin tool harus dipanggil.
  3. Tambahkan instruksi eksplisit di system prompt kapan setiap tool harus digunakan.
  4. Periksa format JSON Schema apakah sudah benar.

JSON Tidak Valid dari AI

// Selalu handle kemungkinan JSON tidak valid
$content = $client->extractContent($response);
$data    = json_decode($content, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    // Coba ekstrak JSON dari markdown code block
    preg_match('/```(?:json)?\s*([\s\S]*?)\s*```/', $content, $matches);
    if (!empty($matches[1])) {
        $data = json_decode($matches[1], true);
    }

    if (json_last_error() !== JSON_ERROR_NONE) {
        // Fallback: kembalikan sebagai string
        return ['raw_response' => $content];
    }
}

Token Habis (Context Length Exceeded)

{"error": {"code": "context_length_exceeded", "message": "This model's maximum context length is..."}}

Solusi:

// Estimasi jumlah token sebelum request
function estimateTokens(string $text): int
{
    // Rata-rata: 1 token ≈ 4 karakter untuk teks bahasa Inggris/Indonesia
    return (int) ceil(strlen($text) / 4);
}

// Truncate history jika mendekati batas
function truncateHistory(array $history, int $maxTokens = 50000): array
{
    $totalTokens = 0;
    $truncated   = [];
    foreach (array_reverse($history) as $msg) {
        $tokens = estimateTokens($msg['content']);
        if ($totalTokens + $tokens > $maxTokens) break;
        $truncated[] = $msg;
        $totalTokens += $tokens;
    }
    return array_reverse($truncated);
}

Poin Kunci Bab 23

Troubleshooting yang efektif dimulai dari logging yang baik. Jika Anda sudah mengimplementasikan logging di Bab 16, sebagian besar masalah akan mudah diidentifikasi dari log files.