TT Lab
Get started
Learn Learning paths Courses

AI Agents — A Graph, Not a Model

LangGraph — Build an Agent That Stops

Continue in TT Lab

Goal

You build a small agent with LangGraph that answers questions about inventory. It has eight steps: a graph, accumulating state, a conditional branch, a loop that stops, a tool node, a failure path, a checkpointer and a path record.

No model is called

The node that makes the judgment is written as rules. This is because what this lab teaches is the graph, not the model call — when to stop, what to carry in the state, and where to go when a tool fails. That is where the real difficulty in agents is, and attaching a model is later a matter of swapping one node.

Format

Put the following in /root/work/agent/graph.py.

The state has at least question, steps (a list), tries (an integer) and answer.

Set up a graph and run it

After mkdir -p /root/work/agent, put build_graph() in graph.py. Create a StateGraph, add one node, and return the result of compile(). Put a steps list in the state and have the node leave its own name in it.

build_graph().invoke() runs and the node name is left in steps

Make the state accumulate

Increase the nodes to two and have both leave their names in steps. If you do not use Annotated[list, operator.add], only the last one remains — the path taken disappears.

It passes through two or more different nodes and all of them remain in steps

Split the branch by the question

Build the branch with add_conditional_edges. A question containing the word for "stock" (inventory) goes to the lookup node, and anything else goes to another node.

A stock question passes through lookup and a greeting does not

Loop, but always stop

Build a loop that retries when it cannot find the item. Put tries in the state and set a limit (about 3 attempts). Without a limit, it hits the recursion limit and dies with an exception.

The loop runs at least twice and stops by itself within 5 times

Actually use the tool's result

Put at least 3 entries in the CATALOG dictionary (item: quantity), and have lookup find the item in the question and look it up. The looked-up value must actually go into answer.

The value from CATALOG is reflected in answer

A tool failure is a path, not an exception

If you ask about something that is not in the list, go to a fallback node and make "could not find it" the answer. If you pass the empty result along as it is, it will make things up, and that is the most common route to hallucination.

A question about a missing item passes through fallback and answer carries the meaning "I don't know"

Continue the conversation

Make it accept build_graph(checkpoint=True) and attach a MemorySaver. Check whether the state is separated by thread_id — the same id continues and a different id is kept separately.

The state remains through get_state and is managed separately per thread_id

Record the path taken

Run two questions that take different branches and save {질문: [노드, ...]} (a mapping from each question to its list of nodes) to /root/work/agent/08-trace.json. If the record differs from the actual execution, you cannot diagnose anything from that record.

The paths in 08-trace.json match the actual execution and the two paths differ from each other