Prasyarat

  • Node.js 18+

Instalasi

Instal @anthropic-ai/claude-code dari NPM:

npm install -g @anthropic-ai/claude-code

Untuk melihat kode sumber TypeScript SDK, kunjungi halaman @anthropic-ai/claude-code di NPM.

Penggunaan dasar

Antarmuka utama melalui TypeScript SDK adalah fungsi query, yang mengembalikan iterator async yang mengalirkan pesan saat mereka tiba:

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Analisis performa sistem",
  options: {
    maxTurns: 5,
    appendSystemPrompt: "Anda adalah seorang insinyur performa",
    allowedTools: ["Bash", "Read", "WebSearch"],
    abortController: new AbortController(),
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Opsi konfigurasi

ArgumenTipeDeskripsiDefault
abortControllerAbortControllerAbort controller untuk membatalkan operasinew AbortController()
additionalDirectoriesstring[]Direktori tambahan untuk disertakan dalam sesiundefined
allowedToolsstring[]Daftar alat yang diizinkan digunakan ClaudeSemua alat diaktifkan secara default
appendSystemPromptstringTeks untuk ditambahkan ke prompt sistem defaultundefined
canUseTool(toolName: string, input: any) => Promise<ToolPermissionResult>Fungsi izin kustom untuk penggunaan alatundefined
continuebooleanLanjutkan sesi terbarufalse
customSystemPromptstringGanti prompt sistem default sepenuhnyaundefined
cwdstringDirektori kerja saat iniprocess.cwd()
disallowedToolsstring[]Daftar alat yang tidak diizinkan digunakan Claudeundefined
envDict<string>Variabel lingkungan untuk diaturundefined
executable'bun' | 'deno' | 'node'Runtime JavaScript mana yang akan digunakannode saat berjalan dengan Node.js, bun saat berjalan dengan Bun
executableArgsstring[]Argumen untuk diteruskan ke executable[]
fallbackModelstringModel untuk digunakan jika model utama gagalundefined
hooksPartial<Record<HookEvent, HookCallbackMatcher[]>>Hook siklus hidup untuk kustomisasiundefined
includePartialMessagesbooleanSertakan event streaming parsial dalam aliran pesanfalse
maxThinkingTokensnumberToken maksimum untuk proses berpikir Claudeundefined
maxTurnsnumberJumlah maksimum giliran percakapanundefined
mcpServersRecord<string, McpServerConfig>Konfigurasi server MCPundefined
modelstringModel Claude untuk digunakanMenggunakan default dari konfigurasi CLI
pathToClaudeCodeExecutablestringPath ke executable Claude CodeExecutable yang dikirim dengan @anthropic-ai/claude-code
permissionModePermissionModeMode izin untuk sesi"default" (opsi: "default", "acceptEdits", "bypassPermissions", "plan")
resumestringID sesi untuk dilanjutkanundefined
stderr(data: string) => voidCallback untuk output stderrundefined
strictMcpConfigbooleanPaksa validasi konfigurasi MCP yang ketatundefined

Streaming pesan parsial

Ketika includePartialMessages diaktifkan, SDK akan mengeluarkan pesan stream_event yang berisi event streaming mentah dari Claude API. Ini memungkinkan Anda mengakses konten parsial saat sedang dibuat, berguna untuk mengimplementasikan pembaruan UI real-time atau indikator progres.

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Tulis esai panjang tentang kecerdasan buatan",
  options: {
    includePartialMessages: true,
    maxTurns: 1
  }
})) {
  // Tangani event streaming parsial
  if (message.type === "stream_event") {
    const event = message.event;
    
    // Akses teks parsial saat streaming
    if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
      process.stdout.write(event.delta.text);
    }
    
    // Lacak progres berpikir
    if (event.type === "content_block_start" && event.content_block.type === "thinking") {
      console.log("\n[Claude sedang berpikir...]");
    }
  }
  
  // Tetap dapatkan hasil akhir
  if (message.type === "result" && message.subtype === "success") {
    console.log("\nHasil akhir:", message.result);
  }
}

Setiap pesan stream_event mencakup:

  • event: Event streaming mentah dari API
  • session_id: Pengenal sesi saat ini
  • parent_tool_use_id: ID alat yang sedang dieksekusi (jika berlaku)
  • uuid: Pengenal unik untuk event ini

