Learnixo
Back to blog
AI Systemsintermediate

Entry Points, Finish Points, and Graph Compilation

Configure entry and finish points in LangGraph. Understand set_entry_point, set_finish_point, multiple entry points, and what graph compilation does.

Asma Hafeez KhanMay 16, 20264 min read
LangGraphGraph ConfigurationPython
Share:𝕏

Entry Points

Every LangGraph graph needs exactly one entry point — the first node that receives the initial state when you call invoke().

Python
from langgraph.graph import StateGraph, END
from typing import TypedDict

class State(TypedDict):
    message: str
    result: str

def process(state: State) -> State:
    return {**state, "result": f"Processed: {state['message']}"}

graph = StateGraph(State)
graph.add_node("process", process)

# Set the entry point
graph.set_entry_point("process")
graph.add_edge("process", END)

app = graph.compile()
result = app.invoke({"message": "hello", "result": ""})
print(result["result"])  # "Processed: hello"

Finish Points

set_finish_point() sets a node as the terminal state — execution ends when this node completes, without needing an explicit edge to END:

Python
graph = StateGraph(State)
graph.add_node("start", start_fn)
graph.add_node("process", process_fn)
graph.add_node("finalize", finalize_fn)

graph.set_entry_point("start")
graph.add_edge("start", "process")
graph.add_edge("process", "finalize")

# finalize is the finish point  no edge to END needed
graph.set_finish_point("finalize")

app = graph.compile()

set_finish_point is equivalent to adding graph.add_edge("finalize", END). Use whichever is clearer for your graph structure.


Using END Directly

The most common pattern uses END from langgraph.graph:

Python
from langgraph.graph import StateGraph, END

# Conditional routing to END
graph.add_conditional_edges(
    "router",
    routing_function,
    {
        "process": "process_node",
        "skip": END,  # Goes directly to end
        "error": "error_handler",
    },
)

Multiple Conditional Entry Points

Use add_conditional_edges from START for dynamic entry routing:

Python
from langgraph.graph import StateGraph, START, END
from typing import TypedDict

class QueryState(TypedDict):
    query: str
    query_type: str  # "drug_info", "interaction", "dosing"
    result: str

def classify_query(state: QueryState) -> str:
    """Route to different handlers based on query type."""
    query = state["query"].lower()
    if "interaction" in query:
        return "interaction_handler"
    elif "dose" in query or "dosing" in query:
        return "dosing_handler"
    return "drug_info_handler"

def drug_info_handler(state: QueryState) -> QueryState:
    return {**state, "result": "General drug info response"}

def interaction_handler(state: QueryState) -> QueryState:
    return {**state, "result": "Drug interaction response"}

def dosing_handler(state: QueryState) -> QueryState:
    return {**state, "result": "Dosing guidance response"}

graph = StateGraph(QueryState)
graph.add_node("drug_info_handler", drug_info_handler)
graph.add_node("interaction_handler", interaction_handler)
graph.add_node("dosing_handler", dosing_handler)

# Conditional entry from START
graph.add_conditional_edges(
    START,
    classify_query,
    {
        "drug_info_handler": "drug_info_handler",
        "interaction_handler": "interaction_handler",
        "dosing_handler": "dosing_handler",
    },
)

# All handlers go to END
for handler in ["drug_info_handler", "interaction_handler", "dosing_handler"]:
    graph.add_edge(handler, END)

app = graph.compile()

result = app.invoke({"query": "What is the interaction between warfarin and aspirin?", "query_type": "", "result": ""})
print(result["result"])  # "Drug interaction response"

What graph.compile() Does

compile() converts the graph definition into an executable CompiledGraph:

Python
app = graph.compile()

Compile-time operations:

  1. Validation: Checks that all edges reference defined nodes, entry point is set, no unreachable nodes
  2. Optimization: Pre-computes routing paths where possible
  3. Checkpointing setup: If a checkpointer is provided, configures persistence
  4. Interrupt setup: Registers human-in-the-loop interrupt points

Compilation fails with clear errors if the graph is malformed:

  • Missing entry point → ValueError: Entry point not set
  • Edge to undefined node → ValueError: Unknown node 'xyz'
  • No path to END → Detected as potential infinite loop at runtime

Compile Options

Python
from langgraph.checkpoint.memory import MemorySaver

checkpointer = MemorySaver()

app = graph.compile(
    checkpointer=checkpointer,     # Enable state persistence
    interrupt_before=["review"],   # Pause before "review" node for human approval
    interrupt_after=["generate"],  # Pause after "generate" to inspect output
    debug=True,                    # Print detailed execution trace
    recursion_limit=50,            # Max graph steps (default: 25)
)

Inspecting the Compiled Graph

Python
# Get the Mermaid diagram of the graph
print(app.get_graph().draw_mermaid())
# Output:
# %%{init: {'flowchart': {'curve': 'linear'}}}%%
# graph TD;
#     __start__([__start__]):::first
#     process([process])
#     __end__([__end__]):::last
#     ...

# Get all nodes
print(list(app.get_graph().nodes))

# Stream execution events (useful for debugging)
for event in app.stream({"message": "hello", "result": ""}):
    print(event)

Common Entry/Finish Mistakes

Mistake 1: Forgetting to set entry point

Python
graph.compile()  # Raises: ValueError: Entry point not set

Mistake 2: Node with no outgoing edge and no finish point

Python
graph.add_node("orphan", fn)  # This node has no edge to END and is not set_finish_point
# Graph may compile but execution gets stuck at "orphan"

Mistake 3: Circular import preventing START import

Python
# Wrong: END is always imported, but START may not be in older versions
from langgraph.graph import StateGraph, END  # OK for edge-based entry
from langgraph.graph import START  # Needed for conditional_edges from START

Always explicitly add graph.add_edge(node, END) or graph.set_finish_point(node) for every terminal node in your graph.

Enjoyed this article?

Explore the AI Systems learning path for more.

Found this helpful?

Share:𝕏

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.