Komunikasi antar-agen otonom (Agent-to-Agent atau A2A protocol) umumnya mengandalkan pertukaran pesan terstruktur seperti JSON-RPC melalui HTTP POST atau Server-Sent Events (SSE) untuk streaming. Ketidakcocokan skema payload dan ketidakpastian respons model LLM sering memicu regresi parsing serta flaky tests pada pipeline CI/CD. Artikel ini mengulas strategi verifikasi kontrak protokol A2A melalui pengujian deterministik dan mocking server lokal.
Tantangan Kontrak dalam Protokol A2A
Tidak seperti REST API konvensional dengan skema statis, interaksi A2A sering kali menghadapi dua masalah utama:
- Drift Skema dan Regresi Parsing: Perubahan kecil pada struktur tool call atau pesan JSON-RPC dapat merusak serialisasi agen penerima.
- Ketidakpastian Respons Jaringan: Latensi eksternal, network jitter, dan respons non-deterministik memicu timeout acak jika diuji langsung ke runtime model.
Solusi yang tepat adalah mengisolasi dependensi eksternal menggunakan mock server lokal berbasis kontrak skema (JSON Schema) dan menerapkan assertions yang toleran terhadap jitter tanpa menoleransi pelanggaran protokol.
Validasi Skema JSON-RPC pada Interaksi A2A
Pencegahan regresi parsing payload dimulai dengan validasi ketat terhadap envelope protokol A2A. Format standar umumnya berbasis spesifikasi JSON-RPC 2.0.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["jsonrpc", "method", "params", "id"],
"properties": {
"jsonrpc": { "type": "string", "const": "2.0" },
"method": { "type": "string", "pattern": "^[a-z_]+(\\.[a-z_]+)*$" },
"params": {
"type": "object",
"required": ["task_id", "context"],
"properties": {
"task_id": { "type": "string", "format": "uuid" },
"context": { "type": "object" }
}
},
"id": { "type": ["string", "number"] }
}
}Validasi dilakukan di tingkat transport middleware sebelum payload dieksekusi oleh reasoning engine agen target. Jika envelope gagal divalidasi, agen wajib mengembalikan error parsing standar sebelum membuang komputasi eksekusi model.
Skenario Integration Test Menggunakan Mock Server Lokal
Alih-alih menghubungi runtime LLM secara langsung, pengujian integrasi A2A harus diarahkan ke mock server lokal deterministik. Node.js native node:http atau WireMock dapat digunakan untuk memverifikasi handshake protokol dan perilaku agen pengirim.
Berikut adalah implementasi integration test agen menggunakan Node.js test runner bawaan dengan verifikasi payload dan penanganan retry idempotent:
import test from 'node:test';
import assert from 'node:assert/strict';
import http from 'node:http';
function createMockAgentServer(port) {
let requestCount = 0;
const server = http.createServer((req, res) => {
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', () => {
requestCount++;
const payload = JSON.parse(body);
// Simulasi 1x network jitter/failure, sukses pada percobaan retry
if (requestCount === 1) {
res.writeHead(503, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: { code: -32000, message: 'Agent busy' } }));
return;
}
// Verifikasi kontrak JSON-RPC
if (payload.jsonrpc !== '2.0' || !payload.id || !payload.params?.task_id) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ jsonrpc: '2.0', id: payload.id || null, error: { code: -32600, message: 'Invalid Request' } }));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
jsonrpc: '2.0',
id: payload.id,
result: { status: 'acknowledged', correlation_id: payload.params.task_id }
}));
});
});
return {
start: () => new Promise(resolve => server.listen(port, resolve)),
stop: () => new Promise(resolve => server.close(resolve)),
getRequestCount: () => requestCount
};
}
// Client caller dengan timeout dan retry idempotent
async function dispatchA2ATask(url, payload, maxRetries = 2, timeoutMs = 1000) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Idempotency-Key': payload.params.task_id },
body: JSON.stringify(payload),
signal: controller.signal
});
clearTimeout(timer);
if (response.ok) return await response.json();
if (attempt === maxRetries) throw new Error(`HTTP Error: ${response.status}`);
} catch (err) {
clearTimeout(timer);
if (attempt === maxRetries) throw err;
}
}
}
test('A2A Client: Retry idempotent dan validasi payload skema', async () => {
const port = 8085;
const mockServer = createMockAgentServer(port);
await mockServer.start();
try {
const payload = {
jsonrpc: '2.0',
method: 'delegate_task',
params: { task_id: '123e4567-e89b-12d3-a456-426614174000', context: { priority: 'high' } },
id: 'req-001'
};
const response = await dispatchA2ATask(`http://localhost:${port}`, payload);
assert.equal(mockServer.getRequestCount(), 2, 'Client harus melakukan 1x retry setelah gagal');
assert.equal(response.result.status, 'acknowledged');
assert.equal(response.result.correlation_id, payload.params.task_id);
} finally {
await mockServer.stop();
}
});Menangani Timeout dan Retry Idempotent
Agen pengirim harus memberlakukan batas waktu tegas (hard timeout) untuk mencegah hanging connection saat agen downstream mengalami degradasi. Parameter verifikasi berikut wajib dipenuhi:
- Idempotency-Key: Setiap pesan A2A wajib menyertakan identitas unik (misalnya kombinasi task ID dan sequence counter). Ketika agen penerima memproses ulang permintaan akibat retry, status state sebelumnya harus dikembalikan tanpa memicu eksekusi ganda.
- Bounded Backoff: Hindari thundering herd saat agen downstream pulih dengan menggunakan retry interval eksponensial singkat (misal: 100ms, 200ms) di lingkungan pengujian.
- Validasi Envelope Streaming (SSE): Untuk transport berbasis SSE, validasi struktur
data:harus dilakukan per baris pesan menggunakan parser streaming untuk memastikan delimiter\n\ntidak terpotong (chunk fragmented).
Catatan: Hindari testing interaksi A2A langsung terhadap LLM API aktif di pipeline integrasi. Lakukan validasi reasoning di level unit terpisah, dan kunci komunikasi protokol A2A pada boundary transport menggunakan mock server deterministik.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!