Tutorials Logic, IN info@tutorialslogic.com

LangGraph Installation and Project Setup: Python Environment, Packages, and First Run

LangGraph Installation and Project Setup

The installation step looks simple, but it shapes every later lesson. A rushed setup usually produces the worst kind of beginner frustration: import errors, mismatched package versions, and examples that fail before the graph logic even starts.

A clean LangGraph environment has three jobs. It must isolate dependencies, keep provider packages explicit, and make it obvious where graph code, tool code, prompts, and configuration belong as the project grows.

The goal of this page is not just to get `pip install` working. It is to give you a setup you can still live with when the tutorial becomes a real codebase.

Choose a Development Baseline

Use a dedicated virtual environment for every LangGraph project. Graph applications often combine model integrations, database adapters, checkpoint packages, tracing clients, and testing libraries. Sharing those across unrelated projects creates version drift quickly.

Keep your Python version modern and stable. When a tutorial mixes async execution, typing, and provider SDKs, recent Python versions reduce friction and make example code cleaner.

  • Create a project folder before installing packages.
  • Use `venv`, `uv`, Poetry, or another environment manager consistently.
  • Record package choices in `requirements.txt` or `pyproject.toml` early.

Install the Graph Runtime First

The core package gives you `StateGraph`, routing primitives, and graph execution. Add provider-specific model packages only after the base graph import works. This isolates setup failures to one layer at a time.

Official docs now separate graph runtime concerns from provider integrations. That is healthy for production too: your graph architecture should not be tightly coupled to one model vendor.

  • Install the graph package first.
  • Then add only the model integrations you actually use.
  • Add checkpoint backends deliberately, not by default.

A Durable Project Layout

Even in a tutorial repo, separate graph definitions from node implementations. Nodes are easier to unit test when they are plain functions in their own module. Tools, database clients, and prompts should also live outside the graph wiring file.

The graph file should read like an architecture diagram: state definitions, node registration, edge definitions, compilation. When business logic and graph wiring mix heavily, the graph stops being readable.

  • app/state.py for schemas and reducers
  • app/nodes/ for task-focused node functions
  • app/tools/ for external actions
  • app/graphs/ for graph assembly and compile logic
  • tests/ for node, route, and end-to-end graph checks

Verification Before Building Anything Interesting

Do a thin smoke test before you start writing real workflows. Import the graph package, compile a one-node graph, and invoke it with a tiny state object. That test catches the majority of early environment problems.

If you plan to use persistence, verify the checkpointer in isolation too. Storage-related issues often appear only after the graph compiles successfully, so treat checkpoint setup as a separate acceptance check.

  • Import packages successfully.
  • Compile a graph with START and END.
  • Run one invocation and inspect the returned state.
  • Only then add provider SDKs, tools, or persistence.

Setup Choices That Age Well in Production

Avoid burying secrets in node files or notebooks. Use environment variables or a settings layer from day one. LangGraph systems often evolve into services, and the cost of unwinding hard-coded credentials later is not worth the convenience.

The same goes for logging. Introduce structured logs and a shared configuration module early, even in small tutorial projects. Agent workflows are much easier to grow when the plumbing starts clean.

  • Keep API keys outside source files.
  • Use separate config for local, test, and production environments.
  • Pin dependencies before shipping examples to other teammates.

Setup for Reliable Learning and Real Projects

A good LangGraph setup should make experiments reproducible. Use a dedicated virtual environment, pin important package versions for projects, and keep model credentials, tracing configuration, and checkpoint settings outside source code. This prevents confusing bugs where a graph works on one machine because of hidden local state.

Start with the smallest possible graph after installation: one state schema, one node, one edge from START, and one edge to END. This proves that the environment, imports, and invocation path work before you add models, tools, persistence, or streaming. If the first graph is complicated, setup errors become harder to isolate.

Add project structure early. Keep graph construction, node functions, state definitions, tool wrappers, tests, and configuration in separate modules once the example grows. LangGraph applications become easier to maintain when the graph shape is not tangled with every backend implementation detail.

For serious work, configure tracing and checkpointing before the graph becomes complex. You do not need production infrastructure on day one, but you do need the habit of seeing state transitions, node outputs, and errors. Debugging without traces is possible for toy graphs and painful for real ones.

  • Use an isolated environment and explicit configuration.
  • Verify installation with the smallest graph first.
  • Separate state, nodes, graph assembly, tools, and tests as the project grows.
  • Introduce tracing and checkpoint habits early.

