PromptisePromptise
Docs
GitHub
Promptise - AI Framework LogoPromptise

The foundation layer for agentic intelligence. Build, secure and operate autonomous AI systems with Promptise Foundry.

pip install promptise

[01] Foundry

  • MCPcast
  • The Promptise Agent
  • Reasoning Engine
  • MCP
  • Agent Runtime
  • Prompt Engineering
  • Execution Engine
  • Agent Identity

[02] Resources

  • Documentation
  • GitHub
  • Guides
  • Learning Paths
  • Questions

[03] Company

  • About
  • Terms of Service
  • Privacy Policy
  • Cookie Policy
  • Subprocessors

© 2026 Promptise by Manser Ventures. All rights reserved.

Open source · Python

← Guides> Frameworks and comparisons

LangGraph Alternatives: 7 Options and How to Migrate (2026)

LangGraph alternatives compared: why teams look, 7 options and when each fits, the same agent in LangGraph and Promptise, and a concept map to migrate.

Level
Intermediate
Reading time
18 min
Published
Oct 18, 2026
Last updated
Oct 18, 2026
Tested with
Promptise 1.4.1
By
Promptise Team
  • AI Agent Frameworks
Contents · 16 sections↓
  1. 01What is the best LangGraph alternative?
  2. 02Why do developers look for LangGraph alternatives?
  3. 03How LangGraph works, and what an alternative must replace
  4. 04When to stay with LangGraph (and when to switch)
  5. 057 LangGraph alternatives and when each fits
  6. 06What you need to run the examples
  7. 07Step 1: Write the tools once
  8. 08Step 2: Build the agent with LangGraph's StateGraph
  9. 09Step 3: Build the same agent with Promptise
  10. 10Step 4: Keep explicit routing with a Promptise graph
  11. 11How do you migrate from LangGraph to Promptise?
  12. 12Running it in production
  13. 13Common problems and fixes
  14. 14Limitations
  15. 15Frequently asked questions
  16. 16Next steps

LangGraph is the most widely used graph framework for AI agents, and also one that many teams start to question once their agent works. This guide is for developers who use LangGraph today, or are about to, and want to know their options. It covers why people look for LangGraph alternatives, seven alternatives and when each one fits, the same agent written in LangGraph and in Promptise Foundry, and a concept map for migrating node by node.

[01]

What is the best LangGraph alternative?

It depends on why you are leaving. If the graph feels like too much code for a tool-calling agent, pick a framework where the loop is built in: Promptise Foundry, Pydantic AI or the OpenAI Agents SDK. If you like graphs but want another ecosystem, Microsoft Agent Framework workflows, Pydantic Graph, LlamaIndex Workflows and Google ADK all have graph or workflow APIs. If you want a team of role-based agents, CrewAI. And if you depend on durable runs that pause for days, check carefully, because that is where LangGraph is strongest.

  • Most agents don't need an explicit graph. A model, tools, an approval rule and a step limit cover a large share of real agents.

  • LangGraph's checkpointers and interrupts are hard to replace. Few alternatives let a paused run wait in a database and resume after a restart.

  • Your tools can move unchanged. LangChain @tool functions work in Promptise as they are, and MCP servers work in every framework here.

  • Migrate one agent at a time, and run the same evals before and after.

  • For a full feature table across frameworks, see Python AI agent frameworks compared.


[02]

Why do developers look for LangGraph alternatives?

