Buyer's guide
Best sales agents for marketing teams, and what to check
Apollo suits teams starting free, VoiceDrop suits voicemail campaigns, and PipeLime suits hands-off email and LinkedIn prospecting.
Tutorial Agent tools and integrations
A step-by-step LangGraph tutorial on the stable v1.0 API: build a working ReAct agent with state, nodes, edges and checkpointing.

You searched for a LangGraph tutorial and found ten articles. Nine of them use set_entry_point(), a function deprecated two years ago. If you’ve tried following those guides and hit import errors or broken behavior, that’s why.
This tutorial uses the stable LangGraph v1.0 API throughout. Every code block runs. We’ll go from a blank Python file to a working ReAct agent with tool calling and persistent memory, using the patterns that actually work today.
LangGraph is an open-source Python library for building stateful AI agent workflows as directed graphs. Developed by LangChain Inc. and reaching stable v1.0 in October 2025, LangGraph models agent execution as nodes (computation steps) connected by edges (control flow) sharing a common State object. The LangGraph GitHub repository has over 42,600 stars. Many LangGraph tutorials still in circulation use deprecated v0.1 API patterns, including set_entry_point() and pre-MessagesState TypedDict definitions, instead of the v1.0 canonical patterns this one uses throughout.
That’s not a minor inconvenience. ChatGPT reached 900 million weekly active users in February 2026, and AI assistants are an increasingly common way developers find tutorials like this one. When the answers those platforms serve are based on deprecated patterns, every developer who follows them hits the same broken imports.
Companies including Replit, Klarna, LinkedIn and Uber adopted the framework in early production agent workflows, per Techstrong.ai’s coverage of the LangGraph 0.3 release.
If you’re still deciding whether LangGraph suits your project, our guide on how to choose an AI agent framework covers the decision criteria. If you’ve already made the call, keep reading.
TL;DR: This tutorial uses LangGraph v1.0 (stable, October 2025), all code is tested and current. Build a working ReAct agent with
StateGraph,MessagesState, andcreate_react_agent.
LangGraph in Python uses StateGraph to define agent workflows. Install with pip install langgraph langgraph-prebuilt langchain-openai. Import StateGraph, START, END from langgraph.graph. Define your state as a TypedDict, add nodes as Python functions with add_node(), connect them with add_edge(), then call compile(). Invoke the finished graph with graph.invoke({'messages': [...]}).
LangGraph 1.0 requires Python 3.10 or higher, support for 3.8 and 3.9 was dropped in the 1.x major release. Run the following to install everything you need for this tutorial:
pip install langgraph langgraph-prebuilt langchain-openai langchain-core python-dotenv
Create a .env file in your project root with your API key. LangGraph is model-agnostic, it works with Anthropic, Google Gemini, Groq, and any provider with a LangChain-compatible wrapper, but this tutorial uses OpenAI for simplicity:
OPENAI_API_KEY=your-key-here
Load it at the top of your script:
from dotenv import load_dotenv
load_dotenv()
That’s the complete setup. No additional services, no configuration files, no dependencies beyond what’s listed. The LangChain documentation describes LangGraph as “very low-level, and focused entirely on agent orchestration”, which is why getting the imports right from the start matters. The library executes exactly what you define, nothing more.
Every LangGraph script you write will start with some version of these three lines. They replace the deprecated patterns you’ll see in most tutorials:
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import MessagesState
from langgraph.prebuilt import create_react_agent
START and END are sentinel nodes built into LangGraph that represent the entry and exit points of your graph. Any graph that uses set_entry_point() or set_finish_point() is using the old v0.1 API.
The table below maps the most common deprecated patterns to their current equivalents.
| Old code (v0.1) | Current code (v1.0) | Why it changed |
|---|---|---|
set_entry_point('node') |
add_edge(START, 'node') |
START/END sentinels make graph topology explicit and composable |
set_finish_point('node') |
add_edge('node', END) |
Same reason; finish point was redundant with a terminal edge |
| Manual TypedDict with messages list | MessagesState from langgraph.graph.message |
Prebuilt state includes the add_messages reducer by default |
from langgraph.prebuilt import ToolExecutor |
from langgraph.prebuilt import ToolNode |
ToolNode replaced ToolExecutor in v0.2; ToolExecutor is removed in v1.0 |
In LangGraph, nodes are Python functions that perform computation, LLM calls, tool invocations, or data transformations. Edges define the execution order between nodes. Simple edges use add_edge('node_a', 'node_b'). Conditional edges use add_conditional_edges() to route based on current state, enabling branching and loops in agent workflows.
A node is any Python function that takes the current graph state and returns a dictionary of updates. The simplest possible node, a direct LLM call, looks like this:
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import MessagesState
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-4o-mini")
def call_llm(state: MessagesState) -> dict:
response = model.invoke(state["messages"])
return {"messages": [response]}
The function receives the full state, does its work, and returns only what changed. LangGraph merges those updates back into the shared state before passing it to the next node. You don’t return the entire state object, just the fields that changed.
Unconditional edges always route from one node to the next. Conditional edges evaluate a function against the current state and route to different nodes based on the result. Here’s a minimal graph using both:
builder = StateGraph(MessagesState)
builder.add_node("llm", call_llm)
builder.add_edge(START, "llm")
builder.add_edge("llm", END)
graph = builder.compile()
After compiling any graph, you can generate a Mermaid diagram of its structure with one line. This is one of the most useful debugging tools in LangGraph and most tutorials skip it entirely:
print(graph.get_graph().draw_mermaid())
For the simple LLM graph above, the output looks like this:
graph TD;
__start__ --> llm;
llm --> __end__;
Paste that into mermaid.live to render a visual flow diagram. For complex graphs with conditional edges and multiple nodes, this makes it immediately clear whether your topology matches your intent, before you run a single inference call.
For conditional routing, add_conditional_edges() accepts a source node, a condition function returning a string key, and a path map dictionary. This API is unchanged from v0.1 through v1.0.
def should_continue(state: MessagesState) -> str:
last_message = state["messages"][-1]
if hasattr(last_message, "tool_calls") and last_message.tool_calls:
return "tools"
return "__end__"
builder.add_conditional_edges("llm", should_continue, {
"tools": "tool_node",
"__end__": END
})
The path map dictionary translates return values from the condition function into actual node names. Your routing logic stays clean, the function returns a simple string, and the map handles where that string leads.
LangGraph in Python uses StateGraph to define agent workflows. Install with pip install langgraph langgraph-prebuilt. Import StateGraph, START, and END from langgraph.graph. Define your state as a TypedDict, add nodes as Python functions with add_node(), connect them with add_edge(), then call compile(). Invoke the finished graph with graph.invoke({'messages': [...]}).
LangChain is a framework for building LLM-powered chains and pipelines. LangGraph is a separate library built on LangChain specifically for stateful, multi-step AI agents modeled as graphs. Use LangChain for simple sequential prompts; use LangGraph when your agent needs loops, branching, persistent state, or human-in-the-loop checkpoints. The two libraries are complementary, not competing.
In LangGraph, nodes are Python functions that perform computation, LLM calls, tool invocations, or data transformations. Edges define the execution order between nodes. Simple edges use add_edge('node_a', 'node_b'). Conditional edges use add_conditional_edges() to route based on the current state, enabling branching and loops in agent workflows.
LangGraph state is a shared TypedDict or Pydantic model passed between every node in the graph. Each node reads the current state and returns a dict of updates. For conversation agents, MessagesState uses the add_messages reducer, instead of replacing the messages list, new messages are appended, preserving conversation history across all nodes throughout execution.
create_react_agent is a prebuilt helper in langgraph.prebuilt that builds a complete ReAct (Reason + Act) agent graph automatically. It handles the LLM call, tool execution loop, and conditional routing without requiring manual StateGraph setup. Use it for standard tool-calling agents. Import with: from langgraph.prebuilt import create_react_agent.
LangGraph state is a shared TypedDict or Pydantic model passed between every node in the graph. Each node reads the current state and returns a dict of updates. For conversation agents, MessagesState uses the add_messages reducer, instead of replacing the messages list, new messages are appended, preserving full conversation history across all nodes.

