Agen AI kini membaca error API Anda

Bagikan

Pada bulan Maret, Mintlify menjumlahkan lalu lintas satu bulan ke situs dokumentasi yang di-hosting-nya. Hasilnya sekitar 790 juta request, dan 45,3% di antaranya dibuat oleh agen coding AI. Browser membuat 45,8%. Claude Code sendirian mengirim seperempat dari semuanya (angka dari Mintlify).

Itu lalu lintas ke dokumentasi, bukan ke API. Tetapi agen yang membaca dokumentasi adalah agen yang sama yang kemudian menulis request, menjalankannya, dan membaca apa pun yang kembali. Dalam survei State of the API 2025 dari Postman, 24% developer mengatakan mereka sudah merancang API dengan memperhitungkan agen. Saat survei itu keluar, kedengarannya terlalu dini. Sekarang tidak lagi.

Sebagian besar yang kami bangun di sini berkisar pada kegagalan: endpoint yang mengembalikan 500, macet, atau berhenti di tengah response. Jadi pertanyaan yang terus kami ajukan sangat spesifik. Saat agen mendapat error dari API Anda, apakah ia punya cukup informasi untuk melakukan hal yang benar berikutnya?

Agen menerima pesan error Anda apa adanya

Developer yang menerima {"error":"E4021"} mencari kodenya, tidak menemukan apa-apa, lalu bertanya ke rekan kerja. Agen tidak bisa bertanya ke siapa pun. Ia bekerja dengan body yang Anda kirim, dan jika body itu tidak berisi hal yang berguna, ia menebak: mengulang request yang sama, atau mengubah field yang sebenarnya sudah benar.

Inilah yang dikatakan endpoint produk kami saat ID-nya tidak ada:

Terminal
$ curl -i https://api.testingapis.com/api/Products/99999
HTTP/1.1 404 Not Found
content-type: application/json; charset=utf-8

{"status":404,"error":"Not Found","message":"Product with ID 99999 does not exist."}

Kalimatnya membosankan, dan itu tidak apa-apa. Ia menyebut resource dan ID-nya, jadi siapa pun yang membacanya, manusia atau program, tahu bahwa masalahnya ada di ID dan mengirim ulang tidak akan membantu.

Jika Anda ingin bentuk standar untuk error, RFC 9457 (Problem Details for HTTP APIs) mendefinisikan type, title, status, detail, dan instance, yang dikirim sebagai application/problem+json. RFC ini menggantikan RFC 7807 pada 2023. Menurut kami format persisnya tidak terlalu penting. Yang penting ada kalimat yang jelas di suatu tempat.

Sebutkan berapa lama harus menunggu

Agen mencoba ulang. Jika 429 atau 503 Anda tidak menyebutkan berapa lama harus menunggu, klien harus memilih angka sendiri, dan agen yang mengerjakan tugas dalam loop akan terus memilih. Retry-After sudah menjadi bagian HTTP selama puluhan tahun dan menyelesaikan ini dengan satu header:

Terminal
$ curl -i https://api.testingapis.com/api/status/429
HTTP/1.1 429 Too Many Requests
content-type: application/json; charset=utf-8
retry-after: 5

{"status":429,"statusText":"Too Many Requests","category":"client-error","message":"This is a 429 response. Use /api/status/{code} to request any status."}
GET/api/status/429

IETF juga sedang menggarap header RateLimit dan RateLimit-Policy, yang memungkinkan klien melihat kuotanya sebelum habis, bukan sesudahnya. Draf 11 keluar pada bulan Mei. Sintaksnya seperti ini:

Header
RateLimit-Policy: "default";q=100;w=60
RateLimit: "default";r=50;t=30

Itu dibaca sebagai "100 request per 60 detik, sisa 50, jendela direset dalam 30". Ini masih draf, jadi kami tidak akan membuang header X-RateLimit-* yang sudah dibaca klien Anda. Mengirim keduanya hampir tanpa biaya.

