LangGraph is a library for building stateful, multi-actor applications with LLMs using graphs.
from typing import TypedDict, List, Any
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain.tools import tool
# 1) Define state
class AgentState(TypedDict):
messages: List[Any]
docs: List[str]
answer: str
next_action: str
# 2) Define tools
@tool
def search_docs(query: str) -> list[str]:
"""Search your vector store or docs."""
return [f"Doc about {query} - 1",
f"Doc about {query} - 2"]
# 3) Nodes
llm = ChatOpenAI(model="gpt-4o", temperature=0)
def planner(state: AgentState) -> AgentState:
user_msg = state["messages"][-1].content
if "search" in user_msg.lower():
state["next_action"] = "search"
else:
state["next_action"] = "answer"
return state
def do_search(state: AgentState) -> AgentState:
query = state["messages"][-1].content
docs = search_docs.invoke({"query": query})
state["docs"] = docs
state["next_action"] = "answer"
return state
def generate_answer(state: AgentState) -> AgentState:
docs = "\n".join(state.get("docs", []))
prompt = (
"Use the following docs to answer the user.\n"
f"Docs:\n{docs}\n\n"
"Question: " + state["messages"][-1].content)
resp = llm.invoke([HumanMessage(content=prompt)])
state["answer"] = resp.content
return state
# 4) Build graph
graph = StateGraph(AgentState)
graph.add_node("planner", planner)
graph.add_node("search", do_search)
graph.add_node("answer", generate_answer)
graph.set_entry_point("planner")
def route(state: AgentState) -> str:
return state["next_action"]
graph.add_conditional_edges("planner", route,
{"search": "search", "answer": "answer"})
graph.add_edge("search", "answer")
graph.add_edge("answer", END)
app = graph.compile()
LangChain is a framework for building LLM applications by composing together components.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.memory import ConversationBufferMemory
from langchain.agents import create_openai_tools_agent, AgentExecutor
from langchain.tools import tool
# 1) LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 2) Tools
@tool
def get_weather(location: str) -> str:
"""Get current weather for a location."""
return f"Sunny, 28C in {location}"
@tool
def search_web(query: str) -> str:
"""Search the web and return a short summary."""
return f"Top result for {query}: ..."
tools = [get_weather, search_web]
# 3) Prompt
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant. "
"Use tools when needed."),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
# 4) Agent + executor
agent = create_openai_tools_agent(llm, tools, prompt)
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
)
executor = AgentExecutor(
agent=agent,
tools=tools,
memory=memory,
verbose=True,
)
# 5) Run
response = executor.invoke(
{"input": "What is the weather in Boston?"})
print(response["output"])
Use LangChain for rapid composition of LLM apps. Use LangGraph for complex, stateful, controllable workflows. Use PyRIT and promptfoo to red-team and continuously harden your AI applications.
Details →