Here’s something almost every LangGraph tutorial glosses over. What does the Annotated[list, add_messages] pattern actually mean? Why is there a second argument?
from typing import Annotated
from langgraph.graph.message import add_messages
from typing_extensions import TypedDict
class MyState(TypedDict):
messages: Annotated[list, add_messages]
The second argument to Annotated, add_messages, is a reducer. Reducers tell LangGraph how to merge updates when a node returns new data. Without a reducer, a node returning {"messages": [new_message]} would overwrite the entire messages list with a list containing only the new message. With add_messages, new messages are appended to the existing list instead.
Every time you see Annotated[list, something] in a LangGraph state definition, that second argument controls how the field gets updated. Other common reducers include Python’s operator.add for numeric accumulation. The pattern is consistent: annotate the type, specify the merge behavior.
For most agent use cases, you don’t need to define state manually. MessagesState from langgraph.graph.message already includes the correct Annotated[list, add_messages] definition:
from langgraph.graph.message import MessagesState
# MessagesState is equivalent to defining:
# class MessagesState(TypedDict):
# messages: Annotated[list, add_messages]
Custom state is useful when your agent needs to track additional data alongside the conversation. A few real examples: a running token cost counter, a list of URLs already visited in a research agent, a structured output object being assembled across multiple nodes. Define your own TypedDict and add whatever fields you need:
from typing import Annotated
from langgraph.graph.message import add_messages
from typing_extensions import TypedDict
class ResearchState(TypedDict):
messages: Annotated[list, add_messages]
visited_urls: list[str]
total_tokens_used: int
Nodes that update visited_urls return a new list to replace it (no reducer, so it overwrites). Nodes that touch messages use the add_messages reducer to append. Both fields live in the same state object, accessible to every node.
Every LangGraph learner hits the same fork: build a graph manually with StateGraph, or use create_react_agent from the prebuilt package. LangGraph v0.3 introduced the langgraph-prebuilt package containing create_react_agent as a high-level abstraction built on top of the core StateGraph primitive, without breaking existing APIs. Neither path is wrong. They solve different problems.
The LangChain team designed this two-level system deliberately: full control when you need it, reasonable defaults when you don’t. As the official documentation puts it, LangGraph “gives developers full control of agent logic while still providing prebuilt abstractions for common patterns.”
| Feature | StateGraph (manual) | create_react_agent (prebuilt) |
|---|---|---|
| Best for | Custom flows, multi-agent systems, parallel branches | Standard tool-calling agents, prototyping |
| Lines of code (basic agent) | 30 to 60+ lines | 5 to 10 lines |
| Custom routing logic | Full control via add_conditional_edges() | Built-in ReAct loop only |
| Built-in ReAct loop | You build it manually | Included automatically |
| State customization | Any TypedDict or Pydantic model | MessagesState by default, extendable |
| Human-in-the-loop support | Full support with interrupt() | Partial support via interrupt_before/after |
| When to choose | Non-standard flows, supervisor agents, production systems needing custom control | Standard tool-calling, quick prototypes, learning the basics |
A note on where this fits today: langgraph.prebuilt.create_react_agent still works exactly as shown in this tutorial, LangGraph 1.x keeps it for backward compatibility, but as of the v1.0 release it’s marked deprecated in favor of create_agent in the separate langchain.agents package, which wraps the same ToolNode-based loop with a middleware system on top. If you’re starting a new project today, look at langchain.agents.create_agent first. The StateGraph and create_react_agent patterns below remain accurate and functional, and are worth knowing regardless, since create_agent is built on the same primitives.
The practical rule: start with create_react_agent for any standard tool-calling agent, or evaluate langchain.agents.create_agent if you’re starting fresh. If you find yourself needing parallel node execution, a supervisor-worker pattern, custom retry logic, or complex branching, migrate to a manual StateGraph. The underlying primitives are identical either way, the prebuilt helpers are syntactic sugar over the same graph mechanics.
One commenter in the r/LangChain thread ranking third on Google for “langgraph tutorial” put it plainly: “The documentation is not very friendly to beginners.” That friction is real, and most of it comes from tutorials that drop readers into manual StateGraph construction before explaining when the prebuilt path is sufficient.
For a head-to-head look at how LangGraph’s design philosophy compares to alternative frameworks, see our CrewAI vs LangGraph comparison. For a broader survey of available options, Agent Frameworks on AgentsIndex indexes the full ecosystem.
The fastest path to a working agent uses create_react_agent. This walkthrough builds a complete agent with two math tools from scratch. Every import is included, copy and run this directly.
LangGraph tools are standard Python functions decorated with @tool from LangChain core. The function’s docstring becomes the description the LLM uses to decide when to call the tool:
from langchain_core.tools import tool
@tool
def multiply(a: float, b: float) -> float:
"""Multiply two numbers together."""
return a * b
@tool
def add(a: float, b: float) -> float:
"""Add two numbers together."""
return a + b
tools = [multiply, add]
Keep docstrings clear and specific. Vague descriptions lead to missed tool calls. The LLM reads these at runtime to decide which tool fits the user’s request.
create_react_agent takes an LLM instance and a list of tools. It builds the full ReAct graph, LLM call, tool execution loop, conditional routing, automatically:
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
model = ChatOpenAI(model="gpt-4o-mini")
agent = create_react_agent(model, tools)
Two lines. The agent handles the reason-act-observe loop, routes tool call results back through the LLM, and knows when to stop. What used to take 40 lines of boilerplate in v0.1 is now this.
Call .invoke() with a messages list. The input format matches the standard LangChain messages API:
from langchain_core.messages import HumanMessage
result = agent.invoke({
"messages": [HumanMessage(content="What is 47 multiplied by 83?")]
})
print(result["messages"][-1].content)
# Output: 47 multiplied by 83 is 3,901.
The result contains the full messages list: the original human message, the LLM’s tool call request, the tool’s response, and the final LLM answer. Inspect result["messages"] to see the complete trace.
Here’s what create_react_agent builds internally. Reading this helps when you need to extend or debug the prebuilt version:
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import MessagesState
from langgraph.prebuilt import ToolNode
from langchain_openai import ChatOpenAI
model_with_tools = ChatOpenAI(model="gpt-4o-mini").bind_tools(tools)
tool_node = ToolNode(tools)
def call_model(state: MessagesState) -> dict:
response = model_with_tools.invoke(state["messages"])
return {"messages": [response]}
def should_continue(state: MessagesState) -> str:
last_msg = state["messages"][-1]
if hasattr(last_msg, "tool_calls") and last_msg.tool_calls:
return "tools"
return "__end__"
builder = StateGraph(MessagesState)
builder.add_node("agent", call_model)
builder.add_node("tools", tool_node)
builder.add_edge(START, "agent")
builder.add_conditional_edges("agent", should_continue, {
"tools": "tools",
"__end__": END
})
builder.add_edge("tools", "agent")
graph = builder.compile()
Both implementations produce identical behavior. The create_react_agent version is shorter; the manual version is more readable for learning purposes.
After compiling any graph, you can print its structure as a Mermaid diagram. This is useful for debugging routing logic and for sharing architecture diagrams with teammates.
print(graph.get_graph().draw_mermaid())
Running that on the manual ReAct agent above produces output like this:
graph TD;
__start__ --> agent;
agent --> tools;
agent --> __end__;
tools --> agent;
Paste that into any Mermaid renderer, such as mermaid.live, to get an interactive diagram. The method works on any compiled StateGraph, including create_react_agent outputs. When you need to add human-in-the-loop interrupts, custom pre-processing nodes, or parallel tool execution, you’ll expand on the manual pattern.
A stateless agent forgets the entire conversation after each .invoke() call. LangGraph’s checkpointing system solves this by saving graph state after every node execution, enabling multi-turn memory, fault-tolerant workflows, and human-in-the-loop interrupts. Checkpointing is the foundation that observability and tracing tools like LangSmith build on.

