Most agent tutorials reach for a framework on line one — LangChain, LangGraph, CrewAI, pick one. This series does the opposite. Over seven parts, we build a real support-ticket agent with no agent framework at all: a hand-written loop against a raw model SDK, explicit guardrails, and an eval set built before the agent exists.
The full code is on GitHub: akash-pal/agent-from-scratch. Every article in this series links back to the specific files it's talking about — this isn't a toy snippet series, it's a walkthrough of one real (if intentionally small) build.
Chatbot vs. agent
A chatbot answers once per turn. You send a message, it sends one back, done.
An agent runs a loop: it decides an action, executes a tool, observes the result, and decides again — repeating until the task is done or it gives up. This is the classic ReAct pattern (Reason + Act):
That loop is the entire reason the rest of this series exists. Because the agent calls tools autonomously and repeatedly, small errors compound across steps in a way a single chatbot turn never does. Propose a refund on the wrong order, and unlike a chatbot giving a wrong answer once, an agent might act on that mistake — call a tool, change state, send an email. The infrastructure this series builds — evals, tracing, guardrails, memory design — exists to bound and catch that compounding failure, not because agents are inherently harder to prompt.
Three components sit around the loop:
- Tools — each is a name + natural-language description + JSON input schema + an executor function. The description is what the LLM reads to decide when to call it — treat it as a specification, not documentation. (More on this in Part 2.)
- Memory — what the agent knows within a run and across runs. (Part 4.)
- Orchestrator — the LLM (or a graph/state machine wrapping it) that decides which tool to call next based on the current state.
Why build it without a framework first
Frameworks pay for themselves under specific conditions: multi-agent orchestration, streaming UI needs, integrated tracing, advanced retry/fallback logic, or a team of people who need a shared abstraction. None of those apply to a first agent built by one person to understand what's actually happening.
If you can't tell whether LangGraph is adding value or hiding a bug, you don't yet know what LangGraph is doing for you. Writing the raw loop first — even a bad one — gives you a mental model to evaluate any framework against later. That's the actual thesis of this whole series: build the ~100-line version, understand every step of it, then decide if you need more.
The build order this series follows
Every part below produced a real, committed artifact in the repo, in this order — and the order is deliberate, not incidental:
- Pin the use case — bounded input, bounded output, a hard cap on tool count, one measurable success metric.
- Map tools & data sources — write every tool contract before writing code.
- Build the eval set — 21 cases, written before the agent existed, so it measures against a real target instead of tuning to whatever the agent happens to do.
- Write the minimal loop — the raw ReAct loop, no framework.
- Write the system prompt — six required elements, versioned like code.
- Iterate to green — one change per fix, and a log of what broke and why.
- Add human review — approval gating on consequential actions, decided as an architecture choice, not bolted on after launch.
The use case: an e-commerce support-ticket agent
The concrete system this series builds triages and resolves inbound customer support tickets — order status questions, refund requests, and knowledge-base lookups — for a fictional e-commerce company. Five tools, one agent, real guardrails:
order_lookup and kb_search are read-only and run freely. issue_refund and send_email are gated — they require human approval before they execute, because they're consequential and hard to reverse. That distinction — which actions can run autonomously and which need a human in the loop — turns out to be an architecture decision made in Part 1 of the design, not a safety feature bolted on at the end. Part 7 covers exactly how that gating works.
What's next
Part 2: Pinning the Use Case and Writing Tool Contracts Like Specs → covers pinning the use case and writing the five tool contracts — including the specific wording change that fixed a real eval failure later in the series.


Top comments (0)