Building Agentic AI systems: a practical tutorial with real code
Overview: From “toy agent” to production system
Agentic systems are just graphs: nodes that do work (LLM calls, tools, other agents), edges that decide what happens next, and a state object that everything reads and writes. LangGraph makes that graph explicit, which is what lets you add planning loops, human checkpoints, retries, and multi-agent patterns without everything turning into spaghetti.
langchain-ai.github
+1
Assume Python, LangChain models, and LangGraph StateGraph. The examples focus on structure rather than every import; you can paste each block into a small file and run it after wiring in your model and tools.
docs.langchain
+1
Core setup: state and a basic tool-calling agent
Define a state schema that represents “everything the agent knows right now”. LangGraph uses this as the contract between nodes.
langchain
python
from typing import TypedDict, List
from langgraph.graph import StateGraph, END
from langchain_core.messages import AnyMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
class AgentState(TypedDict):
messages: List[AnyMessage]
plan: str
scratchpad: str
@tool
def get_weather(city: str) -> str:
"""Look up current weather for a city."""
# Dummy implementation
return f"It's always sunny in {city}."
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
tools = [get_weather]
llm_with_tools = llm.bind_tools(tools)
Now build a single-node tool-calling agent: the node calls the LLM with tools bound; LangGraph automatically executes tools and appends results to messages when the model emits tool calls.
langchain-ai.github
python
def agent_node(state: AgentState) -> AgentState:
response = llm_with_tools.invoke(state["messages"])
return {"messages": state["messages"] + [response]}
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.set_entry_point("agent")
graph.add_edge("agent", END)
app = graph.compile()
You now have a minimal, stateful tool-calling agent; invoke it with:
python
result = app.invoke({"messages": [HumanMessage(content="What's the weather in London?")]})
How would you extend this minimal state to support, say, a task-level goal distinct from the raw conversation history?
Multi-agent orchestration with a supervisor
A common pattern is a “supervisor + specialists”: one LLM routes tasks to sub-agents (e.g., “planner”, “researcher”, “coder”). LangGraph lets each agent be a node or even a subgraph that reads/writes shared state.
reddit
+1
Define roles in state and separate nodes:
python
class MultiState(TypedDict):
messages: List[AnyMessage]
active_role: str # "planner" | "researcher" | "coder" | "done"
planner_llm = llm
researcher_llm = llm_with_tools
coder_llm = llm
def planner_node(state: MultiState) -> MultiState:
resp = planner_llm.invoke(
state["messages"] + [
HumanMessage(content="You are a planner. Break the user goal into steps.")
]
)
return {
"messages": state["messages"] + [resp],
"active_role": "researcher",
-
Rizwan Saleem | https://rizwansaleem.co
Top comments (0)