Expert Practice Lab

Create a clean starter project that includes a virtual environment, pinned dependencies, a minimal graph, one test, and a simple tracing configuration. This becomes a reusable baseline for future LangGraph experiments.

Then intentionally break one piece: remove a dependency, change a state field, or misconfigure an environment variable. A good setup should make the failure obvious. Learning how failure looks early makes larger projects much less intimidating.

  • Keep a reproducible starter project.
  • Add one test before adding complexity.
  • Practice diagnosing setup failures.

Final Expert Note

A clean setup also helps collaboration: another developer should be able to install dependencies, run the smallest graph, and execute tests without asking for hidden steps.

Review Margin

For deeper learning, pair the concept with a tiny graph and a saved trace. Seeing state before and after each node makes the lesson concrete and gives learners a reliable debugging habit from the beginning.

Beginner Example: Create and Verify the Environment

This setup sequence gives you a minimal but reliable local environment.

Beginner Example: Create and Verify the Environment
# Windows PowerShell
py -3.11 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install langgraph

python - <<'PYCODE'
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict

class State(TypedDict):
    text: str

def echo(state: State) -> dict:
    return {"text": state["text"]}

builder = StateGraph(State)
builder.add_node("echo", echo)
builder.add_edge(START, "echo")
builder.add_edge("echo", END)
graph = builder.compile()
print(graph.invoke({"text": "setup works"}))
PYCODE
  • Upgrade pip first to reduce installation noise.
  • Compile a graph immediately after installation to prove the runtime works.
  • Use a tiny smoke test before layering in provider packages.

Intermediate Example: Add a Checkpointer for Local Development

Official docs show `InMemorySaver` for development and testing. It lets you verify persistence-related wiring without external infrastructure.

Intermediate Example: Add a Checkpointer for Local Development
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver

class State(TypedDict):
    count: int

def bump(state: State) -> dict:
    return {"count": state["count"] + 1}

builder = StateGraph(State)
builder.add_node("bump", bump)
builder.add_edge(START, "bump")
builder.add_edge("bump", END)

checkpointer = InMemorySaver()
graph = builder.compile(checkpointer=checkpointer)

config = {"configurable": {"thread_id": "demo-thread"}}
print(graph.invoke({"count": 0}, config=config))
  • Use `InMemorySaver` for tests and local exploration, not production durability.
  • A `thread_id` identifies which persisted run state should be used.
  • This prepares you for interrupts, memory, and replay later.

Advanced Example: A Scalable Project Skeleton

This file layout keeps graph assembly, nodes, tools, and tests separate so the tutorial code can grow into a service.

Advanced Example: A Scalable Project Skeleton
langgraph_app/
|-- pyproject.toml
|-- .env.example
|-- app/
|   |-- settings.py
|   |-- state.py
|   |-- graphs/
|   |   `-- support_graph.py
|   |-- nodes/
|   |   |-- classify.py
|   |   |-- retrieve.py
|   |   `-- draft.py
|   `-- tools/
|       `-- order_lookup.py
`-- tests/
    |-- test_nodes.py
    |-- test_routes.py
    `-- test_graph_runs.py
  • Keep graph assembly declarative.
  • Make nodes importable and testable in isolation.
  • Separate operational config from execution logic.
Key Takeaways
  • Use isolated environments per project.
  • Verify imports and one graph invocation before writing larger examples.
  • Add provider and checkpoint packages only when you need them.
  • Separate graph wiring from business logic files.
Common Mistakes to Avoid
Installing many optional packages before the base graph import works.
Mixing notebook experiments and production code in the same environment.
Treating checkpoint storage as an afterthought instead of part of setup.

Practice Tasks

  • Create a fresh virtual environment and run the one-node smoke test.
  • Add a second smoke test that compiles a graph with a local checkpointer.
  • Sketch a project folder layout for a future support-agent tutorial.

Frequently Asked Questions

Use whichever helps you learn fastest, but move into a normal project structure as soon as the workflow has more than one or two nodes.

No. Use in-memory persistence for local learning, then introduce a durable backend when you need pause-resume or shared services.

A tiny graph compiles and returns state successfully. Everything else builds on that proof.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.