Streaming pesan parsial terutama berguna untuk kasus penggunaan lanjutan di mana Anda memerlukan kontrol granular atas respons streaming. Untuk sebagian besar aplikasi, perilaku default (menunggu pesan lengkap) sudah cukup.

Percakapan multi-turn

Untuk percakapan multi-turn, Anda memiliki dua opsi.

Anda dapat menghasilkan respons dan melanjutkannya, atau Anda dapat menggunakan mode input streaming yang menerima async/generator untuk array pesan. Untuk saat ini, mode input streaming adalah satu-satunya cara untuk melampirkan gambar melalui pesan.

Lanjutkan dengan manajemen sesi

import { query } from "@anthropic-ai/claude-code";

// Lanjutkan percakapan terbaru
for await (const message of query({
  prompt: "Sekarang refaktor ini untuk performa yang lebih baik",
  options: { continue: true }
})) { 
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Lanjutkan sesi spesifik
for await (const message of query({
  prompt: "Perbarui tes",
  options: {
    resume: "550e8400-e29b-41d4-a716-446655440000",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Mode input streaming

Mode input streaming memungkinkan Anda menyediakan pesan sebagai async iterable alih-alih string tunggal. Ini memungkinkan percakapan multi-turn, lampiran gambar, dan generasi pesan dinamis:

import { query } from "@anthropic-ai/claude-code";

// Buat generator async untuk streaming pesan
async function* generateMessages() {
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Mulai menganalisis codebase ini"
    }
  };
  
  // Tunggu kondisi tertentu atau input pengguna
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Sekarang fokus pada modul autentikasi"
    }
  };
}

// Gunakan input streaming
for await (const message of query({
  prompt: generateMessages(),
  options: {
    maxTurns: 5,
    allowedTools: ["Read", "Grep", "Bash"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Input streaming dengan gambar

Mode input streaming adalah satu-satunya cara untuk melampirkan gambar melalui pesan:

import { query } from "@anthropic-ai/claude-code";
import { readFileSync } from "fs";

async function* messagesWithImage() {
  // Kirim gambar dengan teks
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: [
        {
          type: "text",
          text: "Analisis screenshot ini dan sarankan perbaikan"
        },
        {
          type: "image",
          source: {
            type: "base64",
            media_type: "image/png",
            data: readFileSync("screenshot.png", "base64")
          }
        }
      ]
    }
  };
}

for await (const message of query({
  prompt: messagesWithImage()
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Prompt sistem kustom

Prompt sistem mendefinisikan peran, keahlian, dan perilaku agen Anda:

import { query } from "@anthropic-ai/claude-code";

// Agen respons insiden SRE
for await (const message of query({
  prompt: "API down, investigasi",
  options: {
    customSystemPrompt: "Anda adalah ahli SRE. Diagnosis masalah secara sistematis dan berikan solusi yang dapat ditindaklanjuti.",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Tambahkan ke prompt sistem default
for await (const message of query({
  prompt: "Refaktor fungsi ini",
  options: {
    appendSystemPrompt: "Selalu sertakan penanganan error yang komprehensif dan unit test.",
    maxTurns: 2
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Integrasi Server MCP

Model Context Protocol (MCP) memungkinkan Anda memberikan agen Anda alat dan kemampuan kustom:

import { query } from "@anthropic-ai/claude-code";

// Agen SRE dengan alat monitoring
for await (const message of query({
  prompt: "Investigasi gangguan layanan pembayaran",
  options: {
    mcpConfig: "sre-tools.json",
    allowedTools: ["mcp__datadog", "mcp__pagerduty", "mcp__kubernetes"],
    appendSystemPrompt: "Anda adalah SRE. Gunakan data monitoring untuk mendiagnosis masalah.",
    maxTurns: 4
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Alat kustom dengan server MCP in-process

Server MCP SDK memungkinkan Anda membuat alat kustom yang berjalan langsung dalam proses aplikasi Anda, menyediakan eksekusi alat yang type-safe tanpa overhead proses terpisah atau komunikasi jaringan.

Membuat alat kustom

Gunakan fungsi helper createSdkMcpServer dan tool untuk mendefinisikan alat kustom yang type-safe:

import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-code";
import { z } from "zod";

// Buat server MCP SDK dengan alat kustom
const customServer = createSdkMcpServer({
  name: "my-custom-tools",
  version: "1.0.0",
  tools: [
    tool(
      "calculate_compound_interest",
      "Hitung bunga majemuk untuk investasi",
      {
        principal: z.number().describe("Jumlah investasi awal"),
        rate: z.number().describe("Tingkat bunga tahunan (sebagai desimal, mis. 0.05 untuk 5%)"),
        time: z.number().describe("Periode investasi dalam tahun"),
        n: z.number().default(12).describe("Frekuensi pemajemukan per tahun")
      },
      async (args) => {
        const amount = args.principal * Math.pow(1 + args.rate / args.n, args.n * args.time);
        const interest = amount - args.principal;
        
        return {
          content: [{
            type: "text",
            text: `Jumlah akhir: $${amount.toFixed(2)}\nBunga yang diperoleh: $${interest.toFixed(2)}`
          }]
        };
      }
    ),
    tool(
      "fetch_user_data",
      "Ambil data pengguna dari database aplikasi Anda",
      {
        userId: z.string().describe("ID pengguna yang akan diambil"),
        fields: z.array(z.string()).optional().describe("Field spesifik untuk dikembalikan")
      },
      async (args) => {
        // Akses langsung ke lapisan data aplikasi Anda
        const userData = await myDatabase.getUser(args.userId, args.fields);
        
        return {
          content: [{
            type: "text",
            text: JSON.stringify(userData, null, 2)
          }]
        };
      }
    )
  ]
});

// Gunakan alat kustom dalam query Anda
for await (const message of query({
  prompt: "Hitung bunga majemuk untuk $10,000 pada 5% selama 10 tahun",
  options: {
    mcpServers: {
      "my-custom-tools": customServer
    },
    maxTurns: 3
  }
})) {
  if (message.type === "result") {
    console.log(message.result);
  }
}

Type safety dengan Zod

Helper tool menyediakan inferensi tipe TypeScript penuh dari skema Zod Anda:

tool(
  "process_data",
  "Proses data terstruktur dengan type safety",
  {
    // Skema Zod mendefinisikan validasi runtime dan tipe TypeScript
    data: z.object({
      name: z.string(),
      age: z.number().min(0).max(150),
      email: z.string().email(),
      preferences: z.array(z.string()).optional()
    }),
    format: z.enum(["json", "csv", "xml"]).default("json")
  },
  async (args) => {
    // args sepenuhnya diketik berdasarkan skema
    // TypeScript tahu: args.data.name adalah string, args.data.age adalah number, dll.
    console.log(`Memproses data ${args.data.name} sebagai ${args.format}`);
    
    // Logika pemrosesan Anda di sini
    return {
      content: [{
        type: "text",
        text: `Data diproses untuk ${args.data.name}`
      }]
    };
  }
)

Hook

Hook memungkinkan Anda menyesuaikan dan memperluas perilaku Claude Code dengan menjalankan callback kustom pada berbagai titik dalam siklus hidup agen. Tidak seperti hook CLI yang mengeksekusi perintah bash, hook SDK adalah fungsi JavaScript/TypeScript yang berjalan in-process.

Mendefinisikan hook

Hook diorganisir berdasarkan tipe event, dengan matcher opsional untuk memfilter kapan mereka berjalan:

import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Analisis codebase",
  options: {
    hooks: {
      PreToolUse: [
        {
          matcher: "Write",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`Akan menulis file: ${input.tool_input.file_path}`);
              
              // Validasi operasi
              if (input.tool_input.file_path.includes('.env')) {
                return {
                  decision: 'block',
                  stopReason: 'Tidak dapat menulis ke file environment'
                };
              }
              
              // Izinkan operasi
              return { continue: true };
            }
          ]
        }
      ],
      PostToolUse: [
        {
          matcher: "Write|Edit",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`File dimodifikasi: ${input.tool_response.filePath}`);
              // Jalankan formatting atau validasi kustom Anda
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Event hook yang tersedia

  • PreToolUse: Berjalan sebelum eksekusi alat. Dapat memblokir alat atau memberikan umpan balik.
  • PostToolUse: Berjalan setelah eksekusi alat berhasil.
  • UserPromptSubmit: Berjalan ketika pengguna mengirimkan prompt.
  • SessionStart: Berjalan ketika sesi dimulai.
  • SessionEnd: Berjalan ketika sesi berakhir.
  • Stop: Berjalan ketika Claude akan berhenti merespons.
  • SubagentStop: Berjalan ketika subagen akan berhenti.
  • PreCompact: Berjalan sebelum pemadatan percakapan.
  • Notification: Berjalan ketika notifikasi dikirim.

Tipe input hook

Setiap hook menerima input yang diketik berdasarkan event:

// Input PreToolUse
type PreToolUseHookInput = {
  hook_event_name: 'PreToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
}

// Input PostToolUse
type PostToolUseHookInput = {
  hook_event_name: 'PostToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
  tool_response: unknown;
}

Output hook

Hook mengembalikan output yang mengontrol alur eksekusi:

interface HookJSONOutput {
  // Lanjutkan eksekusi (default: true)
  continue?: boolean;
  
  // Tekan output ke pengguna
  suppressOutput?: boolean;
  
  // Alasan berhenti (ditampilkan ke model)
  stopReason?: string;
  
  // Keputusan untuk hook PreToolUse
  decision?: 'approve' | 'block';
  
  // Pesan sistem untuk ditampilkan
  systemMessage?: string;
  
  // Output spesifik hook
  hookSpecificOutput?: {
    // Untuk PreToolUse
    permissionDecision?: 'allow' | 'deny' | 'ask';
    permissionDecisionReason?: string;
    
    // Untuk UserPromptSubmit atau PostToolUse
    additionalContext?: string;
  };
}

Contoh praktis

Logging dan monitoring

const hooks = {
  PreToolUse: [
    {
      hooks: [
        async (input) => {
          // Log semua penggunaan alat
          await logToMonitoring({
            event: 'tool_use',
            tool: input.tool_name,
            input: input.tool_input,
            session: input.session_id
          });
          
          return { continue: true };
        }
      ]
    }
  ]
};

Validasi operasi file

const hooks = {
  PreToolUse: [
    {
      matcher: "Write|Edit",
      hooks: [
        async (input) => {
          const filePath = input.tool_input.file_path;
          
          // Blokir file sensitif
          const sensitivePatterns = ['.env', '.git/', 'secrets/', '*.key'];
          
          for (const pattern of sensitivePatterns) {
            if (filePath.includes(pattern)) {
              return {
                decision: 'block',
                stopReason: `Tidak dapat memodifikasi file sensitif yang cocok dengan ${pattern}`
              };
            }
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Auto-formatting kode

import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

const hooks = {
  PostToolUse: [
    {
      matcher: "Write|Edit|MultiEdit",
      hooks: [
        async (input) => {
          const filePath = input.tool_response.filePath;
          
          // Auto-format berdasarkan tipe file
          if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
            await execAsync(`prettier --write "${filePath}"`);
          } else if (filePath.endsWith('.py')) {
            await execAsync(`black "${filePath}"`);
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Peningkatan prompt

const hooks = {
  UserPromptSubmit: [
    {
      hooks: [
        async (input) => {
          // Tambahkan konteks ke prompt
          const projectContext = await loadProjectContext();
          
          return {
            continue: true,
            hookSpecificOutput: {
              hookEventName: 'UserPromptSubmit',
              additionalContext: `Konteks proyek: ${projectContext}`
            }
          };
        }
      ]
    }
  ]
};

Instruksi pemadatan kustom

const hooks = {
  PreCompact: [
    {
      hooks: [
        async (input) => {
          const trigger = input.trigger; // 'manual' atau 'auto'
          
          return {
            continue: true,
            systemMessage: 'Fokus pada mempertahankan detail implementasi dan resolusi error'
          };
        }
      ]
    }
  ]
};

Perilaku eksekusi hook

  • Paralelisasi: Semua hook yang cocok berjalan secara paralel
  • Timeout: Hook menghormati sinyal abort dari opsi
  • Penanganan error: Error hook dicatat tetapi tidak menghentikan eksekusi
  • Matcher: Mendukung pola regex (mis. "Write|Edit")

Menggabungkan hook dengan canUseTool

Sementara canUseTool menyediakan kontrol izin, hook menawarkan integrasi siklus hidup yang lebih luas:

for await (const message of query({
  prompt: "Bangun fitur",
  options: {
    // Kontrol izin yang detail
    canUseTool: async (toolName, input) => {
      // Modifikasi input atau tolak berdasarkan kondisi runtime
      return { behavior: "allow", updatedInput: input };
    },
    
    // Hook siklus hidup untuk monitoring dan otomasi
    hooks: {
      PreToolUse: [
        {
          hooks: [
            async (input) => {
              // Log, validasi, atau persiapkan
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  // Proses pesan
}

Kontrol izin dengan canUseTool

Callback canUseTool menyediakan kontrol yang detail atas eksekusi alat. Ini dipanggil sebelum setiap penggunaan alat dan dapat mengizinkan, menolak, atau memodifikasi input alat:

type ToolPermissionResult = 
  | { behavior: "allow"; updatedInput?: any }
  | { behavior: "deny"; message?: string };

for await (const message of query({
  prompt: "Analisis perilaku pengguna dan hitung metrik",
  options: {
    mcpServers: {
      "analytics": analyticsServer
    },
    canUseTool: async (toolName: string, input: any) => {
      // Kontrol alat mana yang dapat digunakan
      if (toolName.startsWith("mcp__analytics__")) {
        // Periksa izin untuk alat analytics
        const hasPermission = await checkUserPermissions(toolName);
        
        return hasPermission
          ? { behavior: "allow", updatedInput: input }
          : { behavior: "deny", message: "Izin tidak mencukupi" };
      }
      
      // Modifikasi input untuk alat tertentu
      if (toolName === "Bash") {
        // Tambahkan pemeriksaan keamanan atau modifikasi perintah
        const safeInput = sanitizeBashCommand(input);
        return { behavior: "allow", updatedInput: safeInput };
      }
      
      // Izinkan alat lain secara default
      return { behavior: "allow", updatedInput: input };
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Kasus penggunaan untuk canUseTool

  • Manajemen izin: Periksa izin pengguna sebelum mengizinkan eksekusi alat
  • Validasi input: Validasi atau sanitasi input alat sebelum eksekusi
  • Rate limiting: Implementasikan batas rate untuk operasi mahal
  • Audit logging: Log penggunaan alat untuk kepatuhan atau debugging
  • Izin dinamis: Aktifkan/nonaktifkan alat berdasarkan kondisi runtime
// Contoh: Rate limiter web scraping
const rateLimits = new Map<string, { count: number; resetTime: number }>();

const canUseTool = async (toolName: string, input: any) => {
  // Rate limit web scraping untuk mencegah IP ban dan masalah kuota API
  if (toolName === "WebFetch" || toolName === "WebSearch") {
    const now = Date.now();
    const limit = rateLimits.get(toolName) || { count: 0, resetTime: now + 60000 };
    
    // Reset counter setiap menit
    if (now > limit.resetTime) {
      limit.count = 0;
      limit.resetTime = now + 60000;
    }
    
    // Izinkan maksimal 10 permintaan per menit
    if (limit.count >= 10) {
      return { 
        behavior: "deny", 
        message: `Batas rate terlampaui: maksimal 10 permintaan ${toolName} per menit. Reset dalam ${Math.ceil((limit.resetTime - now) / 1000)}s` 
      };
    }
    
    limit.count++;
    rateLimits.set(toolName, limit);
    
    // Log aktivitas scraping untuk monitoring
    console.log(`Permintaan ${toolName} ${limit.count}/10 ke: ${input.url || input.query}`);
  }
  
  // Cegah loop tak terbatas yang tidak disengaja dalam skrip bash
  if (toolName === "Bash" && input.command?.includes("while true")) {
    return { 
      behavior: "deny", 
      message: "Loop tak terbatas tidak diizinkan" 
    };
  }
  
  return { behavior: "allow", updatedInput: input };
};

Format output

Output teks (default)

// Output teks default
for await (const message of query({
  prompt: "Jelaskan file src/components/Header.tsx"
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
    // Output: Ini adalah komponen React yang menampilkan...
  }
}

Output JSON

// Kumpulkan semua pesan untuk akses seperti JSON
const messages = [];
for await (const message of query({
  prompt: "Bagaimana lapisan data bekerja?"
})) {
  messages.push(message);
}

// Akses pesan hasil dengan metadata
const result = messages.find(m => m.type === "result" && message.subtype === "success");
console.log({
  result: result.result,
  cost: result.total_cost_usd,
  duration: result.duration_ms
});

Format input

// Prompt langsung
for await (const message of query({
  prompt: "Jelaskan kode ini"
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Dari variabel
const userInput = "Jelaskan kode ini";
for await (const message of query({ prompt: userInput })) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Contoh integrasi agen

Agen respons insiden SRE

import { query } from "@anthropic-ai/claude-code";

// Agen respons insiden otomatis
async function investigateIncident(
  incidentDescription: string,
  severity = "medium"
) {
  const messages = [];

  for await (const message of query({
    prompt: `Insiden: ${incidentDescription} (Tingkat keparahan: ${severity})`,
    options: {
      appendSystemPrompt: "Anda adalah ahli SRE. Diagnosis masalah, nilai dampak, dan berikan item tindakan segera.",
      maxTurns: 6,
      allowedTools: ["Bash", "Read", "WebSearch", "mcp__datadog"],
      mcpConfig: "monitoring-tools.json"
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// Penggunaan
const result = await investigateIncident("Payment API mengembalikan error 500", "high");
console.log(result.result);

Review keamanan otomatis

import { query } from "@anthropic-ai/claude-code";
import { execSync } from "child_process";

async function auditPR(prNumber: number) {
  // Dapatkan diff PR
  const prDiff = execSync(`gh pr diff ${prNumber}`, { encoding: 'utf8' });

  const messages = [];
  for await (const message of query({
    prompt: prDiff,
    options: {
      appendSystemPrompt: "Anda adalah insinyur keamanan. Review PR ini untuk kerentanan, pola tidak aman, dan masalah kepatuhan.",
      maxTurns: 3,
      allowedTools: ["Read", "Grep", "WebSearch"]
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// Penggunaan
const report = await auditPR(123);
console.log(JSON.stringify(report, null, 2));

Asisten hukum multi-turn

import { query } from "@anthropic-ai/claude-code";

async function legalReview() {
  // Mulai sesi review hukum
  let sessionId: string;

  for await (const message of query({
    prompt: "Mulai sesi review hukum",
    options: { maxTurns: 1 }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      sessionId = message.session_id;
    }
  }

  // Review multi-langkah menggunakan sesi yang sama
  const steps = [
    "Review contract.pdf untuk klausul tanggung jawab",
    "Periksa kepatuhan dengan persyaratan GDPR",
    "Buat ringkasan eksekutif risiko"
  ];

  for (const step of steps) {
    for await (const message of query({
      prompt: step,
      options: { resume: sessionId, maxTurns: 2 }
    })) {
      if (message.type === "result" && message.subtype === "success") {
        console.log(`Langkah: ${step}`);
        console.log(message.result);
      }
    }
  }
}

Skema pesan

Pesan yang dikembalikan dari JSON API diketik secara ketat sesuai dengan skema berikut:

type SDKMessage =
  // Pesan asisten
  | {
      type: "assistant";
      uuid: string;
      session_id: string;
      message: Message; // dari Anthropic SDK
      parent_tool_use_id: string | null;
    }

  // Pesan pengguna (input)
  | {
      type: "user";
      uuid?: string;
      session_id: string;
      message: MessageParam; // dari Anthropic SDK
      parent_tool_use_id: string | null;
    }

  // Pesan pengguna (output/replay dengan UUID yang diperlukan)
  | {
      type: "user";
      uuid: string;
      session_id: string;
      message: MessageParam; // dari Anthropic SDK
      parent_tool_use_id: string | null;
    }

  // Dipancarkan sebagai pesan terakhir pada sukses
  | {
      type: "result";
      subtype: "success";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      result: string;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // Dipancarkan sebagai pesan terakhir pada error atau max turns
  | {
      type: "result";
      subtype: "error_max_turns" | "error_during_execution";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // Dipancarkan sebagai pesan pertama di awal percakapan
  | {
      type: "system";
      subtype: "init";
      uuid: UUID;
      session_id: string;
      apiKeySource: "user" | "project" | "org" | "temporary";
      cwd: string;
      tools: string[];
      mcp_servers: {
        name: string;
        status: string;
      }[];
      model: string;
      permissionMode: "default" | "acceptEdits" | "bypassPermissions" | "plan";
      slash_commands: string[];
      output_style: string;
    };

  type SDKPermissionDenial = {
    tool_name: string;
    tool_use_id: string;
    tool_input: Record<string, unknown>;
  }

Tipe pendukung tambahan:

Tipe Message, MessageParam, dan Usage tersedia di Anthropic TypeScript SDK.

Sumber daya terkait