DEV Community

Rushank Savant
Rushank Savant

Posted on

Day 13: The Self-Correcting Agent β€” Building Loops with LangGraph πŸ”„

Yesterday, we learned that LangGraph is all about nodes and edges. Today, we’re putting that into practice by building a Stateful Agent that can actually "think," use a tool, and then decide if it needs to do more.

In the old way (Chains), if a tool returned an error, the app crashed. In the LangGraph way, we create a loop where the agent sees the error and tries a different approach.


🧠 The Agentic Loop: Thought β†’ Action β†’ Observation

To build this, we need a graph that doesn't just go in a straight line. We need it to circle back.

  1. Agent Node: The LLM decides what to do.
  2. Tools Node: If the LLM wants to use a tool, this node executes it.
  3. The Loop: The result of the tool goes back to the Agent so it can "observe" the result and decide if it's done.

πŸ› οΈ Coding the Loop

We'll use the ToolNodeβ€”a pre-built helper from LangGraphβ€”to make this easy.

from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults

# 1. Define the State (Our notebook)
class State(TypedDict):
    # add_messages tells LangGraph to append new messages to history
    messages: Annotated[list, add_messages]

# 2. Setup Tools and Model
tools = [TavilySearchResults(max_results=2)]
model = ChatOpenAI(model="gpt-4o").bind_tools(tools)

# 3. Define the Nodes
def chatbot(state: State):
    return {"messages": [model.invoke(state["messages"])]}

# 4. Build the Graph
workflow = StateGraph(State)

workflow.add_node("chatbot", chatbot)
# ToolNode automatically executes tool calls found in the messages
workflow.add_node("tools", ToolNode(tools))

# 5. Define the Logic (The "Brain")
workflow.add_edge(START, "chatbot")

# Conditional Edge: If the model called a tool, go to 'tools', 
# otherwise, go to 'END'.
workflow.add_conditional_edges("chatbot", tools_condition)

# Loop back! After using tools, go back to the chatbot to see if it's done
workflow.add_edge("tools", "chatbot")

graph = workflow.compile()
Enter fullscreen mode Exit fullscreen mode

⚑ Why tools_condition is Magic

This is a built-in "traffic controller." It looks at the last message from the AI:

  • If it contains a tool_call, it sends the flow to the tools node.

  • If it is a regular string, it realizes the AI is finished and sends it to END.

This prevents the AI from getting stuck in an infinite loop!


🎯 Day 13 Summary

Today, you built a truly autonomous agent. You learned:

  • Cyclic Graphs: How to point an edge back to a previous node.

  • ToolNode: Automating the execution of AI-requested actions.

  • Conditional Routing: Letting the graph decide its own path.

Your Homework: Imagine the search tool returns "No results found." Because of the loop we built today, the AI can see that and try a different search query automatically. Try to prompt your agent to find something obscure and watch it work!

See you tomorrow! β˜•

Top comments (0)