2026-06-13 · 7 min
LangChain vs Claude SDK Direct: 6 Bulan Build Agent
Enam bulan lalu saya start build customer service agent untuk klien e-commerce mid-size Jakarta (~14k order/bulan). Versi 1 saya pakai LangChain karena banyak tutorial. Tiga bulan kemudian saya rewrite full pakai Claude SDK direct. Comparison real berdasarkan kerja produktif.
Setup
Use case: agent untuk customer support yang handle order status, return, tukar produk, escalate kompleks ke human. Tools yang agent butuh akses:
- Query order status (Postgres)
- Update return status (Postgres + audit log)
- Send WhatsApp notification (WA Business API)
- Lookup product catalog (Postgres)
- Escalate ke human (Telegram bot ke tim CS)
Volume: ~800 conversation/hari, average 6 turn per conversation.
Versi 1: LangChain
Stack: LangChain.js 0.3, ChatAnthropic provider, agent + tools pattern.
const llm = new ChatAnthropic({ model: 'claude-sonnet-4.7' });
const tools = [orderStatusTool, returnTool, ...];
const agent = createReactAgent({ llm, tools, checkpointer });
LOC code agent: ~1,800 LOC (termasuk tool wrapper, prompt template, state management).
Time-to-MVP: 6 hari.
Yang LangChain kasih:
- Pre-built agent loop (ReAct pattern)
- Memory abstraction (conversation state)
- Tool call retry / error handling baked-in
- Streaming dengan callback chain
Yang LangChain bikin pusing:
- Abstraction berlapis: error stack trace 15 frame dalam. Susah debug.
- Breaking change frequent: dalam 6 bulan saya migrate 3x karena API minor version bump.
- Output format kadang inconsistent: tool call sometimes wrap dalam
__arg, sometimes flat. Saya tambah defensive parsing. - Token usage tidak transparent: saya susah audit cost per conversation.
Latency v1 (LangChain)
Conversation turn (user message → agent response):
- P50: 3,4 detik
- P95: 7,8 detik
- P99: 18 detik (with retry on tool fail)
Component breakdown:
- LangChain orchestration overhead: ~280ms per turn
- Claude API call: 2,8-6 detik
- Tool execution: 100-500ms
LangChain overhead 280ms per turn × 6 turn/conv = 1,7 detik per conversation. Real.
Versi 2: Claude SDK direct
Tiga bulan kemudian saya rewrite. Stack: @anthropic-ai/sdk langsung, tool_use API native, state di Postgres.
async function runAgent(messages: Message[], userId: string) {
while (true) {
const response = await anthropic.messages.create({
model: 'claude-sonnet-4.7',
max_tokens: 4096,
tools: TOOL_DEFINITIONS,
messages,
});
if (response.stop_reason === 'end_turn') {
return response.content;
}
if (response.stop_reason === 'tool_use') {
const toolUse = response.content.find(c => c.type === 'tool_use');
const result = await executeTool(toolUse, userId);
messages.push({ role: 'assistant', content: response.content });
messages.push({ role: 'user', content: [{
type: 'tool_result',
tool_use_id: toolUse.id,
content: JSON.stringify(result)
}]});
}
}
}
LOC: ~520 LOC. Reduction 71%.
Time-to-rewrite: 4 hari.
Latency v2 (Claude SDK direct)
Conversation turn:
- P50: 2,2 detik
- P95: 4,8 detik
- P99: 9 detik
P50 turun 38%, P95 turun 38%. Source: no LangChain orchestration overhead.
Cost
Token usage per conversation rata-rata:
- LangChain v1: 8,400 token input + 1,200 token output (prompt template heavy)
- SDK direct v2: 4,200 token input + 1,150 token output (lean prompt)
Cost per conversation (Claude Sonnet 4.7 pricing):
- v1: 8,400 × $3/M + 1,200 × $15/M = $0,043
- v2: 4,200 × $3/M + 1,150 × $15/M = $0,030
Saving per conv: $0,013. Volume 800 conv/hari × 30 = 24,000 conv/bulan.
Monthly saving: $0,013 × 24,000 = $312/mo (~Rp 5jt/mo).
Plus prompt caching (Claude SDK direct support out-of-box, LangChain v1 saya pakai tidak): cache hit rate 68% di sistem prompt, additional saving ~$140/mo.
Total saving cost: ~$450/mo dari rewrite.
Yang break
-
State persistence: LangChain ada built-in checkpointer (Postgres adapter). Untuk SDK direct, saya tulis sendiri: serialize messages JSON ke
conversation_statetable. Effort 4 jam, jadi pattern reusable. -
Tool retry logic: LangChain ada retry default. Untuk SDK direct, saya tulis manual:
async function executeTool(toolUse, userId, attempt = 1) {
try {
return await tools[toolUse.name](toolUse.input, userId);
} catch (e) {
if (attempt < 3 && isRetriable(e)) {
await sleep(500 * attempt);
return executeTool(toolUse, userId, attempt + 1);
}
return { error: e.message };
}
}
-
Streaming UX: LangChain support streaming via callback. SDK direct saya pakai
anthropic.messages.stream(). Different API tapi works. Saya tulis adapter ke Next.js Server-Sent Events response. -
Observability: di LangChain saya pakai LangSmith ($39/mo). Di SDK direct saya log manual ke OpenObserve (self-hosted di Hetzner). Saving $39/mo + lebih privacy-friendly.
Yang LangChain tetap menang
- Multi-provider switching: ganti dari Claude ke OpenAI ke Gemini di config. SDK direct saya butuh adapter pattern manual.
- Pre-built integrations: ada wrapper untuk Pinecone, Qdrant, Confluence, dll. SDK direct saya implement sendiri.
- Community knowledge: lots of tutorial. SDK direct lebih sedikit example untuk pattern non-trivial.
Kalau project Anda multi-provider atau early prototyping: LangChain valid pilihan. Untuk production single-provider: SDK direct menang.
Debugging experience
Real story: di v1, agent kadang stuck di tool calling loop (infinite retry). Stack trace 15 frame dalam LangChain internal. Saya butuh 4 jam debug satu issue.
Di v2, agent loop saya tulis sendiri, ~50 LOC. Bug semacam itu kebetulan ada juga (off-by-one di max iteration counter), tapi debug ~20 menit karena code transparent.
Konsisten dengan pengalaman saya di pattern simpler debugging vs LangChain: less abstraction, more control.
Memory
LangChain v1 RSS process Bun: ~340MB stable. SDK direct v2 RSS process Bun: ~180MB stable.
LangChain dependency footprint besar (~85MB node_modules), SDK direct minimal (~12MB).
Verdict
Untuk production agent dengan Claude single-provider: SDK direct clear winner. Less LOC, faster, cheaper, more debuggable.
LangChain valid untuk: multi-provider orchestration, prototype eksploratoris, atau team yang butuh ekosistem integration luas tanpa effort wrapper.
Bukan magic — rewrite ke SDK direct butuh re-implement state management + retry + observability yang LangChain provide. Effort 4 hari, payback dalam 2 minggu dari saving cost + faster latency.
Pattern saya sekarang: prototype dengan LangChain (cepat eksplorasi), production rewrite ke SDK direct (kontrol + cost). Dua tools, satu workflow.
Ditulis oleh Reza Pradipta