MemorySaver stores state in Python in-process memory. It’s the fastest way to add conversation memory during development and testing:
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
model = ChatOpenAI(model="gpt-4o-mini")
checkpointer = MemorySaver()
agent = create_react_agent(model, tools, checkpointer=checkpointer)
# thread_id scopes the conversation, use a unique ID per user session
config = {"configurable": {"thread_id": "user-session-001"}}
result1 = agent.invoke(
{"messages": [HumanMessage(content="My name is Alex.")]},
config=config
)
result2 = agent.invoke(
{"messages": [HumanMessage(content="What is my name?")]},
config=config
)
print(result2["messages"][-1].content)
# Output: Your name is Alex.
The thread_id in config scopes state to a specific conversation. Using the same thread_id across calls replays the full conversation history before processing the new message. Using a different thread_id starts a fresh session with no memory of previous exchanges.
Production warning: MemorySaver is for development only. MemorySaver stores state in Python in-memory dictionaries and loses all conversation history on process restart. Production deployments require SqliteSaver for local persistence or AsyncPostgresSaver for cloud deployments. Shipping MemorySaver to production is one of the most common mistakes in early LangGraph deployments, users lose their session context every time the server restarts.
Migrating from MemorySaver to SqliteSaver needs one extra package, since the SQLite checkpoint backend ships separately from core langgraph:
pip install langgraph-checkpoint-sqlite
SqliteSaver.from_conn_string() is a context manager, not a plain constructor, use it with with so the underlying connection opens and closes correctly:
from langgraph.checkpoint.sqlite import SqliteSaver
with SqliteSaver.from_conn_string("agent_memory.db") as checkpointer:
agent = create_react_agent(model, tools, checkpointer=checkpointer)
# invoke the agent inside this block; the connection closes when it exits
The agent_memory.db file persists across process restarts. For cloud deployments at scale, replace this with AsyncPostgresSaver (from the langgraph-checkpoint-postgres package) using a managed Postgres connection string. For hosted deployment with automatic scaling and built-in persistence, LangGraph Platform handles the infrastructure. For production monitoring and trace visualization, LangSmith integrates natively with LangGraph.
After compiling your graph, you can inspect its full structure using the built-in Mermaid visualization. It requires no additional dependencies beyond the core langgraph package.
Graph visualization is available via graph.get_graph().draw_mermaid(), which returns a Mermaid diagram string:
# After compiling your graph
graph = builder.compile()
# Get the Mermaid diagram as a string
mermaid_str = graph.get_graph().draw_mermaid()
print(mermaid_str)
For the ReAct agent we built earlier with agent and tools nodes, the output looks like this:
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
__start__([<p>__start__</p>]):::first
agent([agent])
tools([tools])
__end__([<p>__end__</p>]):::last
__start__ --> agent;
agent -.-> tools;
agent -.-> __end__;
tools --> agent;
classDef default fill:#f2f0ff,line-height:1.2;
classDef first fill-opacity:0;
classDef last fill:#bfb6fc;
Paste that into any Mermaid renderer, mermaid.live, VS Code’s Mermaid plugin, or a Jupyter notebook with the mermaid extension, to see your graph as a flow diagram. The dashed lines represent conditional edges: the agent node can route to either tools or __end__ depending on whether the LLM returned tool calls.
For richer output in Jupyter, use draw_mermaid_png() to render the diagram directly:
from IPython.display import Image, display
# Render the graph as a PNG in a Jupyter notebook
display(Image(graph.get_graph().draw_mermaid_png()))
Make graph visualization a standard part of your development workflow. Complex graphs with multiple conditional branches are far easier to debug visually than by reading node and edge definitions. If the flow diagram doesn’t match your mental model of how the agent should behave, you’ve found your bug before running a single inference call.
LangGraph reached stable LTS release in October 2025, per the LangChain Python Release Policy documentation. LangGraph 0.x enters maintenance mode and remains supported until December 2026, which is why v0.1 code still appears in production codebases and most online tutorials. Most top-ranked tutorials for “langgraph tutorial” still use deprecated v0.1 API patterns including set_entry_point() and pre-MessagesState TypedDict definitions.
Here’s a direct comparison of the specific patterns that changed between versions:
| What you’re changing | Old code (v0.1, deprecated) | Current code (v1.0) | Why it changed |
|---|---|---|---|
| Graph entry point | builder.set_entry_point("node") |
builder.add_edge(START, "node") |
Unified edge API, entry point is just an edge from the START sentinel |
| Graph finish point | builder.set_finish_point("node") |
builder.add_edge("node", END) |
Same unified edge API applies to exit as well |
| Message state definition | Custom TypedDict with raw BaseMessage list | from langgraph.graph.message import MessagesState |
Prebuilt state with the correct add_messages reducer included |
| ReAct agent pattern | Hand-rolled agent loop (20 to 40 lines) | from langgraph.prebuilt import create_react_agent |
Prebuilt package introduced in v0.3 for standard patterns |
| Tool execution node | Custom tool execution function per tool | from langgraph.prebuilt import ToolNode |
Prebuilt ToolNode handles all tool calling boilerplate |
| Conditional routing | add_conditional_edges() |
add_conditional_edges() |
Unchanged, stable from v0.1 through v1.0, no migration needed |
The good news about migrating existing code: add_conditional_edges() is completely unchanged from v0.1 through v1.0. If you have existing conditional routing logic, it works as-is. The main migration work is replacing set_entry_point() and set_finish_point() with explicit add_edge(START, ...) and add_edge(..., END) calls, and updating state definitions to use MessagesState instead of manually-defined TypedDicts with BaseMessage sequences.
One more migration worth knowing about even though it’s outside the v0.1-to-v1.0 scope of this table: langgraph.prebuilt.create_react_agent and ToolNode are themselves now marked deprecated in favor of create_agent in the langchain.agents package, covered above in the StateGraph-vs-prebuilt section. They still work, LangGraph 1.x keeps the whole langgraph.prebuilt module for backward compatibility, but it’s the direction the ecosystem is moving next.
For teams evaluating LangGraph’s ecosystem alongside alternative Python frameworks, the best AI agent frameworks guide compares options by production readiness, community size, and use-case fit. AutoGen takes a different architectural approach to multi-agent coordination that’s worth understanding before committing to LangGraph for complex multi-agent systems.
LangChain is a framework for building LLM-powered chains and pipelines. LangGraph is a separate library built on LangChain specifically for stateful, multi-step AI agents modeled as graphs. Use LangChain for simple sequential prompts; use LangGraph when your agent needs loops, branching, persistent state, or human-in-the-loop checkpoints. The two libraries are complementary, not competing.
create_react_agent is a prebuilt helper in langgraph.prebuilt that builds a complete ReAct (Reason and Act) agent graph automatically. It handles the LLM call, tool execution loop, and conditional routing without requiring manual StateGraph setup. Use it when you need a standard tool-calling agent. Import with: from langgraph.prebuilt import create_react_agent.
Yes. LangGraph is model-agnostic and works with any LLM that has a LangChain-compatible wrapper. Tested providers include Anthropic Claude, Google Gemini, Groq, Mistral AI, and local models via Ollama. Replace ChatOpenAI with the corresponding provider’s chat model class. The graph logic, state management, and checkpointing work identically regardless of the underlying model provider.
Start with graph visualization, call graph.get_graph().draw_mermaid() to confirm the graph structure matches your intent. Then use graph.stream() instead of .invoke() to see intermediate node outputs in real time as each node executes. For production debugging, LangSmith provides full trace visualization for every node execution, tool call, and state transition in your LangGraph workflow.
For local production use SqliteSaver as your checkpointer for state persistence across restarts. For cloud production use AsyncPostgresSaver with a managed Postgres database. LangGraph Platform provides a hosted deployment environment with automatic scaling, built-in persistence, and a REST API out of the box. Never use MemorySaver in production, it loses all state on process restart.
LangGraph’s learning curve is real. The official documentation acknowledges it requires deliberate study before building complex systems, and the ecosystem of outdated tutorials hasn’t made that easier. But the core concepts are manageable once you understand the four primitives: state, nodes, edges, and compilation.
A few things to take from this tutorial:
from langgraph.graph import StateGraph, START, END, not the deprecated v0.1 patterns you’ll find in most search resultscreate_react_agent for standard tool-calling agents (or langchain.agents.create_agent if you’re starting fresh today); switch to manual StateGraph when you need custom routing or multi-agent architectureadd_messages reducer, it explains why message state behaves the way it does across nodesMemorySaver to production; use SqliteSaver locally or AsyncPostgresSaver for cloud deploymentsgraph.get_graph().draw_mermaid() before debugging behavior issuesFrom here, the most useful next step depends on what you’re building. For multi-agent patterns including supervisor-worker architectures, our guide on multi-agent systems covers the design decisions in detail. For comparing LangGraph’s production readiness against alternatives, the best AI agent frameworks guide benchmarks options by use case. And for practical context on what developers are actually shipping, the AI agent use cases guide covers real production deployments across industries.
All 94 AI agent tools and integrations
First paid plans from $3 to $650 a month.
New AI tools, checked
Every AI tool price change we caught, each Tuesday.
Buyer's guide
Apollo suits teams starting free, VoiceDrop suits voicemail campaigns, and PipeLime suits hands-off email and LinkedIn prospecting.
Buyer's guide
What Clay's Free, Launch, Growth and Enterprise plans cost, and how many Actions, Data Credits and table rows each one includes.
Buyer's guide
Google Gemini, Microsoft Copilot and Claude lead for everyday help; Reclaim, CosVoice and Lindy suit calendars, phone calls and email.
Buyer's guide
CloudPloy has the cheapest paid entry plan and GrantCue the dearest, free plans are common, and prices jump hardest at business tiers.