AI Agents Complete Guide 2026: Build Autonomous Systems with LangGraph and AutoGen
Advertisement
AI Agents in Production 2026
An AI agent is an LLM that can take actions — browse the web, write code, query databases, send emails — in a loop until a goal is achieved. This guide covers everything you need to build reliable production agents.
- What Makes a Good Agent?
- Simple ReAct Agent from Scratch
- LangGraph: Stateful Multi-Step Agents
- Multi-Agent Systems with AutoGen
- Agent Memory Patterns
- Production Agent Checklist
What Makes a Good Agent?
A production-ready agent needs:
- Tools — functions the LLM can call
- Memory — short-term (conversation) + long-term (vector store)
- Planning — ability to decompose complex tasks
- Error recovery — retry logic, fallbacks
- Observability — logging, tracing, evaluation
Simple ReAct Agent from Scratch
from openai import OpenAI
import json
client = OpenAI()
# Tool definitions
def calculator(expression: str) -> str:
"""Safely evaluate a math expression."""
try:
return str(eval(expression, {"__builtins__": {}}, {}))
except Exception as e:
return f"Error: {e}"
def search_web(query: str) -> str:
"""Simulate web search (replace with real search API)."""
return f"Search results for '{query}': [relevant content here]"
TOOLS = {
"calculator": calculator,
"search_web": search_web,
}
TOOL_SCHEMAS = [
{
"type": "function",
"function": {
"name": "calculator",
"description": "Evaluate mathematical expressions",
"parameters": {"type": "object", "properties": {"expression": {"type": "string"}}, "required": ["expression"]},
},
},
{
"type": "function",
"function": {
"name": "search_web",
"description": "Search the internet for current information",
"parameters": {"type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"]},
},
},
]
def run_agent(task: str, max_iterations: int = 10) -> str:
messages = [
{"role": "system", "content": "You are a helpful AI agent. Use tools to accomplish tasks."},
{"role": "user", "content": task},
]
for i in range(max_iterations):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=TOOL_SCHEMAS,
tool_choice="auto",
)
msg = response.choices[0].message
messages.append(msg)
if response.choices[0].finish_reason == "stop":
return msg.content
if msg.tool_calls:
for call in msg.tool_calls:
result = TOOLS[call.function.name](**json.loads(call.function.arguments))
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": str(result),
})
return "Max iterations reached"
print(run_agent("What is 15% of 847, and search for the current Python version?"))
LangGraph: Stateful Multi-Step Agents
LangGraph is the production standard for complex agent workflows with cycles, branching, and state:
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage
from typing import TypedDict, Annotated
import operator
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
step_count: int
final_answer: str | None
llm = ChatOpenAI(model="gpt-4o")
def agent_node(state: AgentState) -> AgentState:
"""Call the LLM with current messages."""
response = llm.invoke(state["messages"])
return {
"messages": [response],
"step_count": state["step_count"] + 1,
"final_answer": None,
}
def should_continue(state: AgentState) -> str:
"""Decide whether to continue or end."""
last_message = state["messages"][-1]
if state["step_count"] >= 5:
return "end"
if "FINAL ANSWER:" in last_message.content:
return "end"
return "continue"
# Build the graph
workflow = StateGraph(AgentState)
workflow.add_node("agent", agent_node)
workflow.set_entry_point("agent")
workflow.add_conditional_edges("agent", should_continue, {"continue": "agent", "end": END})
app = workflow.compile()
result = app.invoke({
"messages": [HumanMessage(content="Plan a 3-step process to analyze a CSV file with sales data")],
"step_count": 0,
"final_answer": None,
})
print(result["messages"][-1].content)
Multi-Agent Systems with AutoGen
AutoGen enables multiple AI agents to collaborate and debate:
import autogen
config_list = [{"model": "gpt-4o", "api_key": "your-key"}]
llm_config = {"config_list": config_list, "timeout": 60}
# Define specialized agents
engineer = autogen.AssistantAgent(
name="Engineer",
llm_config=llm_config,
system_message="""You are a senior software engineer.
Write clean, production-ready Python code with proper error handling.
Always include type hints and docstrings.""",
)
critic = autogen.AssistantAgent(
name="Critic",
llm_config=llm_config,
system_message="""You are a code reviewer who finds bugs, security issues, and performance problems.
Be specific about line numbers and provide concrete improvements.""",
)
user_proxy = autogen.UserProxyAgent(
name="User",
human_input_mode="NEVER",
max_consecutive_auto_reply=10,
code_execution_config={"work_dir": "coding", "use_docker": False},
)
# Start the conversation
user_proxy.initiate_chat(
engineer,
message="Write a Python function that reads a large CSV file efficiently and returns summary statistics",
)
Agent Memory Patterns
from langchain.memory import ConversationBufferWindowMemory
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
# Short-term memory: last N messages
short_term = ConversationBufferWindowMemory(k=10, return_messages=True)
# Long-term memory: vector store of important facts
embeddings = OpenAIEmbeddings()
long_term_db = Chroma(persist_directory="./agent_memory", embedding_function=embeddings)
def remember(fact: str):
"""Store important information for later."""
long_term_db.add_texts([fact])
def recall(query: str, k: int = 3) -> list[str]:
"""Retrieve relevant memories."""
docs = long_term_db.similarity_search(query, k=k)
return [d.page_content for d in docs]
# Agent with memory
def memory_agent(user_input: str) -> str:
# Recall relevant past context
memories = recall(user_input)
context = "\n".join(memories) if memories else "No relevant memories."
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": f"Relevant past context:\n{context}"},
{"role": "user", "content": user_input},
],
)
answer = response.choices[0].message.content
# Store key facts from this interaction
remember(f"User asked: {user_input}\nAnswer: {answer[:200]}")
return answer
Production Agent Checklist
- Timeouts: Set max execution time per tool call
- Retry logic: Exponential backoff on API failures
- Logging: Log every tool call and LLM response
- Human-in-the-loop: Flag high-risk actions for approval
- Rate limiting: Prevent runaway agents from blowing your API budget
- Evaluation: Test with a suite of known tasks and expected outcomes
- Sandboxing: Run code execution in Docker containers
Advertisement