LangGraph Tutorial (Python): deploying to AWS Lambda for advanced developers

By Cyprian AaronsUpdated 2026-04-21
langgraphdeploying-to-aws-lambda-for-advanced-developerspython

This tutorial shows how to package a LangGraph Python app as an AWS Lambda handler and expose it through API Gateway. You need this when you want your agent workflow to run serverlessly with predictable scaling, low idle cost, and a clean HTTP interface.

What You'll Need

  • Python 3.11
  • AWS account with permissions for:
    • Lambda
    • IAM roles
    • CloudWatch Logs
    • API Gateway
  • pip and venv
  • LangGraph and LangChain packages:
    • langgraph
    • langchain-core
    • langchain-openai
  • OpenAI API key set as an environment variable: OPENAI_API_KEY
  • AWS CLI configured locally
  • A deployment package strategy:
    • zip-based deployment for this tutorial
  • Basic familiarity with:
    • LangGraph state graphs
    • AWS Lambda handlers

Step-by-Step

  1. Start by building a minimal LangGraph workflow that can run inside Lambda without extra framework glue. Keep the graph stateless across invocations; Lambda containers may be reused, but you should never depend on that for correctness.
from typing import TypedDict

from langgraph.graph import StateGraph, START, END


class GraphState(TypedDict):
    message: str


def uppercase_node(state: GraphState) -> dict:
    return {"message": state["message"].upper()}


builder = StateGraph(GraphState)
builder.add_node("uppercase", uppercase_node)
builder.add_edge(START, "uppercase")
builder.add_edge("uppercase", END)

graph = builder.compile()
  1. Add a Lambda handler that accepts API Gateway events, extracts input, runs the graph, and returns JSON. This keeps the Lambda boundary simple and makes local testing easy because the handler is just a pure function around your graph.
import json

def lambda_handler(event, context):
    body = event.get("body") or "{}"
    payload = json.loads(body)

    user_message = payload.get("message", "hello")
    result = graph.invoke({"message": user_message})

    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps(result),
    }
  1. If you want the graph to call an LLM, wire in a real model node using langchain-openai. In production, keep model creation at module scope so cold starts pay the initialization cost once per container, not once per request.
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage


llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)


class LLMState(TypedDict):
    message: str


def llm_node(state: LLMState) -> dict:
    response = llm.invoke([HumanMessage(content=state["message"])])
    return {"message": response.content}


llm_builder = StateGraph(LLMState)
llm_builder.add_node("llm", llm_node)
llm_builder.add_edge(START, "llm")
llm_builder.add_edge("llm", END)

llm_graph = llm_builder.compile()
  1. Package the app for Lambda with dependencies installed into a deployment folder. Use the same Python version locally that you will use in Lambda, otherwise compiled wheels can break at runtime.
mkdir -p lambda_app
cd lambda_app

python3.11 -m venv .venv
source .venv/bin/activate

pip install --upgrade pip
pip install langgraph langchain-core langchain-openai

cat > app.py <<'PY'
import json
from typing import TypedDict

from langgraph.graph import StateGraph, START, END


class GraphState(TypedDict):
    message: str


def uppercase_node(state: GraphState) -> dict:
    return {"message": state["message"].upper()}


builder = StateGraph(GraphState)
builder.add_node("uppercase", uppercase_node)
builder.add_edge(START, "uppercase")
builder.add_edge("uppercase", END)
graph = builder.compile()


def lambda_handler(event, context):
    body = event.get("body") or "{}"
    payload = json.loads(body)
    result = graph.invoke({"message": payload.get("message", "hello")})
    return {"statusCode": 200, "headers": {"Content-Type": "application/json"}, "body": json.dumps(result)}
PY

zip -r function.zip app.py .venv/lib/python3.11/site-packages/*
  1. Create the Lambda function and point it at your handler. If you are using the OpenAI-backed graph instead of the uppercase example, add OPENAI_API_KEY as an environment variable in Lambda before testing.
aws iam create-role \
  --role-name langgraph-lambda-role \
  --assume-role-policy-document file://trust-policy.json

aws iam attach-role-policy \
  --role-name langgraph-lambda-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

aws lambda create-function \
  --function-name langgraph-tutorial \
  --runtime python3.11 \
  --handler app.lambda_handler \
  --role arn:aws:iam::<YOUR_ACCOUNT_ID>:role/langgraph-lambda-role \
  --zip-file fileb://function.zip \
  --timeout 30 \
  --memory-size 512
  1. Put API Gateway in front of the function so you can call it over HTTP. For advanced use cases, this is where you later add auth, throttling, request validation, and structured observability.
aws lambda add-permission \
  --function-name langgraph-tutorial \
  --statement-id apigw-invoke \
  --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com

aws apigatewayv2 create-api \
  --name langgraph-api \
  --protocol-type HTTP

# Connect route/integration in the console or via CLI,
# then deploy to a stage and test with POST /invoke.

Testing It

Send a POST request with JSON like {"message":"hello"} to your API Gateway endpoint. If you used the uppercase graph, you should get back {"message":"HELLO"}.

Check CloudWatch Logs for handler output and runtime errors if the request fails. For LLM-backed graphs, confirm that OPENAI_API_KEY is set on the function and that outbound internet access is allowed through your chosen network setup.

If cold starts are too slow, reduce dependency size and keep model/client initialization at module scope. If you need stricter latency bounds, move heavier orchestration logic out of the request path and keep each invocation to one short graph execution.

Next Steps

  • Add structured state models with Pydantic so your graph inputs and outputs are validated before execution.
  • Split routing logic into multiple nodes and conditional edges for real agent workflows.
  • Add tracing with LangSmith so you can inspect node-level latency and failures in production.

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides