RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /How-to
  5. /How to build a LangGraph agent from scratch
HOW-TO · SUP

How to build a LangGraph agent from scratch

intermediate·30 min·By Fredoline Eruo
Target environment
Ubuntu 24.04 · Ollama 0.4.x
PREREQUISITES

LangGraph installed, Python 3.10+

What this does

Building a LangGraph agent from scratch creates a stateful, graph-based AI agent that uses a defined workflow of nodes and edges to process user requests. Unlike linear chain agents, LangGraph agents support branching logic, cyclical reasoning patterns, and conditional routing between nodes. The agent maintains state across steps, enabling multi-turn interactions with memory. The graph structure makes the agent's decision path transparent and debuggable.

Steps

Define the agent's state schema using TypedDict: class AgentState(TypedDict): messages: Annotated[list, add_messages]; next_step: str; tool_results: dict. Initialize the LLM: from langchain_ollama import ChatOllama; llm = ChatOllama(model="llama3", temperature=0). Define the tool set. Create a simple calculator tool and a web search tool using the @tool decorator: from langchain.tools import tool; @tool def calculator(expression: str) -> str: return str(eval(expression)). Bind tools to the LLM: llm_with_tools = llm.bind_tools([calculator, web_search]). Build the graph. Import StateGraph and define nodes. The agent node calls the LLM with the current messages and returns the response: def agent_node(state: AgentState): response = llm_with_tools.invoke(state["messages"]); return {"messages": [response]}. The tool_executor node detects tool calls in the last message and executes them: def tool_node(state: AgentState): last_msg = state["messages"][-1]; results = []; for tool_call in last_msg.tool_calls: result = tool_map[tool_call["name"]].invoke(tool_call["args"]); results.append(ToolMessage(content=result, tool_call_id=tool_call["id"])); return {"messages": results}. Add a should_continue routing function: def route(state): return "tool_executor" if state["messages"][-1].tool_calls else END. Create the graph: workflow = StateGraph(AgentState); workflow.add_node("agent", agent_node); workflow.add_node("tool_executor", tool_node); workflow.set_entry_point("agent"); workflow.add_conditional_edges("agent", route); workflow.add_edge("tool_executor", "agent"). Compile: app = workflow.compile(). Run: result = app.invoke({"messages": [HumanMessage(content="What is 25 * 4?")]}).

  • Record the local run evidence. Save the exact command, runtime or package version, model name if applicable, and observed output so the result can be reproduced later.

  • Confirm the local starting state. Print the active binary, package version, model name, or configuration path before changing the workflow.

  • Run the smallest complete path. Execute the minimum command or script that proves the guide works end to end on the local machine.

  • Compare against expected output. Check the final line, status code, generated artifact, or model response against the verification section before expanding the setup.

  • Record the local run evidence. Save the exact command, runtime or package version, model name if applicable, and observed output so the result can be reproduced later.

Verification

Run the agent with a simple arithmetic query and verify the final answer contains the correct result. Check the intermediate messages in result["messages"]—there should be HumanMessage, AIMessage with tool_calls, ToolMessage, and final AIMessage. Run a web search query and verify the tool was called. Test a query that requires no tools: "Hello" should return a greeting without triggering the tool executor. Verify the agent handles multiple sequential tool calls in one run by asking "What is 5+3 and then multiply that by 2?"

Common failures

LLM fails to call tools: Verify the model supports function calling—use bind_tools() correctly and check that the tool schema format matches the model's expectations. Infinite tool-calling loop: Add a max iteration check in the should_continue function: if iteration_count > 10: return END. Tool execution errors crash the graph: Wrap tool calls in try/except in the tool_node and return error messages as ToolMessage so the agent can self-correct. State not accumulating messages: Use Annotated[list, add_messages] in the TypedDict definition for the messages field. Model outputs malformed JSON for tool args: Set strict=True in the tool definition and add a format instruction to the system prompt.

  • Version mismatch - The installed package or runtime differs from the command shown; check the version first and rerun the smallest verification command.
  • Local environment drift - Another service, virtual environment, model, or path is being used; print the active binary path and configuration before changing the guide steps.

Related guides

  • build-multi-agent-supervisor-workflow
  • setup-agent-tool-use-function-calling
  • build-code-generation-agent-local-models
← All how-to guidesCourses →