Claude API Integration with LangChain Framework
Integrating the Claude API with LangChain means wiring Anthropic's models into LangChain's chain, agent, and tool abstractions so you can build retrieval pipelines, multi-step agents, and structured workflows without hand-rolling the request/response logic yourself. LangChain handles prompt templating, memory, tool calling, and output parsing; Claude provides the model. The integration itself is small — a chat model wrapper and an API key — but getting it production-ready (rate limits, streaming, multiple team members, cost tracking) takes a bit more planning.
This guide walks through the actual code for connecting Claude to LangChain, how to use it inside chains and agents with tool calling, and what to consider once you move past a prototype and need a stable endpoint multiple developers can share.
Why use LangChain with Claude at all
Claude's native API is already simple to call directly. LangChain adds value when you need:
- Composable chains — prompt → model → parser → next step, without rewriting plumbing for every pipeline.
- Agentic tool use — letting Claude decide when to call a function, search a database, or hit another API, using LangChain's tool-calling interface.
- Memory management — conversation history, summarization buffers, or vector-store-backed retrieval across turns.
- Swappable backends — if you later test Claude against another model, you change one line instead of rewriting your application logic.
If you're just sending single prompts and parsing text responses, you may not need LangChain at all — a direct call to Claude's Messages API is simpler. LangChain earns its place once you have multi-step logic or tool orchestration.
Setting up the integration
Install the LangChain Anthropic package:
npm install @langchain/anthropic @langchain/core
Set your API key as an environment variable, then instantiate the chat model:
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
model: "claude-sonnet-4-5",
temperature: 0.3,
});
const response = await model.invoke("Summarize the key risks in this contract clause.");
console.log(response.content);
That's the entire baseline integration. Everything else — chains, memory, tools — builds on this model object.
Building a basic chain
LangChain chains combine a prompt template with the model and an output parser:
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
const prompt = ChatPromptTemplate.fromMessages([
["system", "You are a precise technical reviewer."],
["human", "Review this code snippet for bugs:\n\n{code}"],
]);
const chain = prompt.pipe(model).pipe(new StringOutputParser());
const result = await chain.invoke({ code: "function add(a,b){ return a-b }" });
console.log(result);
This pattern — prompt, model, parser, piped together — is the backbone of almost every LangChain application, regardless of which LLM sits in the middle.
Tool calling with Claude in LangChain
Claude supports native tool use, and LangChain exposes it through .bindTools():
import { z } from "zod";
import { tool } from "@langchain/core/tools";
const getWeather = tool(
async ({ city }) => `Weather in ${city}: 18°C, light rain.`,
{
name: "get_weather",
description: "Get current weather for a city",
schema: z.object({ city: z.string() }),
}
);
const modelWithTools = model.bindTools([getWeather]);
const result = await modelWithTools.invoke("What's the weather in Lisbon?");
console.log(result.tool_calls);
LangChain translates the tool schema into the format Claude expects and parses the structured tool call back into JavaScript objects. If you're calling Claude's tool-use feature directly without LangChain, the same concept applies at the API level — see /docs/tools for the raw request/response shape.
Memory and multi-turn context
For conversational agents, wrap the model in a MessagesPlaceholder and manage history manually, or use LangChain's memory classes to persist state across turns. Claude doesn't maintain server-side session state, so whichever approach you choose, the full conversation history has to be sent with every request — this is true whether you call Claude directly or through LangChain.
Moving from prototype to production
A LangChain prototype calling the Anthropic API directly works fine for one developer testing locally. It gets harder once you have:
- Multiple team members who each need their own key, with no easy way to see who's spending what.
- No built-in way to track token usage or cost per project or per user.
- Rate limit and retry logic you have to write yourself for every service that calls Claude.
This is where SubToAPI fits into a LangChain setup. Instead of pointing ChatAnthropic at raw Anthropic credentials shared across your team, you generate scoped sub_live_... keys per project or per developer from one dashboard, with streaming, tool use, and usage metadata handled the same way. Because the request and response format mirrors Claude's Messages API, swapping the base URL and key in your LangChain config is usually the only change needed:
const model = new ChatAnthropic({
apiKey: process.env.SUBTOAPI_KEY,
model: "claude-sonnet-4-5",
clientOptions: {
baseURL: "https://api.subtoapi.app/v1",
},
});
That gives you per-key usage tracking and team seats without touching the rest of your LangChain chains, agents, or tool definitions. If you're building something that multiple engineers or services will call against Claude, it's worth checking /docs/quickstart before you wire credentials directly into every microservice.
Review /docs/messages and /docs/streaming if your LangChain app needs streamed tokens — the streaming behavior maps directly onto LangChain's .stream() method on the chat model.
Common pitfalls
- Forgetting system prompts count toward context — LangChain's prompt templates make it easy to accidentally duplicate system instructions across chain steps.
- Not handling tool-call loops — if Claude requests a tool, you need to actually execute it and feed the result back; LangChain won't do this automatically unless you use an agent executor.
- Sharing one API key across a team — this works until you need to know which feature or developer is driving cost or hitting rate limits. Separate keys per service, via
/pricing-tier access or a managed layer like SubToAPI, solve this early rather than after a billing surprise.
Questions
Does LangChain require a special Claude-specific setup? No. You install @langchain/anthropic, provide an API key, and instantiate ChatAnthropic like any other chat model. Chains, agents, and tools work the same way regardless of the underlying LLM provider.
Can I use Claude's tool-use feature inside a LangChain agent? Yes. Bind tools with .bindTools() or use LangChain's agent executor, and Claude will return structured tool-call requests that LangChain parses automatically.
Do I need SubToAPI if I'm just prototyping with LangChain? Not necessarily — a direct Anthropic key works fine for local development. It becomes useful once multiple people or services need separate, trackable keys without managing billing and access manually; see /signup to try it.