Integrasi Large Language Model (LLM) dengan fungsi eksternal (tool-calling) memperluas kapabilitas sistem, tetapi sekaligus membuka celah keamanan kritis. Saat model menerima instruksi berbahaya melalui indirect prompt injection, agen dapat dieksploitasi untuk memanggil tool sensitif di luar batasan bisnis yang diinginkan. Menyerahkan validasi keamanan sepenuhnya pada sistem instruksi LLM (system prompt) adalah kesalahan fundamental. Lapisan eksekusi tool harus diperlakukan sebagai batas kepercayaan (trust boundary) yang tidak aman.

Vektor Serangan pada Tool-Calling Agent

Ancaman utama pada arsitektur agen otonom mencakup:

  • Indirect Prompt Injection: Data eksternal yang dibaca agen (email, issue tracker, halaman web) mengandung instruksi tersembunyi yang mengesampingkan konfigurasi awal sistem.
  • Parameter Manipulation: Model menghasilkan argumen destruktif yang lolos dari inferensi semantik biasa (misalnya: modifikasi ID target atau penambahan flag sistem yang tidak sah).
  • Session Hijacking / Privilege Creep: Penggunaan credential jangka panjang (long-lived API keys) yang dibagikan secara global ke seluruh siklus hidup agen, memungkinkan eskalasi hak akses saat satu sesi terkompromi.

Arsitektur Hardening Multi-Layer

Untuk mengamankan eksekusi fungsi oleh AI agent, gunakan pipeline pertahanan berlapis sebelum request diteruskan ke infrastruktur internal:

  1. Schema Validation: Verifikasi tipe data, format, dan allowlist parameter pada runtime menggunakan runtime schema parser (seperti Zod).
  2. Policy Enforcement & Token Budgeting: Cek batas alokasi token dan frekuensi eksekusi untuk mencegah looping yang disengaja (denial-of-wallet).
  3. Human-in-the-Loop (HITL) Gate: Tahan eksekusi jika tool tergolong destruktif sampai pengguna manusia memberikan token otorisasi eksplisit.
  4. Ephemeral Secret Generation: Terbitkan credential jangka pendek ber-scope minimal hanya saat fungsi divalidasi dan siap dipanggil.

Implementasi Middleware Inspeksi Tool-Call (TypeScript)

Contoh berikut mengimplementasikan middleware eksekusi tool di Node.js menggunakan TypeScript dan Zod. Pola ini memvalidasi muatan input, menahan aksi destruktif tanpa konfirmasi HITL, dan menginjeksi credential ephemeral bertenggat waktu singkat.

import { z } from "zod";
import crypto from "crypto";

// 1. Skema runtime ketat untuk tool destruktif
export const DeleteDatabaseRecordSchema = z.object({
  table: z.enum(["logs", "temporary_exports"]), // Batasi tabel yang diizinkan
  recordId: z.string().uuid(),
  reason: z.string().min(10).max(255),
});

export type DeleteDatabaseRecordInput = z.infer<typeof DeleteDatabaseRecordSchema>;

interface ToolExecutionContext {
  agentId: string;
  sessionToken: string;
  isHumanApproved?: boolean;
  approvalToken?: string;
  tokenBudgetRemaining: number;
}

interface EphemeralCredential {
  token: string;
  expiresAt: number;
}

// 2. Generator secret ephemeral (TTL 60 detik, scope terbatas)
function generateEphemeralDbSecret(table: string): EphemeralCredential {
  const payload = `${table}:${Date.now() + 60_000}`;
  const token = crypto.createHmac("sha256", process.env.INTERNAL_SIGNING_KEY || "dev-secret")
                      .update(payload)
                      .digest("hex");
  return {
    token: `ephem_${token}`,
    expiresAt: Date.now() + 60_000,
  };
}

