Cara Mengembangkan Chatbot dengan Claude Code
Pelajari cara mengembangkan chatbot menggunakan Claude Code. Dilengkapi contoh kode praktis dan panduan langkah demi langkah.
Mengembangkan Chatbot dengan Claude Code
Pengembangan chatbot AI melibatkan banyak elemen seperti implementasi UI, integrasi API, manajemen percakapan, dan pemrosesan streaming. Dengan Claude Code, chatbot yang mengintegrasikan semuanya bisa dibangun dalam waktu singkat.
Implementasi Chat UI Dasar
> Buat component chatbot di React.
> Dengan dukungan respons streaming, tampilan riwayat percakapan, dan form input.
import { useState, useRef, useEffect } from "react";
interface Message {
id: string;
role: "user" | "assistant";
content: string;
}
export function ChatBot() {
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState("");
const [isLoading, setIsLoading] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
const sendMessage = async () => {
if (!input.trim() || isLoading) return;
const userMessage: Message = {
id: crypto.randomUUID(),
role: "user",
content: input,
};
setMessages((prev) => [...prev, userMessage]);
setInput("");
setIsLoading(true);
const assistantId = crypto.randomUUID();
setMessages((prev) => [
...prev,
{ id: assistantId, role: "assistant", content: "" },
]);
try {
const response = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
messages: [...messages, userMessage].map(({ role, content }) => ({
role,
content,
})),
}),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
setMessages((prev) =>
prev.map((m) =>
m.id === assistantId
? { ...m, content: m.content + chunk }
: m
)
);
}
} catch (error) {
setMessages((prev) =>
prev.map((m) =>
m.id === assistantId
? { ...m, content: "Terjadi error. Silakan coba lagi." }
: m
)
);
}
setIsLoading(false);
};
return (
<div className="flex flex-col h-[600px] border rounded-lg">
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((msg) => (
<div
key={msg.id}
className={`flex ${msg.role === "user" ? "justify-end" : "justify-start"}`}
>
<div
className={`max-w-[70%] p-3 rounded-lg ${
msg.role === "user"
? "bg-blue-600 text-white"
: "bg-gray-100 text-gray-900"
}`}
>
{msg.content}
</div>
</div>
))}
<div ref={messagesEndRef} />
</div>
<div className="border-t p-4 flex gap-2">
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && sendMessage()}
placeholder="Ketik pesan..."
className="flex-1 p-2 border rounded-lg"
disabled={isLoading}
/>
<button
onClick={sendMessage}
disabled={isLoading}
className="px-4 py-2 bg-blue-600 text-white rounded-lg disabled:opacity-50"
>
Kirim
</button>
</div>
</div>
);
}
API Route dengan Dukungan Streaming
API route yang memanggil Anthropic API di backend dan mengembalikan secara streaming.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = await client.messages.stream({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
system: "Kamu adalah asisten yang ramah dan sopan.",
messages,
});
const encoder = new TextEncoder();
const readable = new ReadableStream({
async start(controller) {
for await (const event of stream) {
if (
event.type === "content_block_delta" &&
event.delta.type === "text_delta"
) {
controller.enqueue(encoder.encode(event.delta.text));
}
}
controller.close();
},
});
return new Response(readable, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}
Persistensi Riwayat Percakapan
Menyimpan percakapan ke database agar bisa dilanjutkan nanti.
import { db } from "@/lib/database";
export async function saveConversation(
userId: string,
messages: Message[]
) {
return db.conversation.upsert({
where: { id: `${userId}-current` },
update: {
messages: JSON.stringify(messages),
updatedAt: new Date(),
},
create: {
id: `${userId}-current`,
userId,
messages: JSON.stringify(messages),
},
});
}
export async function loadConversation(userId: string): Promise<Message[]> {
const conv = await db.conversation.findUnique({
where: { id: `${userId}-current` },
});
return conv ? JSON.parse(conv.messages as string) : [];
}
Integrasi RAG (Retrieval-Augmented Generation)
Untuk membuat chatbot yang menjawab berdasarkan dokumen internal, konfigurasi RAG efektif.
import { searchDocuments } from "@/lib/vector-search";
async function generateRAGResponse(query: string, conversationHistory: Message[]) {
// Cari dokumen terkait
const relevantDocs = await searchDocuments(query, { limit: 5 });
const context = relevantDocs
.map((doc) => `---\n${doc.title}\n${doc.content}\n---`)
.join("\n");
const systemPrompt = `Jawab pertanyaan dengan merujuk dokumen berikut.
Jika informasi tidak ada di dokumen, jawab "Informasi tersebut tidak ditemukan".
${context}`;
return client.messages.stream({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
system: systemPrompt,
messages: conversationHistory,
});
}
Untuk cara memperluas fungsionalitas dengan integrasi MCP server, lihat Panduan MCP Server, dan untuk desain prompt yang efektif, lihat 5 Tips Memperbaiki Prompt.
Summary
Dengan Claude Code, chatbot yang mencakup chat UI, streaming API, manajemen percakapan, hingga konfigurasi RAG bisa dikembangkan secara efisien. Pendekatan menambahkan fitur secara bertahap sangat efektif.
Untuk detail, lihat Dokumentasi Resmi Claude Code dan Referensi API Anthropic.
Upgrade Produksi 2026
Chatbot adalah aplikasi yang menerima pesan pengguna, menyimpan konteks secukupnya, lalu memberi jawaban berikutnya dalam bentuk percakapan. Secara sederhana, chatbot adalah pintu masuk untuk support, penjualan, pencarian dokumen, atau panduan belajar. Nilainya bukan hanya pada tampilan chat, tetapi pada workflow yang dipersingkat.
Dengan Claude Code, jangan mulai dari asisten serba bisa. Mulailah dari tugas kecil: menjawab FAQ utama, mengumpulkan data calon pelanggan, mencari dokumen internal, atau membuat draft tiket. Scope kecil lebih mudah diuji, lebih murah dijalankan, dan lebih jelas kontribusinya pada monetisasi.
Tabel Arsitektur
| Lapisan | Tanggung jawab | Catatan produksi |
|---|---|---|
| React UI | Input, riwayat, loading, dan retry | Pola state dasar ada di React useState docs |
| API route | Menyimpan API key di server dan memvalidasi request | Tambahkan limit panjang, autentikasi, dan timeout |
| Streaming | Mengirim jawaban sedikit demi sedikit | Dasarnya ada di MDN Streams API |
| Penyimpanan | Melanjutkan percakapan dan audit kegagalan | Simpan data minimum dan siapkan proses penghapusan |
| RAG | Mencari jawaban dari dokumen produk atau kebijakan | Jika bukti lemah, chatbot harus mengaku tidak tahu |
| Webhook | Mengirim event ke CRM, tiket, atau Slack | Lanjutkan ke Claude Code Webhook Implementation |
| Analytics | Mengukur sukses, eskalasi, dan klik CTA | Gunakan Claude Code Analytics Implementation |
Untuk struktur API, ikuti pola di Claude Code API Development: frontend mengirim role dan content, instruksi sistem ada di server, lalu respons dikirim sebagai stream. Struktur ini membuat UI mudah diganti tanpa membongkar backend.
Demo Streaming yang Bisa Dijalankan
Simpan kode ini sebagai chatbot-stream-demo.mjs, lalu jalankan node chatbot-stream-demo.mjs. Kode ini tidak memanggil API eksternal; tujuannya memverifikasi streaming dan history lebih dulu.
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const faq = new Map([
["password", "Open the account page, choose Reset password, and follow the email link."],
["pricing", "The pricing page explains plans. For a custom quote, collect team size and required features."],
["refund", "Refund requests should be routed to support with the order id and purchase email."],
]);
const history = [];
function chooseAnswer(question) {
const normalized = question.toLowerCase();
for (const [keyword, answer] of faq) {
if (normalized.includes(keyword)) return answer;
}
return "I could not find a safe answer in the FAQ. I will hand this to a human operator.";
}
async function* streamText(text) {
for (const token of text.split(/(\s+)/)) {
await new Promise((resolve) => setTimeout(resolve, 15));
yield encoder.encode(token);
}
}
async function ask(question) {
history.push({ role: "user", content: question });
const answer = chooseAnswer(question);
process.stdout.write(`\nUser: ${question}\nAssistant: `);
let fullAnswer = "";
for await (const chunk of streamText(answer)) {
const token = decoder.decode(chunk);
fullAnswer += token;
process.stdout.write(token);
}
history.push({ role: "assistant", content: fullAnswer });
}
await ask("How do I reset my password?");
await ask("Can I see pricing before talking to sales?");
console.log(`\n\nSaved ${history.length} messages.`);
Di aplikasi nyata, ganti chooseAnswer dengan panggilan Claude API. Urutannya tetap: simpan pesan pengguna, stream jawaban, lalu simpan jawaban final. Ini mencegah failure mode saat UI menampilkan teks, tetapi database menyimpan respons kosong.
Use Case Nyata
Use case pertama adalah kualifikasi lead untuk SaaS. Chatbot menjawab harga, keamanan, integrasi, dan kebutuhan procurement. Jika niat beli tinggi, pengguna diarahkan ke konsultasi. Tim sales menerima percakapan yang lebih siap.
Use case kedua adalah help desk internal. Pertanyaan cuti, reimbursement, VPN, perangkat, dan onboarding sering berulang. RAG bisa menampilkan sumber kebijakan, lalu webhook membuat tiket jika perlu persetujuan.
Use case ketiga adalah situs edukasi. Ketika pembaca bingung harus belajar API, webhook, atau analytics, chatbot merekomendasikan artikel berikutnya dan mengarahkan ke training jika butuh sesi praktik. Workflow ini lebih alami daripada banner penjualan.
Use case keempat adalah intake insiden. Chatbot mengumpulkan pesan error, waktu kejadian, browser, akun, dan langkah reproduksi. Targetnya bukan menyelesaikan semua masalah, tetapi membuat tiket yang lengkap.
Pitfall dan Risiko
Jangan kirim seluruh history tanpa batas ke model. Biaya naik, respons melambat, dan instruksi lama bisa mengganggu pertanyaan baru. Ringkas percakapan lama dan simpan fakta yang relevan saja.
Jangan membuat RAG menjawab tanpa bukti. Jika dokumen tidak ditemukan, chatbot harus mengatakan tidak yakin dan menawarkan jalur manusia. Ini penting untuk support dan kepercayaan pengguna.
Jangan anggap streaming hanya kosmetik. Koneksi putus, double submit, bubble kosong, dan loading tanpa akhir adalah risiko nyata. Gunakan tombol disabled, pembatalan request, timeout, dan pesan retry.
Jangan launch tanpa pengukuran. Catat pertanyaan gagal, eskalasi, klik CTA, dan percakapan yang berujung pembelian atau konsultasi. Jumlah pesan saja tidak membuktikan nilai bisnis.
CTA Monetisasi
Chatbot yang mendukung bisnis harus punya aksi lanjutan yang jelas: audit implementasi, konsultasi, template, atau pelatihan. Di ClaudeCodeLab, jalur yang paling relevan adalah training, karena pembaca bisa membawa implementasi nyata untuk ditinjau.
Alur bacaan yang disarankan: pahami konsep di artikel ini, buat API melalui Claude Code API Development, hubungkan sistem dengan webhooks, lalu ukur dampaknya dengan analytics.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Workflow Obsidian ke CLAUDE.md untuk Claude Code
Ubah catatan kerja Obsidian menjadi operating note CLAUDE.md agar konteks tidak dijelaskan ulang.
Claude Code Revenue CTA Routing: dari artikel ke PDF, Gumroad, dan konsultasi
Workflow Claude Code untuk mengarahkan pembaca ke PDF gratis, Gumroad, atau konsultasi sesuai intent.
Aturan handoff tim Claude Code: bukti review, permission, rollback, dan jalur revenue
Format handoff Claude Code untuk tim: bukti, permission rule, rollback, PDF gratis, Gumroad, dan konsultasi.