Tool use pattern dengan Claude SDK
Bikin Claude bisa panggil function kamu — search produk Tokopedia, cek saldo BCA, query database. Pattern tool-call loop yang clean.
Dipublikasikan 3 Juni 2026
Pakai LLM cuma buat ngobrol itu sayang. Tool use bikin Claude bisa ambil keputusan — kapan harus cek inventory Bukalapak, kapan harus query database, kapan harus hitung dengan kalkulator. Pattern di bawah loop sampai Claude bilang “selesai”. Production-ready, tidak ribet.
Kode
import Anthropic from "@anthropic-ai/sdk";
import type { MessageParam, Tool } from "@anthropic-ai/sdk/resources/messages";
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY! });
// Definisi tool yang Claude bisa panggil
const tools: Tool[] = [
{
name: "cek_stok_produk",
description: "Cek stok produk di gudang berdasarkan SKU",
input_schema: {
type: "object",
properties: {
sku: { type: "string", description: "Kode SKU produk, contoh: TKP-12345" },
},
required: ["sku"],
},
},
{
name: "hitung_ongkir",
description: "Hitung ongkos kirim antar kota di Indonesia",
input_schema: {
type: "object",
properties: {
kota_asal: { type: "string" },
kota_tujuan: { type: "string" },
berat_gram: { type: "number" },
},
required: ["kota_asal", "kota_tujuan", "berat_gram"],
},
},
];
// Implementasi tool — di production ini panggil DB / API beneran
const toolImplementations: Record<string, (args: any) => Promise<unknown>> = {
cek_stok_produk: async ({ sku }) => {
// simulasi query DB
const stok: Record<string, number> = { "TKP-12345": 42, "TKP-99999": 0 };
return { sku, stok: stok[sku] ?? 0, gudang: "Cikarang" };
},
hitung_ongkir: async ({ kota_asal, kota_tujuan, berat_gram }) => {
const tarif = Math.ceil(berat_gram / 1000) * 12000;
return { kota_asal, kota_tujuan, ongkir: tarif, kurir: "JNE Reguler" };
},
};
export async function chatWithTools(userMessage: string): Promise<string> {
const messages: MessageParam[] = [{ role: "user", content: userMessage }];
// Loop sampai Claude tidak request tool lagi
for (let iteration = 0; iteration < 10; iteration++) {
const response = await client.messages.create({
model: "claude-opus-4-5",
max_tokens: 1024,
tools,
messages,
});
// Append response Claude ke history
messages.push({ role: "assistant", content: response.content });
if (response.stop_reason !== "tool_use") {
// Selesai — ambil text final
const textBlock = response.content.find((b) => b.type === "text");
return textBlock?.type === "text" ? textBlock.text : "";
}
// Eksekusi semua tool_use block, kumpulkan hasil
const toolResults: MessageParam = { role: "user", content: [] };
for (const block of response.content) {
if (block.type === "tool_use") {
const impl = toolImplementations[block.name];
let result: unknown;
try {
result = await impl(block.input);
} catch (err) {
result = { error: err instanceof Error ? err.message : String(err) };
}
(toolResults.content as any[]).push({
type: "tool_result",
tool_use_id: block.id,
content: JSON.stringify(result),
});
}
}
messages.push(toolResults);
}
throw new Error("Max iteration tool loop terlewati");
}
Pemakaian
const jawaban = await chatWithTools(
"Stok SKU TKP-12345 berapa? Kalau ada, hitung ongkir 2kg dari Jakarta ke Surabaya"
);
console.log(jawaban);
// "Stok produk TKP-12345 di gudang Cikarang ada 42 unit. Ongkir 2kg
// dari Jakarta ke Surabaya via JNE Reguler sebesar Rp 24.000."
// Pattern: log setiap tool call untuk debugging / audit
const jawaban2 = await chatWithTools(
"Bandingkan ongkir 1kg dan 5kg dari Bandung ke Medan"
);
// Behind the scene: hitung_ongkir dipanggil 2 kali dengan parameter beda
Kapan dipakai
- AI agent yang harus akses sistem internal (CRM, inventory, billing).
- Customer service bot yang butuh action nyata, bukan cuma jawab text.
- Workflow automation — Claude jadi orchestrator yang panggil tool sesuai context.
- Data analyst bot — query DB, run kalkulasi, generate chart.
Catatan
- Iteration limit — selalu kasih max iteration (snippet ini 10). Tanpa itu, kalau Claude loop infinite, biayanya bisa meledak.
- Tool result harus string — JSON.stringify dulu sebelum kirim, walaupun field nya
content. - Error handling per tool — kalau satu tool fail, kirim error message-nya ke Claude. Claude bisa decide retry atau jawab user dengan info error.
- Concurrent tool execution — kalau Claude return multiple tool_use sekaligus, parallelize dengan
Promise.alluntuk speed. - Schema strict — pakai
additionalProperties: falsediinput_schemakalau mau ketat. Validasi lagi server-side karena LLM bisa hallucinate field.
Hati-hati pasang tool yang side-effect (delete, transfer dana). Selalu pasang konfirmasi manual untuk action irreversible. Claude sometimes overconfident dan execute aja.
# tags
claudetool-usefunction-callingagentai
Ditulis oleh Asti Larasati · 3 Juni 2026