Skip to course content
Free LangGraph course

LangGraph for Agentic Workflows

Unit 01.04: Choosing the smallest structure that fits

There are four structures between a plain function and a full graph, and most workflows land in the middle two.

Work down the list, not up

Plain function, function with a conditional, explicit state machine, graph. Each row up the list buys expressiveness and charges debugging cost.

The code lays out all four with what each one fits.

OPTIONS = [
    ("plain function",   "one path",                    "trivial"),
    ("function + if",    "two paths, no cycle",         "easy"),
    ("state machine",    "several paths, no model step", "moderate"),
    ("graph",            "cycles, pausing, or resuming", "high"),
]

print(f"{'structure':18} {'fits when':30} debugging cost")
for structure, fits, cost in OPTIONS:
    print(f"{structure:18} {fits:30} {cost}")

print("""
Work down this list, not up. Start with the plain function and move one row
only when you hit something it genuinely cannot express.

The common failure is starting at the bottom because the problem sounds
agentic. A graph with one linear path is a function with extra machinery
between you and the bug.
""")

The row worth noticing is the state machine: several paths, no model step, moderate cost. A great many workflows described as agents are this - deterministic routing over a few outcomes - and a state machine is easier to exhaustively test than a graph because it has no cycles.

Move one row only when you hit something the current row genuinely cannot express. The move should be forced by a requirement you can name.

The mistake this prevents

There is a second axis this table does not show, and it matters more for risk than structure does: how much the workflow is allowed to do without a person. Autonomy is a spectrum - suggesting something a human then does, acting only after explicit approval, or acting alone - and it is chosen independently of whether you use a function or a graph. What grows with it is the window in which the system can take a consequential action before anyone can intervene. A linear function that sends emails unattended carries more operational risk than an elaborate graph that only drafts. Decide the autonomy level explicitly, write it down, and let it drive how many controls Module 7 makes you build.

The mistake is starting at the bottom because the problem sounds agentic. A graph with one linear path is a function with machinery between you and the bug: an extra layer of state merging, an extra place for a routing error, and a stack trace that goes through the framework rather than your code.

Takeaway

Start with the smallest structure and move up only when a specific requirement forces it. The forcing requirement is almost always one of three: a cycle, a pause, or a failure path that must not crash the run.