// 3. Middleware inspeksi eksekusi tool
export async function executeToolSafely(
  toolName: string,
  rawArgs: unknown,
  context: ToolExecutionContext
): Promise<{ success: boolean; result?: unknown; error?: string }> {
  // A. Guard: Rate limiting / Token budget check
  if (context.tokenBudgetRemaining <= 0) {
    return { success: false, error: "Rate limit / Token budget exhausted for this session." };
  }

  if (toolName === "deleteDatabaseRecord") {
    // B. Guard: Validasi skema runtime
    const parseResult = DeleteDatabaseRecordSchema.safeParse(rawArgs);
    if (!parseResult.success) {
      return { 
        success: false, 
        error: `Parameter payload invalid: ${JSON.stringify(parseResult.error.flatten().fieldErrors)}` 
      };
    }

    const validPayload = parseResult.data;

    // C. Guard: Strict Human-in-the-Loop (HITL) check untuk aksi destruktif
    if (!context.isHumanApproved || !context.approvalToken) {
      return {
        success: false,
        error: "Aksi destruktif memerlukan konfirmasi eksplisit dari pengguna. Menunggu token approval.",
      };
    }

    // D. Isolasi Credential: Buat secret sementara khusus scope tabel ini
    const ephemeralAuth = generateEphemeralDbSecret(validPayload.table);

    // E. Eksekusi nyata menggunakan secret ephemeral
    return await runDeleteOperation(validPayload, ephemeralAuth.token);
  }

  return { success: false, error: `Tool ${toolName} tidak dikenal atau tidak didukung.` };
}

async function runDeleteOperation(
  payload: DeleteDatabaseRecordInput,
  ephemeralToken: string
): Promise<{ success: boolean; result: unknown }> {
  // Database client menerima ephemeralToken untuk autentikasi sementara
  return {
    success: true,
    result: { deleted: payload.recordId, table: payload.table, authScope: ephemeralToken.slice(0, 10) },
  };
}

Isolasi Sesi dengan Secret Ephemeral

Agen AI seharusnya tidak pernah memegang koneksi database permanen dengan izin DROP atau DELETE. Terapkan pola credential vending machine:

  • Short-lived STS Tokens: Gunakan AWS STS (AssumeRole) atau HashiCorp Vault untuk menerbitkan token dengan masa kedaluwarsa maksimal 1 hingga 5 menit.
  • Scoped Permissions: Jika agen berinteraksi dengan API pihak ketiga (misalnya GitHub atau Jira), minta token OAuth yang dibatasi hanya untuk repositori atau project spesifik dari sesi pengguna saat itu, bukan Personal Access Token (PAT) tingkat organisasi.
  • Revocation Registry: Catat token yang dikeluarkan dalam Redis cache dengan TTL otomatis agar pembatalan dapat dilakukan seketika jika anomali terdeteksi.

Pencegahan Denial-of-Wallet Menggunakan Token Budgeting

Adversarial looping dapat memicu recursive function calling tanpa henti. Terapkan batas token hard limit per interaksi:

  1. Tetapkan budget token komputasi per trace (misal: maksimum 4.000 token output atau 5 tool calls per sesi instruksi).
  2. Gunakan sliding-window rate limiter pada level middleware per user ID untuk mencegah eksploitasi konkurensi.
  3. Jika model mencoba memanggil tool berulang kali dengan parameter serupa, lakukan short-circuit dan lempar Execution Loop Aborted ke agent supervisor.

Trade-offs dan Pertimbangan Operasional

Menerapkan validasi deterministik pada output probabilistik LLM memiliki beberapa kompromi:

  • Latensi Eksekusi: Verifikasi HITL memerlukan mekanisme polling atau webhook asynchronous, mengubah alur kerja agen dari synchronous menjadi state-machine berbasis status (pending approval).
  • Rigiditas Skema: Skema validasi yang terlalu kaku dapat menurunkan fleksibilitas agen dalam mengekstrak maksud pengguna. Solusinya adalah menjaga skema tetap fleksibel pada string pencarian, tetapi sangat restriktif pada nama entitas, flag sistem, dan identifier.