A minimal, production-shaped agent has four parts: a planner/loop, tools, memory, and guardrails. This guide walks through each so you can build the scaffold yourself in an afternoon — before you ever need a framework.
The runnable GitHub template that mirrors this guide is being published right now — leave your email below and you'll get the link the day it's public. Everything you need to build it yourself is here in the meantime.
1 · The agent loop
The core loop is simpler than it looks:
observe → decide (call a tool or answer) → act → observe result → repeat
Implement this as an explicit loop you can read and step through — not a black box. Cap the number of iterations (e.g. 6–10) so a confused agent can't loop forever, and log every step (what it decided, why, what happened).
2 · Tools
- Define each tool with a strict schema (name, description, typed arguments).
- Validate arguments before execution — never trust model-generated input to a tool that has side effects.
- Keep tools narrow and composable (
get_order,issue_refund) rather than one giantdo_anythingtool. - Return structured results, not free text, so the model can reason over them reliably.
3 · Memory
- Short-term: the conversation/task history, windowed to fit the context budget — summarize or drop the oldest turns rather than truncating blindly.
- Long-term (optional): a vector store or key-value store for facts that should persist across sessions (user preferences, prior decisions).
- Be explicit about what the agent is allowed to remember and for how long — memory is a privacy surface, not just a feature.
4 · Guardrails
- Input validation: reject or sanitize obviously malicious input before it reaches the model.
- Action confirmation: anything irreversible or money-moving gets a confirmation step (human-in-the-loop) or a hard cap, not a bare tool call.
- Output constraints: validate the model's output against the tool schema before executing it — malformed or out-of-scope calls get rejected, not run.
- Prompt-injection defense: treat tool outputs and retrieved documents as untrusted data, not instructions. The model should never follow a command embedded in a tool result.
5 · Suggested repo layout
agent/
├─ loop.py # the observe → decide → act loop
├─ tools/
│ ├─ registry.py # tool schemas + validation
│ └─ ... # one file per tool
├─ memory/
│ ├─ short_term.py
│ └─ long_term.py # optional
├─ guardrails/
│ ├─ input_checks.py
│ └─ output_checks.py
├─ tracing.py # log every decision, tool call, and result
└─ eval/
└─ scenarios.py # scripted tasks the agent must complete correctly
6 · What to build first
- One tool, no memory, hard iteration cap. Get the loop working end to end.
- Add tracing before you add a second tool — you'll need it to debug.
- Add guardrails on the first tool with side effects.
- Add short-term memory once multi-turn tasks show up in your eval scenarios.
Want this built out further — a full agent framework comparison, deployment patterns, and a graded project? That's in the AI Engineer Interview & Portfolio Kit.