DEV Community

Atlas Whoff
Atlas Whoff

Posted on

LangChain vs Direct SDK: When to Use Each for Production AI Applications

LangChain has become the default framework for building LLM applications. But it's also one of the most over-engineered tools in the ecosystem — layers of abstraction that hide what's happening and make debugging painful. Here's how to evaluate when to use it versus building directly.

What LangChain Actually Provides

LangChain solves real problems:

  • Chain composition: Link LLM calls, tool calls, and transforms
  • Memory: Conversation history management
  • Retrieval: Vector store integration for RAG
  • Agents: Loop-based tool use with multiple LLM providers
  • Streaming: Unified streaming interface

The question is whether you need the abstraction or whether it's adding cost.

The Direct API Approach

For most applications, the Anthropic SDK is sufficient:

import Anthropic from '@anthropic-ai/sdk'

const client = new Anthropic()

// Simple chat
const response = await client.messages.create({
  model: 'claude-sonnet-4-6',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello' }],
})

// With tools
const toolResponse = await client.messages.create({
  model: 'claude-sonnet-4-6',
  tools: myTools,
  messages,
})

// Streaming
const stream = client.messages.stream({ model, messages })
for await (const event of stream) { /* ... */ }
Enter fullscreen mode Exit fullscreen mode

150 lines of direct SDK code is often clearer than 20 lines of LangChain that hides what's happening.

When LangChain Makes Sense

Multi-provider apps: If you genuinely need to swap between OpenAI, Anthropic, and Mistral with one interface:

import { ChatAnthropic } from '@langchain/anthropic'
import { ChatOpenAI } from '@langchain/openai'

// Swap providers without changing downstream code
const model = process.env.AI_PROVIDER === 'openai'
  ? new ChatOpenAI({ model: 'gpt-4o' })
  : new ChatAnthropic({ model: 'claude-sonnet-4-6' })
Enter fullscreen mode Exit fullscreen mode

Complex RAG pipelines: LangChain's retrieval chains handle chunking, embedding, and context injection:

import { createRetrievalChain } from 'langchain/chains/retrieval'
import { createStuffDocumentsChain } from 'langchain/chains/combine_documents'

const questionAnswerChain = await createStuffDocumentsChain({ llm, prompt })
const ragChain = await createRetrievalChain({
  retriever: vectorStore.asRetriever(),
  combineDocsChain: questionAnswerChain,
})

const result = await ragChain.invoke({ input: question })
Enter fullscreen mode Exit fullscreen mode

When to Build Direct

Build directly with the provider SDK when:

  • Single provider (90% of apps)
  • Custom tool execution logic
  • You need to inspect and debug every step
  • Performance is critical (each abstraction layer adds latency)
  • The team needs to understand the code

LangSmith for Observability

LangChain's observability platform works regardless of whether you use LangChain:

import { Client } from 'langsmith'
import { traceable } from 'langsmith/traceable'

// Wrap any function to trace it
const tracedAnalyze = traceable(
  async (text: string) => {
    return anthropic.messages.create({ /* ... */ })
  },
  { name: 'analyze-text', project_name: 'my-app' }
)
Enter fullscreen mode Exit fullscreen mode

LangSmith traces every LLM call, shows token usage, latency, and errors. Worth using even if you skip LangChain.

The Honest Assessment

LangChain is best used as a starting point for exploration, not a production dependency:

  • Prototype fast with LangChain abstractions
  • Replace with direct SDK calls where you hit friction
  • Keep LangSmith for observability throughout

Most production AI applications I've seen eventually strip out LangChain and go direct once the team understands the patterns.


The AI SaaS Starter at whoffagents.com uses the Anthropic SDK directly — no LangChain abstraction — with a clean streaming chat hook, tool execution loop, and conversation persistence. $99 one-time.

Top comments (0)