← Code Recipes
Frameworks & SDKs

LangChain Free code examples in Python and JavaScript

The most widely used orchestration library, and LangGraph for stateful agents.

C# Python Java JavaScript

WHAT THIS PAGE COVERS

LangGraph, because a graph is the honest shape of a real agent.

Model gpt-5.4-mini
Package langchain
Checked

Model ids change. If a sample returns a 404 on the model, that is the first thing to check against the official docs.

Install

The provider is an extra, not a separate top-level package: langchain[openai] rather than langchain plus langchain-openai in the common case.

pip install "langchain[openai]" langgraph

export OPENAI_API_KEY="sk-your-key"   # macOS / Linux
setx OPENAI_API_KEY "sk-your-key"     # Windows, then open a new shell
An agent in eight lines

create_agent from langchain.agents. A plain function is a tool — the docstring is the description the model reads, and the type hints are the schema.

from langchain.agents import create_agent

def get_stock(code: str) -> str:
    """Get the current stock level for a single product code."""
    return f"{code}: 42 units"

agent = create_agent(
    model="gpt-5.4-mini",
    tools=[get_stock],
    system_prompt="You are a concise warehouse assistant.",
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "How many X-17 do we have?"}]}
)

print(result["messages"][-1].content_blocks)
Streaming the steps, not just the answer

stream() with mode 'updates' shows each node as it finishes, which is how you find out the agent called the wrong tool rather than staring at a slow final answer.

for chunk in agent.stream(
    {"messages": [{"role": "user", "content": "How many X-17 do we have?"}]},
    stream_mode="updates",
):
    for node, update in chunk.items():
        # node is "model" or "tools" — watching this is how you debug
        # an agent that answers confidently without calling anything.
        print(node, update)
When the loop is not enough, draw the graph

A GRAPH IS THE HONEST SHAPE OF A REAL AGENT. Branches, retries and human approval are edges and nodes; expressed as prompt instructions they are a state machine you cannot see, test or resume.

from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class Review(TypedDict):
    code: str
    findings: list[str]
    approved: bool

def analyse(state: Review) -> Review:
    return {**state, "findings": ["unbounded loop at line 42"]}

def needs_human(state: Review) -> str:
    # A real edge, not a sentence in a prompt hoping to be obeyed.
    return "approve" if state["findings"] else END

def approve(state: Review) -> Review:
    return {**state, "approved": True}

builder = StateGraph(Review)
builder.add_node("analyse", analyse)
builder.add_node("approve", approve)
builder.add_edge(START, "analyse")
builder.add_conditional_edges("analyse", needs_human)
builder.add_edge("approve", END)

graph = builder.compile()
Pausing for a human, and resuming later

A checkpointer is what makes the graph durable. interrupt_before stops at a node, the state is persisted against a thread id, and a later process resumes it — which is the whole argument for a graph over a loop.

from langgraph.checkpoint.memory import InMemorySaver

# In production this is Postgres or Redis; the interface is the same.
graph = builder.compile(
    checkpointer=InMemorySaver(),
    interrupt_before=["approve"],
)

config = {"configurable": {"thread_id": "review-118"}}

graph.invoke({"code": source, "findings": [], "approved": False}, config)

# ... minutes or days later, in a different process ...
state = graph.get_state(config)
print("waiting at:", state.next)

# Passing None means "carry on from where you stopped".
graph.invoke(None, config)
Install

createAgent and tool are both named exports of `langchain` itself. The provider package is separate, and zod describes the tool arguments.

npm install langchain zod @langchain/openai @langchain/langgraph

export OPENAI_API_KEY="sk-your-key"
An agent in a dozen lines

tool() pairs the function with a zod schema — that schema is what the model sees, so describe() on each field is prompt text rather than documentation.

import { createAgent, tool } from "langchain";
import * as z from "zod";

const getStock = tool(
  (input) => `${input.code}: 42 units`,
  {
    name: "get_stock",
    description: "Get the current stock level for a single product code.",
    schema: z.object({
      code: z.string().describe("The product code, e.g. X-17"),
    }),
  },
);

const agent = createAgent({
  model: "gpt-5.4-mini",
  tools: [getStock],
});

console.log(
  await agent.invoke({
    messages: [{ role: "user", content: "How many X-17 do we have?" }],
  }),
);
Streaming the steps

streamMode 'updates' emits each node as it completes. Watching which tool fired is how you catch an agent that answers from memory instead of calling anything.

const stream = await agent.stream(
  { messages: [{ role: "user", content: "How many X-17 do we have?" }] },
  { streamMode: "updates" },
);

for await (const chunk of stream) {
  for (const [node, update] of Object.entries(chunk)) {
    console.log(node, JSON.stringify(update).slice(0, 200));
  }
}
When the loop is not enough, draw the graph

Branches and approvals belong in edges. Written as instructions in a prompt they are a state machine with no type, no test and no way to resume after a restart.

import { StateGraph, START, END, Annotation } from "@langchain/langgraph";

const Review = Annotation.Root({
  code: Annotation(),
  findings: Annotation({ default: () => [] }),
  approved: Annotation({ default: () => false }),
});

const builder = new StateGraph(Review)
  .addNode("analyse", () => ({
    findings: ["unbounded loop at line 42"],
  }))
  .addNode("approve", () => ({ approved: true }))
  .addEdge(START, "analyse")
  .addConditionalEdges("analyse", (state) =>
    state.findings.length ? "approve" : END,
  )
  .addEdge("approve", END);

const graph = builder.compile();
Pausing for a human, and resuming later

A checkpointer plus a thread id makes the run durable. The process that resumes it does not have to be the one that started it — that is what a graph buys over a loop in memory.

import { MemorySaver } from "@langchain/langgraph";

const durable = builder.compile({
  checkpointer: new MemorySaver(),      // Postgres or Redis in production
  interruptBefore: ["approve"],
});

const config = { configurable: { thread_id: "review-118" } };

await durable.invoke({ code: source }, config);

// ... later, possibly in another process ...
const state = await durable.getState(config);
console.log("waiting at:", state.next);

// null means "carry on from where you stopped".
await durable.invoke(null, config);

QUESTIONS

Which languages are the LangChain examples in?

Python and JavaScript. Every sample runs as pasted and reads its credentials from an environment variable — no key is ever written into the code.

Which package do I install for LangChain?

The samples use langchain. The install step on each language tab gives the exact command.

Which LangChain model do these examples use?

gpt-5.4-mini, checked against the official documentation on 26 September 2026. Model ids change often; if a call returns a model-not-found error, check the current list in the official docs.

Where is the official LangChain documentation?

https://python.langchain.com/docs/introduction/ — it is linked at the bottom of this page, and it is the authority whenever it disagrees with a sample here.

ALSO IN FRAMEWORKS & SDKS

The authority

Official LangChain documentation

Model names, pricing and rate limits change faster than any page here can. When this page and the official docs disagree, the official docs are right.

Read the docs ↗

https://python.langchain.com/docs/introduction/

New drops, every week

Free tools & Claude templates, landing regularly.

We keep shipping new free tools, code recipes and Claude Code templates. Follow @freeyantra on Instagram or join the newsletter so you never miss one.

Follow @freeyantra

or get them by email

Double opt-in. Unsubscribe any time. Privacy