Jangan Tulis Loop Alat Sendiri! Analisis Mendalam Claude Code Agent SDK dan Panduan Penerapan Produksi
Jika Anda masih menulis sendiri loop while dengan SDK native Anthropic untuk mengurai tool_use, menangani callback alat yang rumit, dan mengelola status konteks, artikel ini untuk Anda.
Anthropic baru-baru ini merilis claude-agent-sdk secara senyap (sebelumnya Claude Code SDK). Ini bukan sekadar pembungkus API—melainkan SDK inti yang secara programatis mengekspos loop agentik yang sama, rantai alat bawaan, hook intersepsi izin, dan mekanisme pemulihan konteks sesi yang ada di balik CLI Claude Code.
Artikel ini membahas prinsip arsitektur, mekanisme inti, intersepsi keamanan melalui hook untuk penggunaan produksi, serta praktik lengkap dengan GitHub Actions CI/CD dan kolaborasi multiagen. Mari pelajari SDK ini dari awal sampai mahir.
1. Mengapa semua orang membicarakan claude-agent-sdk
Jika pernah memakai SDK native Anthropic, Anda tahu bahwa untuk membangun agen, Anda perlu:
- menulis loop
whiledan memanggil/v1/messagesberulang kali - mengurai blok
tool_usedantool_resultdari respons API - memelihara riwayat pesan dan jendela konteks sendiri
- menangani berbagai kasus batas dan kesalahan
Pertama kali menjalankannya, hal itu terasa mengesankan. Kali kedua, Anda menyadari sesuatu: semua orang—Anthropic, OpenAI, Gemini—melakukan hal yang sama. Perbedaan sesungguhnya bukan pada inti LLM, melainkan rekayasa di balik agen.
claude-agent-sdk mengekspos langsung loop agentik Claude Code. Artinya, Anda tidak perlu menciptakan kembali seluruh rekayasa agen; hanya dengan beberapa baris kode Anda dapat memperoleh agen coding tingkat produksi.
Hal ini memunculkan dua pertanyaan:
Apa hubungan claude-agent-sdk dengan Claude Code?
Claude Code adalah alat coding agentik berbasis CLI, asisten coding terminal yang sering dibicarakan. claude-agent-sdk dapat dipandang sebagai cara mengekspos inti Claude Code sebagai fungsi dalam kode Anda. SDK ini dapat digunakan sebagai alat baris perintah di terminal, disematkan dalam pipeline CI/CD, atau diintegrasikan ke aplikasi.
Apa hubungan claude-agent-sdk dengan Anthropic SDK?
Anthropic SDK adalah SDK API tingkat rendah untuk memanggil model Claude secara langsung. SDK tersebut menyediakan Messages API, streaming, dan alat. claude-agent-sdk dibangun di atasnya, tetapi dengan tingkat abstraksi jauh lebih tinggi.
Sederhananya, Anthropic SDK seperti memberi Anda mesin lalu meminta Anda merakit mobil sendiri. claude-agent-sdk seperti menyediakan sasis lengkap, rangkaian penggerak, dan modul mengemudi otonom.
2. Prinsip arsitektur inti: semuanya adalah sesi
Konsep desain paling penting pada claude-agent-sdk adalah: semuanya adalah sesi.
Apa itu sesi? Sesi adalah konteks eksekusi mandiri yang menyimpan seluruh status eksekusi agen, termasuk:
- riwayat percakapan (daftar pesan)
- pengaturan izin dan status persetujuan
- status eksekusi alat
- perubahan sistem berkas (secara internal, sesi dapat melacak status berkas)
- konteks lengkap yang diperlukan untuk melanjutkan eksekusi yang terputus
Dengan SDK tingkat rendah, untuk melanjutkan setelah interupsi, Anda harus membuat serialisasi seluruh riwayat pesan sendiri. Namun di claude-agent-sdk, objek Session seperti titik simpan dalam gim: Anda dapat melanjutkan kapan saja dari titik mana pun.
Membuat sesi
import { query } from "@anthropic-ai/claude-agent-sdk";
const session = await query({
prompt: "Please write a Python script that prints 1 to 100",
options: {
allowedTools: ["Bash", "Read"],
},
});
Satu detail yang perlu diketahui: pada pemanggilan pertama, SDK secara otomatis menyiapkan lingkungan (memasang dependensi, menyinkronkan CLI, dan sebagainya). Bergantung pada kondisi jaringan, proses ini dapat memakan beberapa detik hingga beberapa menit.
Peristiwa streaming
for await (const message of session) {
if (message.type === "stream_event") {
console.log(JSON.stringify(message.event, null, 2));
}
}
Di sini terlihat filosofi desain penting: SDK ini bukan sekadar API permintaan-respons. Ini SDK streaming-first yang memberi visibilitas penuh terhadap tindakan agen. SDK tidak menyembunyikan kerumitan, melainkan menawarkan transparansi penuh.
Siklus hidup sesi
Saat agen menyelesaikan semua pekerjaannya, sesi berakhir. Namun SDK juga memungkinkan Anda melanjutkan sesi secara eksplisit:
const resumed = await query(
"Based on the previous answer, change the script to print 1 to 1000",
{
sessionId: session.sessionId,
options: { allowedTools: ["Bash", "Read", "Write"] },
}
);
Tunggu, bukankah kedua pemanggilan ini tampak mirip? Ya, tetapi ada perbedaan penting: pemanggilan pertama membuat sesi baru, sedangkan yang kedua menggunakan sessionId. Inilah arti “semuanya adalah sesi”: agen dapat melanjutkan tepat dari tempat ia berhenti. SDK mengelola serialisasi dan pemulihan konteks untuk Anda.
3. Mekanisme inti: alat, izin, dan hook
3.1 Alat bawaan: rantai alat agen yang lengkap
Jika memakai Anthropic SDK secara langsung, Anda harus mendefinisikan setiap alat sendiri. Anda harus mengetahui cara menjalankan Bash, menangani masukan/keluaran berkas, dan menerapkan pemeriksaan izin.
claude-agent-sdk sudah dilengkapi rantai alat Claude Code secara lengkap:
| Nama alat | Deskripsi | Tingkat izin |
|---|---|---|
| Bash | Menjalankan perintah shell | DefaultAsk |
| Read | Membaca berkas | DefaultAllowed |
| Edit | Mengubah berkas | DefaultAsk |
| Write | Menulis berkas | DefaultAsk |
| Glob | Menemukan berkas berdasarkan pola | DefaultAllowed |
| Grep | Mencari isi berkas | DefaultAllowed |
| WebFetch | Mengambil URL web | DefaultAsk |
| WebSearch | Mencari di web | DefaultAsk |
| TodoList | Menguraikan tugas | DefaultAllowed |
Inilah alat yang sama persis dengan yang digunakan Claude Code di terminal. SDK menyediakan alat yang sama dalam konteks aplikasi Anda sendiri.
3.2 Sistem izin: dua mode operasi
Saat alat yang memerlukan izin dipanggil, SDK harus menentukan cara menanganinya. Ada dua mode:
Mode 1: Izin otomatis (disarankan untuk CI/CD)
const session = await query({
prompt: "Initialize a git repository and commit all files",
options: {
allowedTools: [
{ toolName: "Bash", isAllowed: () => true },
"Read",
"Write",
],
},
});
Dalam mode ini, semua perintah Bash otomatis diizinkan. Anda juga dapat menetapkan fungsi kustom:
allowedTools: [
{
toolName: "Bash",
isAllowed: async (input) => {
const command = input.command;
return command.startsWith("git ") || command.startsWith("npm ");
},
},
]
Mode ini cocok untuk skenario otomatis seperti pipeline CI/CD, ketika lingkungan diketahui dan aman.
Mode 2: Hooks — intersepsi izin tingkat produksi
Jika perlu kontrol izin dinamis, aturan daftar blokir/daftar izin, atau persetujuan manusia dalam alur, Hooks adalah mekanisme intinya.
const session = await query({
prompt: "Run all tests and fix any failures",
options: {
hooks: {
PreToolUse: [
{
matcher: "Bash",
hook: async (input) => {
const command = input.tool_input.command;
if (command.includes("rm -rf")) {
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason:
"rm -rf is not allowed in our CI environment",
},
};
}
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "allow",
},
};
},
},
],
},
},
});
Sebagian pembaca mungkin bertanya: jika isAllowed sudah dapat menangani ini, mengapa perlu Hooks?
Pertanyaan bagus. Perbedaannya:
isAllowedhanya menangani kasus ketika alat sudah tercantum dalamallowedTools. Ia tidak dapat menambahkan alat yang belum ada ke daftar izin atau mengubah cakupan izin secara dinamis saat program berjalan.- Hooks dijalankan sebelum alat benar-benar dieksekusi dan dapat mengintersepsi pada berbagai tahap siklus hidup (PreToolUse, PostToolUse, dan sebagainya). Hooks juga dapat mengubah status sesi, memblokir eksekusi, atau menerapkan alur yang lebih rumit seperti meminta persetujuan manusia.
Singkatnya, hooks merupakan mekanisme yang lebih kuat, fleksibel, dan berorientasi produksi.
3.3 Jenis peristiwa Hook
PreToolUse: dipicu sebelum alat dieksekusi.PostToolUse: dipicu setelah alat dieksekusi.Notification: dipicu ketika agen mengirim notifikasi.UserPromptSubmit: dipicu ketika pengguna mengirim prompt.Stop: dipicu ketika agen selesai.
Siklus hidup hook secara lengkap jauh lebih terperinci. Daftar lengkap dapat dilihat di dokumentasi resmi. Hal pentingnya adalah memahami prinsip berikut: SDK memberi Anda observabilitas dan kendali penuh atas siklus hidup loop agen.
4. Praktik hook produksi: membangun gerbang keamanan
Sekarang kita akan membangun gerbang keamanan praktis untuk produksi. Gerbang ini mengintersepsi setiap perintah Bash dan menerapkan aturan berikut:
- menolak semua perintah
rm -rf(sangat berbahaya) - menolak semua perintah yang menulis di luar direktori kerja (misalnya
cd /etc && echo "hello" > test.txt) - menolak pembacaan kredensial dari berkas variabel lingkungan (seperti
.envdi/etcatau~/.aws/credentials) - mengizinkan semua operasi lain
Berikut implementasi lengkapnya:
// secure-gate.ts
import { query } from "@anthropic-ai/claude-agent-sdk";
const WORKSPACE = "/home/user/project";
const DENY_PATTERNS = [
/^\s*rm\s+(-[a-z]*\s+)*-\s*[a-z]*[r]/i,
/^\s*sudo\s+/i,
/^\s*curl\s+.*(\||>)/i,
/^\s*(cat|tail|head|less|more)\s+.*\.(env|pem|key|p12)/i,
];
const ALLOW_PATTERNS = [
/^\s*(cd|ls|pwd|git|npm|node|python3?|pip|bun|yarn|pnpm|tsc|eslint|prettier)\b/i,
];
function isSafeCommand(command: string): { allowed: boolean; reason?: string } {
const trimmed = command.trim();
// Block dangerous patterns
for (const pattern of DENY_PATTERNS) {
if (pattern.test(trimmed)) {
return {
allowed: false,
reason: `Command matches dangerous pattern: ${pattern}`,
};
}
}
// If it matches our allow-list of build/test commands, let it through
for (const pattern of ALLOW_PATTERNS) {
if (pattern.test(trimmed)) {
return { allowed: true };
}
}
// Otherwise, allow but with audit log
return { allowed: true, reason: "Allowed with audit" };
}
async function main() {
const session = await query({
prompt: "Run npm test and fix any errors",
options: {
allowedTools: ["Bash", "Read", "Write", "Edit"],
hooks: {
PreToolUse: [
{
matcher: "Bash",
hook: async (input) => {
const command = input.tool_input.command as string;
const result = isSafeCommand(command);
if (!result.allowed) {
console.warn(`[SECURITY] Blocked command: ${command}`);
console.warn(`[SECURITY] Reason: ${result.reason}`);
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: result.reason,
},
};
}
if (result.reason === "Allowed with audit") {
console.log(`[AUDIT] ${command}`);
}
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "allow",
},
};
},
},
],
},
},
});
for await (const message of session) {
// consume stream
}
}
main().catch(console.error);
Dalam contoh ini:
- Kami menggunakan kombinasi daftar blokir dan daftar izin berbasis regex.
- Daftar blokir menolak perintah berbahaya; daftar izin meloloskan perintah build/test umum secara langsung sehingga menghindari permintaan izin yang tidak perlu.
- Operasi lain diizinkan, tetapi dicatat untuk audit.
- Hasil keputusan izin dikembalikan kepada agen agar agen dapat menyesuaikan perilakunya.
Sistem produksi sungguhan dapat melangkah lebih jauh: menggunakan mesin kebijakan eksternal seperti OPA, mengintegrasikan SIEM, atau mengarahkan permintaan keputusan ke layanan persetujuan manusia. Namun prinsipnya sama: kendali penuh atas loop agen.
5. GitHub Actions CI/CD: agen sebagai pengembang otomatis
Sekarang kita lihat skenario produksi nyata: menggunakan claude-agent-sdk dalam GitHub Actions CI/CD untuk membuat Pull Request perubahan kode secara otomatis.
Menggunakan CLI dengan --output-format stream-json
Di CI, cara paling sederhana adalah menggunakan CLI secara langsung. CLI dan SDK adalah dua sisi dari hal yang sama. Dalam workflow GitHub Actions, Anda dapat menjalankan:
name: Agent Code Review & Fix
on:
push:
branches: [main]
jobs:
agent-code-review:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
npx -y @anthropic-ai/claude-code@latest \
--output-format stream-json \
--allowedTools "Read,Write,Edit,Bash" \
--permission-mode acceptEdits \
"Review the code, find bugs, fix them, and create a commit"
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
branch: agent-fixes
base: main
title: "Agent auto-fix: code review & bug fixes"
body: "This PR is automatically generated by claude-agent-sdk"
Hal penting yang perlu dipertimbangkan:
- Jangan gunakan langsung identitas commit yang dibuat agen. Gunakan action
create-pull-requestyang menangani autentikasi dan identitas commit secara otomatis. --permission-mode acceptEditsmemungkinkan agen mengubah berkas tanpa meminta izin. Untuk workflow yang lebih sensitif terhadap keamanan, gunakan--permission-mode planagar agen hanya membuat rencana yang kemudian Anda terapkan secara manual.- Jika seluruh proses ingin dialirkan ke log CI, gunakan
--output-format stream-json. - Jangan jalankan perintah interaktif di CI. Pastikan semua izin telah dipraotorisasi.
Ada satu poin penting lainnya: di lingkungan CI, eksekusi CLI pertama kali menyiapkan lingkungan. Inisialisasi ini dapat berlangsung 30–60 detik. Jika eksekusi sering dilakukan, pertimbangkan men-cache direktori ~/.claude:
- name: Cache Claude Code
uses: actions/cache@v4
with:
path: ~/.claude
key: ${{ runner.os }}-claude-${{ hashFiles('**/package-lock.json') }}
Menggunakan SDK di lingkungan CI Node.js
Jika ingin menulis skrip CI kustom di Node.js, SDK dapat digunakan langsung:
// ci-agent.ts
import { query } from "@anthropic-ai/claude-agent-sdk";
import { execSync } from "node:child_process";
import * as fs from "node:fs";
async function runAgent() {
const prompt = `
You are working in a Node.js project.
Please complete the following tasks:
1. Read the current git diff
2. Look for any obvious bugs or type errors
3. Fix them
4. Write a test for the changes
5. Run the tests to make sure they pass
`;
const session = await query({
prompt,
options: {
allowedTools: ["Bash", "Read", "Write", "Edit"],
hooks: {
PreToolUse: [
{
matcher: "Bash",
hook: async (input) => {
const command = input.tool_input.command;
if (!["git", "npm", "node", "npx"].some((cmd) => command.trim().startsWith(cmd))) {
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: `Command not allowed in CI: ${command}`,
},
};
}
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "allow",
},
};
},
},
],
},
},
});
for await (const message of session) {
if (message.type === "stream_event") {
// You can send this to your log aggregation system
console.log(JSON.stringify(message.event));
}
}
const diff = execSync("git diff --stat").toString();
console.log("===== Agent Changes =====");
console.log(diff);
}
runAgent().catch(console.error);
Dalam skrip ini, query memulai sesi dan menjalankan agen. Hooks memastikan agen hanya dapat menggunakan perintah git, npm, node, dan npx, sehingga risiko eksekusi kode arbitrer berkurang drastis. Terakhir, diff diambil untuk membantu memutuskan apakah akan membuat PR atau langsung mengirim perubahan.
6. Kolaborasi multiagen: meneruskan tugas antaragen
Pola multiagen yang paling praktis bukan model “supervisor” yang rumit, tetapi subagen + pipeline. Artinya, alih-alih menumpuk seluruh tanggung jawab dalam satu prompt raksasa, pecah pekerjaan menjadi beberapa eksekusi agen yang berdiri sendiri, masing-masing dengan sasaran dan cakupan izin sendiri.
Contoh: pipeline refaktor kode
Misalkan kebutuhannya: “Refaktor modul pembayaran, ekstrak logika bersama, dan tulis tes.”
Pekerjaan dapat dibagi kepada tiga agen:
- Agen Penjelajah: membaca kode dan membuat rencana refaktor.
- Agen Implementasi: menjalankan rencana dan mengubah kode.
- Agen Peninjau: memeriksa perubahan dan membuat laporan.
Setiap agen memiliki peran, cakupan izin, dan direktori kerja yang berbeda. Berikut cara mengorkestrasikannya:
// multi-agent.ts
import { query } from "@anthropic-ai/claude-agent-sdk";
import * as fs from "node:fs";
interface AgentResult {
sessionId: string;
finalText: string;
output: string;
}
async function runAgent(
prompt: string,
allowedTools: any[],
sessionId?: string
): Promise<AgentResult> {
const session = await query({
prompt,
options: {
allowedTools,
...(sessionId ? { resume: sessionId } : {}),
hooks: {
PreToolUse: [
{
matcher: "Bash",
hook: async (input) => {
if (input.tool_input.command.includes("rm -rf")) {
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "rm -rf is prohibited",
},
};
}
return {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "allow",
},
};
},
},
],
},
},
});
const messages = [];
for await (const message of session) {
if (message.type === "stream_event") {
messages.push(message.event);
if (message.event.type === "result") {
return {
sessionId: session.sessionId,
finalText: message.event.result,
output: JSON.stringify(messages),
};
}
}
}
throw new Error("Agent did not produce a result");
}
async function main() {
// Step 1: Explorer Agent — read and plan
const explorerResult = await runAgent(
`You are the code explorer. Read the payment module under src/payments/.
Analyze the current structure and potential issues. Output a concise
refactoring plan with specific file paths and actions.`,
["Read", "Glob", "Grep"]
);
console.log("===== Explorer Agent Plan =====");
console.log(explorerResult.finalText);
// Step 2: Implementer Agent — execute the plan
const implementerResult = await runAgent(
`You are the implementer. Here is the refactoring plan from the explorer:
${explorerResult.finalText}
Implement the plan. Edit the code, make the changes, and run the tests
to make sure everything passes.`,
["Read", "Write", "Edit", "Bash"]
);
console.log("===== Implementer Agent Result =====");
console.log(implementerResult.finalText);
// Step 3: Reviewer Agent — review the changes
const reviewResult = await runAgent(
`You are the code reviewer. Here is what the implementer did:
${implementerResult.finalText}
Review the current git diff and the files that were changed.
Look for bugs, security issues, and code quality issues.
Write a detailed review report.`,
["Read", "Bash", "Glob", "Grep"]
);
console.log("===== Reviewer Agent Report =====");
console.log(reviewResult.finalText);
}
main().catch(console.error);
Mengapa pola ini lebih mudah dipelihara?
- Konteks terisolasi pada tiap eksekusi: setiap agen memulai dengan konteks baru dan tidak perlu membawa seluruh data eksekusi sebelumnya, sehingga menghindari masalah konteks terlalu panjang.
- Batas tugas: memisahkan “analisis”, “eksekusi”, dan “peninjauan” secara alami memisahkan tugas dan izin. Agen implementasi tidak perlu dapat menjelajahi seluruh internet; agen peninjau tidak perlu dapat menulis berkas.
- Observabilitas: setiap tahap menghasilkan keluaran jelas (rencana, perubahan, laporan) yang dapat disimpan, dibandingkan, dan diaudit.
- Penanganan kegagalan yang teratur: tiap tahap dapat dibungkus logika coba ulang; jika implementasi gagal, proses dapat dimulai lagi dari keluaran penjelajah tanpa memasukkan kembali seluruh riwayat agen.
7. Kesimpulan: SDK adalah tiket masuk ke era agen
Mari rangkum pembahasan:
- Prinsip arsitektur: semuanya adalah sesi. SDK menangani manajemen status; data hulu dan hilir hanya
sessionId. - Mekanisme inti: alat bawaan, sistem izin, dan hooks. Loop agen dapat dikendalikan secara statis dengan
isAlloweddan secara dinamis dengan hooks. - Praktik produksi: hooks dapat membangun gerbang keamanan;
query()dapat mengintegrasikan agen ke CI/CD; beberapa sesi dapat membangun pipeline multiagen. - Pola integrasi: CLI cocok untuk integrasi sederhana, SDK untuk integrasi kustom.
Apakah saya masih perlu menulis loop agen sendiri?
Tidak. Sama seperti bertanya, “Apakah saya perlu menulis tumpukan TCP sendiri ketika sudah ada HTTP?” Logika kustom hanya diperlukan jika ada kebutuhan yang benar-benar khusus. claude-agent-sdk sudah cukup modular. Jika benar-benar memerlukan kendali tingkat lebih rendah, gunakan Anthropic SDK resmi secara langsung. Namun untuk aplikasi agen tingkat produksi, membangun di atas claude-agent-sdk merupakan pilihan yang paling efisien, tangguh, dan mudah dipelihara.
Masa depan rekayasa AI bukan tentang sensasi, melainkan proses, izin, observabilitas, dan pragmatisme. SDK ini bukan mainan, melainkan masa depan rekayasa perangkat lunak.
Referensi
Artikel ini diterjemahkan oleh Claude. Jika menemukan masalah terjemahan, silakan beri tahu penulis.
Penulis:AI Router
Tautan:https://www.airouter.me/blog/claude-code-agent-sdk
Penggunaan ulang nonkomersial dengan atribusi (CC BY-NC-SA 4.0).