Skip to main content
This lesson demonstrates a minimal, production-accurate example of using LangGraph to orchestrate a single LLM call via the OpenAI Responses API. The objective is to show:
  • LangGraph’s execution model and how a typed state flows through a node.
  • How nodes return partial updates that are merged into a global state.
  • How to wire a real model call cleanly and composably.
This example is intentionally minimal so you can extend it later with routing, tools, memory, retries, or observability.
Ensure you have an OpenAI API key and the required packages installed. The examples below use the modern OpenAI Responses API via the OpenAI Python client and LangGraph.

Quick setup

Install the dependencies (uncomment if running in a fresh environment):
Set your environment variable:
  • OPENAI_API_KEY — required
  • OPENAI_MODEL — optional (defaults to gpt-4 in the examples below)
You can set OPENAI_API_KEY in your shell or let the script prompt for it at runtime.
Protect your OPENAI_API_KEY. Using LLMs incurs cost — monitor usage and model selection (OPENAI_MODEL) to control billing.

Initialize the client and constants

The example below creates an OpenAI client (reading OPENAI_API_KEY from the environment) and sets a default MODEL. The helper will prompt for the key if it is not already set.

Define a typed state

LangGraph operates on structured, typed states instead of raw strings. Define the state shape with TypedDict. This example uses a two-field state: question (input) and answer (output).
Using a typed state makes data flow explicit, enables validation, and improves readability when graphs grow larger.

Node: call the Responses API

Each node receives the current typed state and returns a partial update (a dictionary with only the fields it produced). Here is a single node, answer_question, which calls the OpenAI Responses API using the question and returns only the answer field.
Note: nodes should return partial state updates rather than replacing the entire state. LangGraph merges these updates into the global state — this composability enables building larger orchestrations from small, focused nodes.

Build the StateGraph and set the entry point

Register the node in a StateGraph, set the entry point, then compile the graph into a callable app.

Invoke the graph

Invoke the compiled graph with an initial state that provides the question. LangGraph runs the entry node, merges the returned partial update, and returns the final state that includes both the original input and the generated answer.
Example final state:

Why this pattern matters

  • Typed state: makes data flow explicit and type-safe across nodes.
  • Nodes return partial updates: enables small, composable units of work that can be merged by the orchestrator.
  • Graph defines orchestration: lets you add routing, tool-calling, validation, retries, or memory without changing node internals.
This pattern scales cleanly to agentic workflows. You can add routing nodes, tool-call nodes, validation or critique steps, and memory writes while preserving the same execution model.

Next steps and extensions

From here you can extend the basic graph with:
  • Branching and routing (conditional node execution)
  • Tool integration (external APIs, search, databases)
  • Retries and error handling
  • Observability and metrics for each node
  • Persistent memory for multi-step dialogs
Each extension is implemented by adding nodes or orchestration logic — you do not need to rewrite core node implementations.

Watch Video

Practice Lab