Retry menciptakan duplikat

Mengulang GET tidak berbahaya. Mengulang POST berbahaya, jika percobaan pertama sudah sampai ke server dan hanya response-nya yang hilang. Anda berakhir dengan dua pesanan. Manusia biasanya menyadari tagihan ganda. Agen melihat percobaan keduanya berhasil dan melanjutkan.

Solusi yang biasa adalah idempotency key. Klien mengirim header Idempotency-Key yang unik bersama penulisan, dan jika kunci yang sama datang lagi, server mengembalikan hasil pertama alih-alih mengerjakannya dua kali. Stripe sudah bekerja seperti ini bertahun-tahun, dan ada draf IETF untuk header ini, meski belum menjadi RFC. Jika API Anda menerima pembayaran atau membuat sesuatu yang merepotkan untuk dibersihkan, layak ditambahkan sebelum agen mulai memanggilnya.

Server MCP berubah menjadi API HTTP biasa

Banyak agen tidak akan memanggil REST API Anda secara langsung. Mereka akan lewat server MCP yang membungkusnya. Spesifikasi MCP yang dirilis 28 Juli menghapus handshake sesi dan header Mcp-Session-Id. Setiap request kini membawa versi protokol dan detail kliennya sendiri, dan nama metode serta tool dikirim dalam header HTTP, sehingga gateway bisa merutekan dan membatasi request tanpa mem-parse body.

Hasilnya, server MCP kini berperilaku hampir sama dengan layanan HTTP tanpa state lainnya. Ia bisa ditaruh di belakang load balancer biasa, dan saran di atas berlaku untuknya apa adanya. Saat panggilan tool gagal, agen butuh alasan dan waktu tunggu dari server MCP Anda, sama seperti dari API Anda.

Pemeriksaan cepat

Ini skrip yang kami jalankan sambil menulis tulisan ini. Ia mengirim empat request yang gagal dan memeriksa dua hal di masing-masing: adakah alasan yang bisa dibaca program, dan adakah Retry-After?

check-errors.mjs
// For each failure: is there a reason a program can read, and a time to wait?
const BASE = "https://api.testingapis.com";

const cases = [
  ["missing product", "/api/Products/99999"],
  ["rate limited", "/api/status/429"],
  ["server down", "/api/Products/1?error=503"],
  ["bad request", "/api/status/400"],
];

for (const [name, path] of cases) {
  const res = await fetch(BASE + path);
  const body = await res.json().catch(() => ({}));
  const reason = body.message ?? body.detail ?? body.title;
  const wait = res.headers.get("retry-after");
  console.log(
    name.padEnd(16),
    res.status,
    reason ? "reason: yes" : "reason: NO ",
    wait ? `retry-after: ${wait}s` : "retry-after: -",
  );
}
Output (Node 24, 9 Oktober 2026)
missing product  404 reason: yes retry-after: -
rate limited     429 reason: yes retry-after: 5s
server down      503 reason: yes retry-after: -
bad request      400 reason: yes retry-after: -

Setiap response punya alasan, dan itu bagus. Tetapi lihat baris ketiga. /api/status/503 mengirim Retry-After: 5, sedangkan ?error=503 pada endpoint sungguhan tidak mengirim apa-apa. Klien yang diuji terhadapnya tidak akan pernah tahu kapan harus mencoba lagi. Yang itu sudah ada di daftar kami.

Arahkan skrip yang sama ke jalur gagal API Anda sendiri. Jika Anda tidak bisa membuat API Anda gagal kapan saja, panduan response error menunjukkan cara mendapatkan 500, 429, timeout, atau body terpotong dari API kami.

Tidak ada yang baru dari saran ini. Pesan error yang jelas dan Retry-After sudah menjadi ide bagus jauh sebelum ada yang membuat agen. Yang berubah adalah orang yang bingung pada akhirnya akan mengirim email kepada Anda, sedangkan agen hanya mencoba lagi.