Sample article — realistic starter content for NeuralSys. Replace with your own writing anytime; the pipeline (MDX → Git → Vercel) stays the same.
Introduction
A year ago, an "AI agent" meant a clever prompt and a demo. Today it means a long-running software system: tools, memory, retries, budgets, evaluation, and observability.
The prompt is maybe 5% of the work. The other 95% is systems engineering.
From LLM Calls to Systems
A single LLM call is stateless and forgetful. An agent wraps that call in a control loop:
User
|
v
AI Agent
|
+------> LLM (reasoning)
|
+------> Context Engine (memory + retrieval)
|
+------> Tools (code, APIs, browsers)
|
+------> Evaluator (did it work?)Each arrow is an engineering decision: timeouts, retries, schemas, budgets, fallbacks.
The Anatomy of a Reliable Agent
1. A typed tool interface
Tools should look like function signatures, not prose. Validate inputs with schemas, return structured results, and version them.
from pydantic import BaseModel
class SearchArgs(BaseModel):
query: str
top_k: int = 5
def search_tools(args: SearchArgs) -> list[dict]:
"""Deterministic wrapper around retrieval."""
results = retriever.search(args.query, k=args.top_k)
return [{"title": r.title, "score": r.score} for r in results]2. Bounded execution
Every loop needs a budget: max steps, max tokens, max wall-clock time, max spend. Unbounded agents are incidents waiting to happen.
const policy = {
maxSteps: 12,
maxTokens: 24_000,
timeoutMs: 120_000,
onBudgetExceeded: "summarize-and-ask",
};3. Memory that is actually retrieval
"Memory" in agents is almost always context assembly: recent turns + retrieved documents + structured state, ranked and truncated to fit the window.
Context Engineering
The highest-leverage skill in agent building is deciding what goes into the prompt on each step:
| Layer | Source | Lifetime |
|---|---|---|
| System instructions | Static config | Session |
| Task state | Planner / DB | Task |
| Working memory | Recent turns | Minutes |
| Retrieved knowledge | Vector DB / graph | Per step |
| Tool outputs | Live calls | Per step |
Evaluation Before Scale
If you cannot score an agent run, you cannot improve it. Start with three things:
- A golden task set — 20–50 realistic tasks with checkable outcomes.
- Trajectory logging — every step, tool call, and token count.
- A failure taxonomy — wrong tool, bad retrieval, premature stop, format drift.
Implementation Sketch
A minimal agent loop fits in a page of code. Everything else is hardening:
def run_agent(task, tools, llm, budget):
state = {"steps": 0, "history": []}
while state["steps"] < budget.max_steps:
context = assemble_context(task, state) # the real work
action = llm.decide(context)
if action.type == "finish":
return action.answer
result = tools.execute(action, timeout=budget.tool_timeout)
state["history"].append((action, result))
state["steps"] += 1
return summarize_and_ask(task, state)Key Takeaways
- Agents are distributed systems with an LLM inside, not prompts with tools bolted on.
- Budgets, schemas, evaluation, and observability are the product.
- Context assembly is the highest-leverage layer to invest in.
- Start narrow, measure everything, then widen autonomy.
Next in this series: context engineering as the missing layer, and why RAG is a retrieval problem first.