Membangun agen AI yang mampu mengeksekusi instruksi sederhana di lingkungan pengembangan lokal adalah pekerjaan yang menyenangkan. Namun, membawa agen tersebut ke lingkungan produksi perusahaan sering kali berubah menjadi mimpi buruk pemeliharaan. Masalah paling umum yang dihadapi tim rekayasa perangkat lunak adalah fenomena regresi bisu (silent regression): Anda mengubah satu kalimat pada prompt sistem untuk memperbaiki format tanggal, namun perubahan kecil tersebut tanpa disadari merusak urutan pemanggilan perkakas (tool calling trajectory) pada alur pembayaran atau ekstraksi dokumen.
Satu-satunya cara mencegah regresi bisu pada sistem agen AI otonom adalah dengan memperlakukan evaluasi sebagai bagian dari pipeline continuous integration (CI/CD), sama seperti pengujian unit (unit test) pada kode konvensional. Rangkaian uji otomatis ini dikenal sebagai eval harness. Artikel ini menyajikan panduan langkah demi langkah untuk merancang, mengimplementasikan, dan menjalankan eval harness deterministik bagi agen AI multi-langkah, lengkap dengan metrik evaluasi lintasan, penanganan bias semantic judge, dan kode yang dapat diuji.
Mengapa pengujian unit biasa tidak cukup untuk agen AI?
Pengujian unit biasa tidak cukup untuk agen AI karena model bahasa besar bersifat non-deterministik dan menghasilkan keluaran teks probabilistik yang tidak dapat diverifikasi secara andal hanya dengan operator perbandingan nilai kaku seperti assert actual == expected. Pada perangkat lunak konvensional, fungsi pembuat laporan keuangan akan selalu mengembalikan string atau angka yang identik jika diberikan input yang sama.
Pada sistem agen otonom, ada tiga dimensi ketidakpastian yang menggagalkan uji unit biasa:
Pertama, variasi sintaksis alami (syntactic variance). Sebuah agen perangkum tiket pelanggan dapat menjawab dengan sepuluh kalimat berbeda yang semuanya benar secara faktual, namun tidak ada satu pun yang cocok dengan teks ekspektasi yang Anda tulis di kode pengujian. Memaksa pengujian unit kaku akan menghasilkan banyak alarm palsu (false positives).
Kedua, kompleksitas lintasan multi-langkah (multi-step trajectories). Agen tidak hanya menghasilkan satu teks keluaran; agen berpikir, memanggil perkakas pertama, membaca keluaran perkakas, memutuskan apakah membutuhkan perkakas kedua, dan baru menyusun jawaban akhir. Sebuah kesalahan kecil pada langkah kedua dapat membuat agen berputar dalam loop tanpa akhir (infinite tool loop) atau memanggil perkakas dengan urutan yang salah.
Ketiga, ketergantungan model terhadap pembaruan penyedia (upstream drift). Ketika penyedia API memperbarui bobot model di balik layar (seperti peralihan versi minor gpt-4 atau claude-3), distribusi probabilitas keluaran berubah. Prompt yang kemarin bekerja dengan tingkat keberhasilan 98 persen tiba-tiba turun menjadi 80 persen tanpa ada perubahan satu baris pun pada repositori Anda.
Oleh karena itu, eval harness modern menggabungkan tiga tingkatan pengujian: pengujian deterministik pada muatan parameter perkakas, pengujian lintasan urutan aksi (trajectory match), dan pengujian semantik menggunakan model penilai (LLM-as-a-judge).
Anatomi sebuah eval harness: dari dataset uji hingga skor regresi
Sebuah eval harness yang lengkap dibangun di atas empat komponen modular yang saling terhubung:
-
Kumpulan Data Uji Baku (Golden Evaluation Dataset): Kumpulan berkas uji berformat JSON atau YAML yang memuat skenario masukan pengguna, prasyarat konteks, perkakas yang wajib dipanggil, dan kriteria keberhasilan yang divalidasi oleh pakar domain manusia.
-
Runner Eksekusi Terisolasi (Test Execution Runner): Modul yang menjalankan agen terhadap dataset uji dalam lingkungan sandbox terisolasi. Modul ini mencegat (mock) panggilan eksternal berbayar atau berbahaya, memastikan eksekusi uji dapat diulang secara konsisten (reproducible).
-
Penyusun Metrik dan Penilai (Scoring Engine & Evaluators): Kumpulan modul penilai yang memeriksa keluaran agen. Penilai ini mencakup validator skema deterministik (apakah JSON valid?), pemeriksa lintasan perkakas (apakah perkakas A dipanggil sebelum perkakas B?), dan penilai semantik berbasis rubrik (apakah jawaban sopan dan tidak mengandung halusinasi?).
-
Dasbor Jejak dan Pelacak Regresi (Observability & Regression Tracker): Platform pencatatan jejak eksekusi seperti yang disediakan oleh repositori resmi Langfuse di GitHub atau proyek Arize Phoenix. Dasbor ini membandingkan metrik lintasan antara commit git saat ini dengan commit stabil sebelumnya di cabang utama.
Berikut adalah diagram alur pipa evaluasi berkelanjutan yang menghubungkan keempat pilar tersebut:
flowchart LR
Dataset["1. Golden Dataset<br/>Kasus Uji JSON/YAML"] --> Runner["2. Test Runner<br/>Sandbox Terisolasi"]
Runner --> Agent["Agen yang Diuji<br/>Model + Perkakas"]
Agent --> Runner
Runner --> Scoring["3. Mesin Penilai<br/>Skema, TCA/TOA, LLM Judge"]
Scoring --> Observability["4. Dasbor Jejak<br/>Langfuse / Arize"]
Observability --> Gate["Gerbang CI/CD<br/>Pencegah Regresi"]
Gate -->|Lolos Ambang Batas| Pass["Lolos: Siap Rilis Produksi"]
Gate -->|Di Bawah Batas| Fail["Gagal: Blokir Penggabungan Git"]
Menentukan metrik evaluasi lintasan: melacak keputusan agen
Ketika mengevaluasi agen yang memiliki akses perkakas, Anda tidak bisa hanya menilai jawaban akhirnya. Anda wajib menilai jalannya penalaran dan keakuratan setiap tindakan perantara.
Kami mengelompokkan metrik lintasan ke dalam empat indikator kinerja utama:
-
Tool Call Accuracy (TCA): Mengukur rasio antara perkakas yang dipanggil dengan benar terhadap perkakas yang seharusnya dipanggil. Jika skenario membutuhkan pembacaan resi via perkakas
query_shipping_db, namun agen malah memanggil perkakas pencarian web umum, TCA bernilai nol. -
Parameter Precision Score (PPS): Mengukur apakah parameter yang dikirim agen ke dalam fungsi perkakas valid secara semantik dan sintaktis. Contohnya, apakah tanggal dikirim dalam format ISO YYYY-MM-DD? Apakah ID transaksi bersih dari karakter injeksi?
-
Trajectory Order Agreement (TOA): Mengukur apakah urutan pemanggilan perkakas mematuhi ketergantungan logika bisnis. Pada alur logistik, agen wajib memanggil
verify_customer_identitysebelum memanggilcancel_delivery_order. Jika urutan terbalik, TOA gagal meskipun kedua perkakas berhasil dipanggil. -
Loop Exhaustion Ratio (LER): Mengukur seberapa sering agen terjebak dalam putaran perbaikan kesalahan (error loop). Jika agen mencoba memanggil perkakas yang gagal lebih dari tiga kali berturut-turut tanpa meminta klarifikasi kepada pengguna, alur dianggap gagal karena membuang anggaran token.
Pendekatan metrik berbasis lintasan ini juga diadopsi secara luas dalam repositori resmi OpenAI Evals di GitHub, di mana pengujian model difokuskan pada pemenuhan kontrak logika bertahap.
Implementasi langkah demi langkah: membangun harness dengan Python dan Pytest
Untuk membangun harness pengujian yang dapat langsung dijalankan oleh tim pengembang Anda, kita dapat menggunakan pustaka DeepEval dari Confident AI yang terintegrasi secara mulus dengan ekosistem Pytest standar.
Berikut adalah panduan implementasi terstruktur untuk menguji agen logistik sederhana.
Langkah 1: Mendefinisikan berkas dataset uji baku
Buat berkas skenario uji dalam format JSON atau YAML. Berkas ini mendefinisikan apa yang diminta pengguna dan perkakas apa yang wajib dieksekusi:
[
{
"test_id": "TC-LOG-01",
"description": "Pelanggan menanyakan lokasi paket dengan nomor resi valid",
"user_input": "Halo, tolong cek paket saya dengan nomor resi JKT901234 sekarang.",
"expected_tools": ["check_shipment_status"],
"required_params": {
"tracking_id": "JKT901234"
},
"forbidden_tools": ["cancel_shipment_order", "refund_balance"],
"expected_status": "IN_TRANSIT"
},
{
"test_id": "TC-LOG-02",
"description": "Permintaan pembatalan pesanan tanpa nomor resi",
"user_input": "Batalkan pesanan saya segera!",
"expected_tools": [],
"expected_clarification": true
}
]
Langkah 2: Menulis modul runner pengujian agen
Tulis berkas pengujian Python bernama test_agent_eval.py. Kode berikut adalah contoh ilustrasi teknis yang mendemonstrasikan evaluasi lintasan deterministik tanpa membakar token berlebih:
"""
Ilustrasi Implementasi Eval Harness untuk Agen AI
Menguji lintasan pemanggilan perkakas dan validasi parameter secara deterministik.
"""
import json
import pytest
from dataclasses import dataclass
from typing import Any
@dataclass
class ToolExecutionStep:
tool_name: str
arguments: dict[str, Any]
@dataclass
class AgentRunResult:
final_output: str
trajectory: list[ToolExecutionStep]
total_tokens_used: int
class MockLogisticsAgent:
"""Simulasi agen logistik untuk demonstrasi pengujian (ilustrasi)."""
async def run(self, message: str) -> AgentRunResult:
# Logika tiruan: agen mendeteksi nomor resi dan memanggil perkakas
if "JKT901234" in message:
return AgentRunResult(
final_output="Paket JKT901234 saat ini berada di Pusat Distribusi Jakarta.",
trajectory=[
ToolExecutionStep(
tool_name="check_shipment_status",
arguments={"tracking_id": "JKT901234"}
)
],
total_tokens_used=420
)
return AgentRunResult(
final_output="Mohon sebutkan nomor resi paket Anda agar dapat kami periksa.",
trajectory=[],
total_tokens_used=180
)
# Memuat skenario uji baku
def load_golden_dataset():
raw_data = """
[
{
"test_id": "TC-LOG-01",
"user_input": "Halo, tolong cek paket saya dengan nomor resi JKT901234.",
"expected_tools": ["check_shipment_status"],
"required_params": {"tracking_id": "JKT901234"}
}
]
"""
return json.loads(raw_data)
@pytest.mark.asyncio
@pytest.mark.parametrize("scenario", load_golden_dataset())
async def test_agent_trajectory_conformance(scenario):
"""
Menguji bahwa lintasan perkakas agen mematuhi skenario baku:
1. Memeriksa alat yang dipanggil sesuai ekspektasi.
2. Memeriksa parameter alat bebas dari halusinasi nilai.
"""
agent = MockLogisticsAgent()
result = await agent.run(scenario["user_input"])
executed_tools = [step.tool_name for step in result.trajectory]
# Evaluasi 1: Tool Call Accuracy
for expected_tool in scenario["expected_tools"]:
assert expected_tool in executed_tools, (
f"Kegagalan pada {scenario['test_id']}: Perkakas '{expected_tool}' tidak dipanggil. "
f"Perkakas yang dipanggil: {executed_tools}"
)
# Evaluasi 2: Parameter Precision Score
for step in result.trajectory:
if step.tool_name in scenario.get("required_params", {}):
expected_arg = scenario["required_params"][step.tool_name]
assert step.arguments.get(step.tool_name) == expected_arg, (
f"Kegagalan parameter pada {scenario['test_id']}: "
f"Ekspektasi {expected_arg}, didapat {step.arguments.get(step.tool_name)}"
)
# Evaluasi 3: Batasan Anggaran Token (Efficiency Ceiling)
assert result.total_tokens_used < 1500, (
f"Alur {scenario['test_id']} membuang token berlebih: {result.total_tokens_used}"
)
Dengan struktur uji di atas, Anda dapat menjalankan perintah standar pytest test_agent_eval.py di terminal Anda. Jika seorang insinyur mengubah deskripsi fungsi atau prompt sistem yang menyebabkan model lupa memasukkan parameter resi, suite pengujian akan langsung berwarna merah dalam hitungan detik.
Mengatasi bias dan volatilitas LLM-as-a-Judge
Menggunakan model bahasa besar untuk menilai model bahasa lain (LLM-as-a-judge) sangat berguna untuk mengukur kualitas nada bicara, kejelasan penjelasan, dan pencegahan ujaran berbahaya. Namun, mengandalkan LLM sebagai penilai tunggal tanpa pengaman dapat menyesatkan karena model memiliki bias kognitif yang terdokumentasi dengan baik:
-
Bias Preferensi Sendiri (Self-Enhancement Bias): Model yang dikembangkan oleh satu penyedia cenderung memberikan skor lebih tinggi kepada teks yang dihasilkan oleh model dari keluarga yang sama. GPT-4 cenderung menilai keluaran GPT-4 lebih elegan dibandingkan keluaran Claude atau Llama, dan sebaliknya.
-
Bias Urutan dan Posisi (Position Bias): Saat membandingkan dua jawaban secara berdampingan (A vs B), model memiliki kecenderungan bawaan untuk memilih jawaban yang ditaruh pada opsi pertama (primacy effect).
-
Bias Panjang Kalimat (Verbosity Bias): Model penilai secara konsisten memberikan nilai lebih tinggi kepada jawaban yang panjang dan bertele-tele, meskipun jawaban yang pendek dan ringkas jauh lebih berguna bagi pengguna nyata.
Untuk mengatasi kelemahan ini, ada tiga aturan baku yang wajib diterapkan dalam eval harness Anda:
Pertama, jadikan pengujian deterministik sebagai gerbang utama (first gate). Validasi skema JSON, status HTTP, dan kehadiran parameter wajib diuji menggunakan kode Python murni. LLM judge hanya dipanggil jika pengujian deterministik telah lolos seratus persen.
Kedua, gunakan rubrik penilaian biner berkriteria sempit (binary rubric). Jangan meminta model memberi nilai subjektif dari 1 sampai 10. Mintalah penilaian boolean (True/False) dengan kriteria eksplisit: “Jawab TRUE jika teks menyebutkan waktu kedatangan paket; jawab FALSE jika teks tidak menyebutkan waktu sama sekali”.
Ketiga, lakukan penukaran posisi (position swap calibration). Saat melakukan evaluasi komparatif, jalankan evaluasi dua kali dengan posisi kandidat ditukar. Jika penilai memilih A pada putaran pertama namun memilih B ketika posisinya dibalik, hasil evaluasi dinyatakan tidak valid dan harus ditinjau ulang oleh operator manusia.
Pola evaluasi berlapis ini merupakan salah satu pilar layanan yang kami sediakan di layanan konsultasi AI dan proyek harness evaluasi LLM.
Mengintegrasikan eval harness ke pipeline CI/CD GitHub Actions
Pengujian evaluasi agen tidak boleh hanya menjadi skrip manual di komputer laptop seorang insinyur. Pengujian ini wajib berjalan secara otomatis pada setiap tarikan kode (pull request) sebelum kode digabungkan ke cabang utama (main branch).
Berikut adalah contoh alur kerja GitHub Actions (.github/workflows/agent-eval.yml) yang mengeksekusi suite uji evaluasi secara berkala:
name: Agent Continuous Evaluation Gate
on:
pull_request:
branches: [main]
paths:
- "src/agents/**"
- "prompts/**"
- "tests/evals/**"
jobs:
run-eval-harness:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
uses: actions/checkout@v4
- name: Setup Python Environment
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
- name: Install Testing Dependencies
run: |
python -m pip install --upgrade pip
pip install pytest pytest-asyncio deepeval langfuse
- name: Execute Deterministic Agent Evals
env:
EVAL_ENVIRONMENT: ci-sandbox
LANGFUSE_PUBLIC_KEY: ${{ secrets.LANGFUSE_PUBLIC_KEY }}
LANGFUSE_SECRET_KEY: ${{ secrets.LANGFUSE_SECRET_KEY }}
run: |
pytest tests/evals/test_agent_eval.py -v --junitxml=reports/eval-results.xml
- name: Enforce Pass Rate Ceiling
run: |
echo "Memverifikasi tingkat kelulusan evaluasi agen minimal 95%..."
Dengan memasukkan alur kerja ini ke dalam CI/CD, tim Anda menciptakan gerbang kualitas yang tidak dapat dilewati secara diam-diam. Jika sebuah perbaikan prompt menyebabkan tingkat keberhasilan pemanggilan perkakas turun dari 98 persen menjadi 90 persen, integrasi akan gagal dan mencegah kode cacat tersebut mencemari lingkungan produksi.
Memulai dari dataset kecil yang jujur
Membangun eval harness yang andal tidak menuntut Anda menulis seribu skenario uji dalam semalam. Kesalahan terbesar yang sering dilakukan tim adalah menunggu dataset sempurna sebelum mulai menulis pengujian pertama mereka.
Mulailah dari sepuluh kasus kegagalan riil (production incident post-mortems). Setiap kali agen Anda mengalami halusinasi, salah memanggil perkakas, atau membuang token pengguna di lingkungan produksi, salin interaksi tersebut ke dalam dataset uji baku Anda. Tulis pengujian deterministik yang memastikan kegagalan tersebut tidak akan pernah terulang kembali.
Dalam beberapa bulan, sepuluh kasus uji tersebut akan berkembang menjadi jaring pengaman tangguh yang memungkinkan tim Anda bereksperimen dengan model-model baru, mengoptimalkan biaya prompt, dan memperbarui alur bisnis dengan rasa percaya diri penuh.
Jika organisasi Anda ingin merancang eval harness otomatis, mengaudit reliabilitas sistem agen otonom, atau membutuhkan arsitektur continuous evaluation yang terukur, diskusikan kebutuhan rekayasa Anda bersama para insinyur spesialis kami melalui halaman kontak.