The reasons people give are consistent across GitHub issues, forums and Hacker News threads. None of them means LangGraph is a bad tool. They mean it was built for a kind of control that not every agent needs.

  • Abstraction for simple agents. A tool-calling agent in the Graph API needs a state schema, nodes, a conditional edge, a tool node and a compile step. On the LangChain forum, users ask why simple model calls need this many layers. On Hacker News, one developer reports replacing an inherited LangGraph setup with plain function calls and deleting over a thousand lines.

  • Boilerplate for branching logic. Commenters describe conditional graphs as tedious to wire and read (HN).

  • Debugging state and limits. Users report confusion about the recursion limit (langchain-ai/docs #1121) and InvalidUpdateError when parallel branches write the same state key (langgraph #2336, #6446). The recursion limit counts graph steps, not tool calls, which surprises people.

  • Package churn. Several issues report breakage between langgraph and langgraph-prebuilt versions (#6363, #7404). create_react_agent is now deprecated in favor of LangChain's create_agent.

  • Coupling to LangSmith. The library is MIT-licensed and runs without LangSmith, and tracing is off unless you turn it on. But LangGraph Studio needs a LangSmith account and API key, and the managed deployment option is part of LangSmith's paid plans. Some teams prefer not to build on that path.

People also praise LangGraph, for the same reasons: typed state, checkpointing, interrupts that survive restarts, streaming, and full control over every step. Teams building coding agents and long-running workflows choose it for exactly that (HN).


[03]

How LangGraph works, and what an alternative must replace

LangGraph models an agent as a state machine. You define a state schema, often MessagesState, which holds the conversation. Nodes are functions that read the state and return updates. Edges decide which node runs next, either always or based on a condition. You compile the graph, optionally with a checkpointer, which saves the state after each step under a thread_id.

Text
1
2
3
4
5
6
7
            ┌──────────────── state (messages, your keys) ───────────────┐
            │                                                             │
START ──▶ [agent] ──tools_condition──▶ [review] ──▶ [tools] ──▶ back to [agent]
             │                            │
             │ no tool calls              │ interrupt(): run pauses, state saved
             ▼                            ▼        by the checkpointer
            END                 Command(resume=...) continues the same thread_id

Any alternative has to give you five things this picture gives you:

1. The tool loop: call the model, run the tools it asks for, repeat. 2. Control flow: routing, branches and loops you can read. 3. State: what each step can see, and what persists between turns. 4. Pauses: a way to stop before a risky action and continue after a decision. 5. Limits and visibility: a cap on steps and a trace of what happened.

Most frameworks provide the first, third and fifth in a few lines. They differ most on the second and the fourth, and that is where to focus your evaluation.


[04]

When to stay with LangGraph (and when to switch)

Stay with LangGraph when:

  • Approvals wait hours or days, and the run must survive restarts while it waits.

  • Your workflow really is a graph: many branches, parallel fan-out, human steps in the middle, retries per node.

  • You already use LangSmith for tracing and evaluation, and it works for you.

Consider switching when:

  • Most of your graphs are the same agent → tools → agent loop with small variations.

  • New team members struggle to read the graph code, or debugging time goes to state plumbing rather than agent behavior.

  • You need features around the agent that LangGraph leaves to you, such as an MCP server framework, budgets, guardrails or a project runner.

  • You want to avoid a hosted tool for local debugging.

A partial switch is also an option. Keep LangGraph for the one workflow that needs durable pauses, and write the simpler agents in something lighter.


[05]

7 LangGraph alternatives and when each fits

Versions checked on 18 October 2026. Each summary comes from the project's own documentation.

Framework

Core idea

Graph or workflow API

Fits best when

Promptise Foundry 1.4.1

MCP-first agents with approvals, budgets, guardrails and a runtime

Reasoning Graph (PromptGraph)

You want the tool loop built in, plus the production pieces in one package

Pydantic AI 2.57.0

Typed agents with validated inputs and outputs

Pydantic Graph

You want type safety and usage limits

OpenAI Agents SDK 0.24.0

Agents, handoffs, guardrails, sessions

No

You mostly use OpenAI models and want the shortest path

Microsoft Agent Framework 1.22.0

Successor to AutoGen and Semantic Kernel

Workflows (WorkflowBuilder)

You need a graph with checkpoints in a Microsoft or Azure stack

LlamaIndex Workflows 2.26.0

Event-driven steps with a shared context

Workflows (@step)

Your agent is mostly retrieval over your documents

CrewAI 1.15.28

Role-based crews of agents and tasks

Flows

You think in teams of agents with roles

Google ADK 2.12.0

Agents plus sequential, parallel, loop and graph workflows

Workflow agents and graphs

You build on Gemini and Google Cloud

Promptise Foundry

Promptise builds an agent from MCP servers or LangChain tools with one call, build_agent(), and runs the tool loop for you. Approvals are an ApprovalPolicy with a handler, step limits are max_agent_iterations, and conversation history goes in a ConversationStore (memory, SQLite, Postgres or Redis). When you do want explicit control flow, the Reasoning Graph gives you nodes, conditional edges and prebuilt patterns. The same package includes an MCP server framework and promptise run for running and deploying projects. The trade-off: approvals are answered in the running process, so a pending approval does not survive a restart.

Pydantic AI

Pydantic AI treats an agent as a typed function: validated dependencies in, validated output out. It has token and tool-call limits, deferred tools for approvals that resume from message history, and durable execution through Temporal, DBOS or Prefect. For explicit state machines it offers Pydantic Graph. A good fit for teams that already like Pydantic and want strict types.

OpenAI Agents SDK

The OpenAI Agents SDK is a small library around agents, handoffs between agents, guardrails and sessions. Approvals pause a run and return a serializable RunState. It works with other providers through adapters, but its tracing exports to OpenAI by default. A good fit when you want handoffs and minimal code on OpenAI models.

Microsoft Agent Framework

Microsoft Agent Framework is the successor to AutoGen and Semantic Kernel, released as 1.0 in April 2026. Its workflows are the closest thing here to StateGraph: executors connected by edges, with superstep checkpoints and human-in-the-loop requests. It supports Python and .NET. A good fit when you want a graph with checkpoints and your organization runs on Azure.

LlamaIndex Workflows

LlamaIndex Workflows are event-driven: each @step method takes an event and emits the next one, with a shared Context you can serialize to pause and resume. They sit next to LlamaIndex's retrieval tools. A good fit for agents that mainly search and reason over your documents.

CrewAI

CrewAI describes agents by role, goal and backstory and groups them into crews that work through tasks. Its Flows add event-driven steps (@start, @listen, @router) with state persistence. A good fit when the problem maps naturally to a team. Note that it sends anonymous telemetry unless you set CREWAI_DISABLE_TELEMETRY=true.

Google ADK

The Agent Development Kit has LLM agents plus workflow agents that run sub-agents in sequence, in parallel or in a loop, and ADK 2.0 adds graph-based workflows. It works with other models but is designed around Gemini and Google Cloud. A good fit for teams already on that platform.

Two more options deserve a mention. smolagents, from Hugging Face, is a minimal library whose main agent writes Python code as its actions. And for a single agent with two or three tools, no framework at all is a fair choice: how to build an AI agent in Python writes the loop by hand.


[06]

What you need to run the examples

  • Python 3.10 or later and an OpenAI API key. Both examples use gpt-5-mini.

  • Two virtual environments, so the versions stay clean:

>_Terminal
pip install "langgraph==1.2.16" "langchain==1.4.6" "langchain-openai==1.7.2"   # LangGraph
pip install "promptise==1.4.1"                                                 # Promptise

The example is an order-support agent with two tools. It refunds orders, but a refund over 100 USD must stop for a person, who in this example says no.


[07]

Step 1: Write the tools once

Both versions share the same LangChain tools. Keeping tools outside the agent code is the first step of any migration: the tools don't change, only the code around them.

Pythontools.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"""Two LangChain tools both versions share: a lookup and a refund."""
from langchain_core.tools import tool

ORDERS = {
    "O-1001": {"item": "Desk lamp", "amount": 49.00, "status": "delivered"},
    "O-1002": {"item": "Office chair", "amount": 219.00, "status": "delivered"},
}


@tool
def get_order(order_id: str) -> dict:
    """Look up an order by ID: item, amount in USD and status."""
    return ORDERS.get(order_id.strip().upper(), {"error": f"No order {order_id}"})


@tool
def refund_order(order_id: str, amount: float) -> dict:
    """Refund a delivered order. Moves money."""
    return {"refunded": True, "order_id": order_id, "amount": amount}

[08]

Step 2: Build the agent with LangGraph's StateGraph

This is the LangGraph version, written with the Graph API so every part is visible. A review node sits between the model and the tools. It pauses with interrupt() before a refund over 100 USD.

Pythonagent_langgraph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
"""A support agent written with LangGraph's Graph API."""
from langchain.chat_models import init_chat_model
from langchain_core.messages import SystemMessage, ToolMessage
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.types import Command, interrupt

from tools import get_order, refund_order

PROMPT = "You are an order-support agent. Use the tools. Answer in one sentence."
tools = [get_order, refund_order]
model = init_chat_model("openai:gpt-5-mini").bind_tools(tools)


def call_model(state: MessagesState):
    return {"messages": [model.invoke([SystemMessage(PROMPT), *state["messages"]])]}


def review(state: MessagesState):
    """Pause before a refund over 100 USD and wait for a person's decision."""
    call = next((c for c in state["messages"][-1].tool_calls if c["name"] == "refund_order"), None)
    if call and call["args"]["amount"] > 100:
        if interrupt({"question": "Approve this refund?", "args": call["args"]}) != "approve":
            denied = ToolMessage("DENIED: refunds over 100 USD need a manager.", tool_call_id=call["id"])
            return Command(goto="agent", update={"messages": [denied]})
    return Command(goto="tools")


builder = StateGraph(MessagesState)
builder.add_node("agent", call_model)
builder.add_node("review", review)
builder.add_node("tools", ToolNode(tools))
builder.add_edge(START, "agent")
builder.add_conditional_edges("agent", tools_condition, {"tools": "review", END: END})
builder.add_edge("tools", "agent")
graph = builder.compile(checkpointer=InMemorySaver())  # interrupts need a checkpointer

config = {"configurable": {"thread_id": "ticket-42"}, "recursion_limit": 12}
question = {"messages": [{"role": "user", "content": "Order O-1002 arrived broken. Refund it in full."}]}
result = graph.invoke(question, config)
if "__interrupt__" in result:  # the run paused in `review`
    print("paused:", result["__interrupt__"][0].value)
    result = graph.invoke(Command(resume="reject"), config)  # a person said no
print(result["messages"][-1].content)
Output
paused: {'question': 'Approve this refund?', 'args': {'order_id': 'O-1002', 'amount': 219}}
I attempted the full $219 refund for order O-1002 but it was denied because refunds over $100 require manager approval—would you like me to escalate to a manager now, or would you prefer a replacement or a return shipping label instead?

What each part does:

  • MessagesState holds the conversation, and its reducer appends new messages.

  • tools_condition routes to review when the model asked for tools, and to END when it answered.

  • interrupt() stops the run and saves the state through the checkpointer. The caller sees __interrupt__ and resumes with Command(resume=...) on the same thread_id.

  • On a rejection, review adds a ToolMessage that says DENIED, so the model gets a result for its tool call and can answer.

  • recursion_limit caps the number of graph steps.

The strength of this design shows when the state lives in a database: swap InMemorySaver for PostgresSaver, and the paused run can wait for days and resume in another process. The cost is the wiring: you own the state, the routes and the resume logic. LangChain's create_agent with HumanInTheLoopMiddleware hides most of this, as the framework comparison shows.


[09]

Step 3: Build the same agent with Promptise

In Promptise the loop is built in. The approval rule becomes a handler on an ApprovalPolicy, the thread becomes a session_id on a conversation store, and the recursion limit becomes max_agent_iterations.

Pythonagent_promptise.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
"""The same support agent in Promptise: the loop, the gate and the history are settings."""
import asyncio

from promptise import build_agent
from promptise.approval import ApprovalDecision, ApprovalPolicy
from promptise.conversations import InMemoryConversationStore

from tools import get_order, refund_order

PROMPT = "You are an order-support agent. Use the tools. Answer in one sentence."


async def review(request):
    """Runs before every refund_order call. Small refunds pass; a person decides the rest."""
    if request.arguments["amount"] <= 100:
        return ApprovalDecision(approved=True)
    print("paused:", {"question": "Approve this refund?", "args": request.arguments})
    return ApprovalDecision(approved=False, reason="Refunds over 100 USD need a manager.")  # a person said no


async def main():
    agent = await build_agent(
        model="openai:gpt-5-mini",
        instructions=PROMPT,
        extra_tools=[get_order, refund_order],         # your LangChain tools, unchanged
        approval=ApprovalPolicy(tools=["refund_order"], handler=review, timeout=300),
        conversation_store=InMemoryConversationStore(),  # history per session_id
        max_agent_iterations=6,                          # at most 6 model calls
    )
    try:
        print(await agent.chat("Order O-1002 arrived broken. Refund it in full.", session_id="ticket-42"))
    finally:
        await agent.shutdown()


asyncio.run(main())
Output
paused: {'question': 'Approve this refund?', 'args': {'order_id': 'O-1002', 'amount': 219.0}}
I attempted the full $219 refund for order O-1002 but it was denied because refunds over $100 require manager approval—shall I escalate this to a manager now to complete the refund?

What changed:

  • No graph code. build_agent() builds the default reasoning loop (call the model, run tools, repeat).

  • The tools are the same objects. extra_tools= takes LangChain tools unchanged. Tools on MCP servers go in servers= instead.

  • The pause is a function call. The handler runs before every refund_order call and returns a decision. A denied call reaches the model as DENIED: <reason>, which is what the LangGraph version built by hand. In production the handler would post to Slack, a web UI or a webhook and wait, up to timeout seconds.

  • History is a store. agent.chat(..., session_id=...) loads and saves the conversation. Swap InMemoryConversationStore for SQLiteConversationStore or PostgresConversationStore to keep it across restarts.

The difference that matters for some teams: the handler waits inside the running process. If the process restarts while a person is deciding, the pending approval is gone, and the user has to ask again. LangGraph's checkpointed interrupt doesn't have that limit. Human-in-the-loop approval for AI agents covers handlers, timeouts and audit logs.


[10]

Step 4: Keep explicit routing with a Promptise graph

Some LangGraph graphs exist for a reason: a router in front of the agent, a validation step after it, a branch to a cheaper model. You can keep that structure. Promptise's Reasoning Graph has nodes, conditional edges and an entry point, like StateGraph.

Pythongraph_promptise.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
"""An explicit graph, for when you want to keep LangGraph-style routing."""
import asyncio

from pydantic import BaseModel
from promptise import build_agent
from promptise.engine import PromptGraph, PromptNode

from tools import get_order, refund_order


class Triage(BaseModel):
    about_an_order: bool


graph = PromptGraph("support", mode="static")
graph.add_node(PromptNode("triage", output_schema=Triage,
                          instructions="Decide whether the message is about an order."))
graph.add_node(PromptNode("agent", inject_tools=True, is_terminal=True,
                          instructions="You are an order-support agent. Use the tools. Answer in one sentence."))
graph.add_node(PromptNode("decline", is_terminal=True,
                          instructions="Reply only: 'Sorry, I can only help with orders.' Do not do the task."))
graph.on_output("triage", "agent", key="about_an_order", value=True)
graph.on_output("triage", "decline", key="about_an_order", value=False)
graph.set_entry("triage")


async def main():
    agent = await build_agent(model="openai:gpt-5-mini", agent_pattern=graph,
                              extra_tools=[get_order, refund_order])
    try:
        for text in ["What's the status of O-1001?", "Write me a poem about Mondays."]:
            result = await agent.ainvoke({"messages": [{"role": "user", "content": text}]})
            print(f"{text} -> {result['messages'][-1].content}")
    finally:
        await agent.shutdown()


asyncio.run(main())
Output
What's the status of O-1001? -> Order O-1001 (Desk lamp) has been delivered; total $49.00.
Write me a poem about Mondays. -> Sorry, I can only help with orders.

The triage node returns structured output (output_schema=Triage), and on_output routes on one of its fields, like add_conditional_edges with a routing function. One difference to know: a PromptNode with inject_tools=True runs the whole tool loop inside the node. So LangGraph's agent + ToolNode + tools_condition trio becomes one node, and you only draw the edges between larger steps.


[11]

How do you migrate from LangGraph to Promptise?

Map each LangGraph concept to its Promptise equivalent, then move one agent at a time.

LangGraph

Promptise equivalent

Notes

StateGraph(MessagesState)

build_agent() for a tool loop; PromptGraph("name", mode="static") for an explicit graph

Most tool-calling graphs become one build_agent() call

State schema and reducers

GraphState: messages plus a context dict; output_key= writes a node's output to context

No reducers to declare; messages append automatically

add_node(name, fn)

PromptNode, TransformNode (no model call), @node decorator, BaseNode subclass

graph.add_node(...)

add_edge(a, b)

graph.always(a, b) or graph.sequential(a, b, c)

add_conditional_edges(...)

graph.when(a, b, condition=...), graph.on_output(...), graph.on_tool_call(...)

Conditions take the node's NodeResult

START / END

Rendering diagram…

ToolNode + tools_condition

PromptNode(..., inject_tools=True)

The tool loop runs inside the node

compile(checkpointer=...) + thread_id

conversation_store= + agent.chat(..., session_id=...)

Stores the conversation between turns, not mid-run state

interrupt() + Command(resume=...)

Text
ApprovalPolicy(tools=[...], handler=...)

Waits in-process up to timeout (max 24 hours); not durable across restarts

recursion_limit

max_agent_iterations

Counts node executions; with the default loop, one per model call

Subgraphs

SubgraphNode

Send / map-reduce

ParallelNode, FanOutNode

stream() / astream()

agent.astream(), agent.astream_with_tools()

langchain-mcp-adapters

Text
servers={"name": StdioServerSpec(...) or HTTPServerSpec(...)}

MCP is built in

LangSmith tracing

observe=True (local HTML report) or ObservabilityConfig with OTLP or Prometheus

Opt-in, no account needed

LangChain chat models

The same models: pass a model instance or a "provider:model" string

A safe order for the migration:

1. Freeze behavior. Write eval cases for the current agent: the tools it must call, the actions it must never take, the facts its answers must contain. How to evaluate AI agents in Python shows how to build them. 2. Move the tools first. Keep your @tool functions and pass them as extra_tools, or move them to an MCP server so any framework can use them. 3. Replace the loop. Start with build_agent() and your system prompt. Add the graph back only where a route or a step really needs it. 4. Move the approvals. Turn each interrupt() into a handler rule. Decide what happens on timeout: deny is the safe default. 5. Move the history. Map each thread_id to a session_id in a conversation store. 6. Drain, then switch. Checkpoints and paused interrupts don't transfer. Let open runs finish in LangGraph, and send new conversations to the new agent. 7. Run the same evals against both versions until the new one matches.


[12]

Running it in production

Long approvals

If a person may take longer than your process lives, design for it. Either keep that workflow in a framework with durable pauses (LangGraph, Pydantic AI, the OpenAI Agents SDK or Microsoft Agent Framework), or make the action itself asynchronous: the agent files a request through a tool, and a separate system executes it after approval. The second design works in any framework.

Tracing without a hosted service

Promptise records model calls and tool calls when you pass observe=True, and writes an HTML report when the agent shuts down. For a central backend, send spans over OTLP to your own collector. AI agent observability shows what to record.

Limits that raise

max_agent_iterations stops a run that reaches the limit, and raises GraphIterationLimitError if the model was still waiting for tool results. Test that your code handles it. AI agent stuck in a loop? covers loop detection.

Pin and test

Pin the framework and its dependencies, including mcp, and run your evals after every upgrade, in whichever framework you choose.


[13]

Common problems and fixes

Symptom

Cause

Fix

LangGraph raises GraphRecursionError on a normal task

The limit counts graph steps, and each tool round trip is several steps

Raise recursion_limit in the config, or cap model calls instead

An interrupt never pauses the run

No checkpointer, or the resume uses a different thread_id

Compile with a checkpointer and reuse the same config

The model errors after a rejected tool call

The tool call has no ToolMessage answer

Add a DENIED ToolMessage, as review does, or use Promptise's gate, which adds it

A Promptise graph raises "has no entry node"

Static graphs need an explicit entry

Call graph.set_entry("name")

A terminal node answers the user's request anyway

Its instructions are too soft

Tell the node exactly what to reply and what not to do

A pending approval is lost after a deploy

Promptise approval handlers wait in-process

Drain before deploys, or make the action asynchronous

Tools behave differently after the migration

Tool descriptions or argument names changed

Keep the tool objects unchanged and compare eval results


[14]

Limitations

  • This is not a benchmark. It compares documented features and shows one agent. With the same model and tools, answers depend mostly on the model.

  • Promptise approvals are not durable. A pending approval does not survive a restart, and Promptise has no equivalent of resuming a run from a mid-run checkpoint. Its runtime journal records process state for crash recovery between invocations, not inside one.

  • Graph semantics differ. A Promptise PromptNode with tools runs a full tool loop, while a LangGraph node is one function call. Very fine-grained graphs need rethinking, not a line-by-line port.

  • Features move quickly. Check the docs of the versions you install.

  • We make Promptise. We checked every claim about other frameworks against their documentation and pointed out where LangGraph is the better choice.


[15]

Frequently asked questions

What is the best alternative to LangGraph?

It depends on what you need. For tool-calling agents with less code, Promptise Foundry, Pydantic AI or the OpenAI Agents SDK. For explicit graphs in another ecosystem, Microsoft Agent Framework workflows, Pydantic Graph, LlamaIndex Workflows or Google ADK. For role-based teams of agents, CrewAI. If you need runs that pause for days and resume after restarts, LangGraph remains one of the strongest options.

Is LangGraph overkill for simple agents?

Often, yes. A single agent that calls a few tools needs a model, the tools, a stop condition and a step limit. LangGraph's Graph API asks you to also define state, nodes and edges. LangChain's create_agent reduces that, and frameworks like Promptise or Pydantic AI build the loop in. The graph pays off when the workflow has real branches, parallel steps or long human pauses.

Does LangGraph require LangSmith?

No. LangGraph is an MIT-licensed library that runs without LangSmith, and tracing is off unless you enable it. LangGraph Studio, the visual debugger, needs a LangSmith account and API key, and the managed deployment option is part of LangSmith's paid plans. Other tracing tools work through LangChain callbacks or OpenTelemetry.

Can I migrate from LangGraph without rewriting my tools?

Yes. LangChain @tool functions work in Promptise through extra_tools= without changes, and tools served over MCP work in every major framework. What you rewrite is the code around the tools: the graph, the approval and resume logic, and the history handling. Checkpointed threads and paused runs don't transfer, so let them finish first.

What replaces LangGraph's interrupt in Promptise?

An ApprovalPolicy on the agent. You list the tools that need approval and give a handler that returns approve or deny. The handler can ask a person through Slack, a web UI or a webhook, and the run waits up to a timeout. Unlike a checkpointed interrupt, the wait happens in the running process, so it does not survive a restart.

Is LangGraph better than CrewAI?

They solve different problems. LangGraph gives you a low-level graph with persisted state and precise control over every step. CrewAI gives you a higher-level model of agents with roles working through tasks, plus Flows for event-driven steps. For a single agent with strict approval and limits, LangGraph gives more control. For a team of cooperating agents, CrewAI needs less code.


[16]

Next steps

  • Compare seven frameworks feature by feature: Python AI agent frameworks compared.

  • Protect the migration with tests: how to evaluate AI agents in Python.

  • Design approvals that people actually answer: human-in-the-loop approval for AI agents.

  • Move your tools to MCP: build a production MCP server in Python.

  • Reference: the Reasoning Graph, approval and conversation persistence docs.

Contents

  1. 01What is the best LangGraph alternative?
  2. 02Why do developers look for LangGraph alternatives?
  3. 03How LangGraph works, and what an alternative must replace
  4. 04When to stay with LangGraph (and when to switch)
  5. 057 LangGraph alternatives and when each fits
  6. 06What you need to run the examples
  7. 07Step 1: Write the tools once
  8. 08Step 2: Build the agent with LangGraph's StateGraph
  9. 09Step 3: Build the same agent with Promptise
  10. 10Step 4: Keep explicit routing with a Promptise graph
  11. 11How do you migrate from LangGraph to Promptise?
  12. 12Running it in production
  13. 13Common problems and fixes
  14. 14Limitations
  15. 15Frequently asked questions
  16. 16Next steps

Learning paths

Want more structure? Paths put guides in order, like a short course.

See the paths →

> Frameworks and comparisons

Related guides

All guides in this topic →
  • // 01Intermediate · 17 minCrewAI Alternatives: 7 Options and How to Migrate (2026)CrewAI alternatives compared: why teams look, 7 options and when each fits, a crew rebuilt in Promptise, and a map of crews, agents, tasks and flows.
  • // 02Intermediate · 18 minMigrate from AutoGen: Agent Framework, Promptise and MoreAutoGen is archived. Compare migration paths (Microsoft Agent Framework, AG2, Promptise), map agents, group chats and termination, and port an example.
  • // 03Beginner · 7 minWhat Is an AI Agent Framework? When You Need OneWhat an AI agent framework does: the tool loop, model access, limits, approvals and tracing. When you need one and when plain API calls are enough.
  • // 04Intermediate · 22 minPython AI Agent Frameworks Compared: Which to Choose (2026)Compare Promptise, LangGraph, CrewAI, Pydantic AI, OpenAI Agents SDK, smolagents and LlamaIndex: features, the same agent in each, and which to choose.
  • // 05Intermediate · 22 minBest LLM for AI Agents: Test and Switch Models in PythonFind the best LLM for your AI agent with a tool-calling eval, then switch between OpenAI, Anthropic, Azure, Bedrock, Gemini and Ollama in one line.
  • // 06Intermediate · 20 minMCP vs CLI for AI Agents: Tokens, Security, When to Use EachMCP vs CLI tools for AI agents: where the tokens go, prompt caching, per-user security and when to use each or both, with runnable code and real output.

Keep going.

Browse every guide by topic and level, or follow a learning path that puts them in order.

All guidesLearning paths