Sprint 0 · Foundations

Agent architecture from scratch

Build

Concept

What an agent actually is

The word "agent" gets used loosely. Anthropic's Building Effective Agents draws the line cleanly: a workflow is a system where the control flow is fixed in code — the developer decided the sequence. An agent is a system where the model itself decides the sequence of steps at runtime. That distinction matters because it changes who bears the risk of a wrong decision.

The minimal form of an agent is a loop with four phases, described in the ReAct paper (Yao et al., 2022): perceive (receive the goal and any accumulated observations), reason (decide what to do next — call a tool or declare an answer), act (execute the tool call), observe (record the result and feed it back). That four-phase cycle, repeated until a stop condition is met, is the architecture underneath every agent in this track — regardless of how many layers of framework are on top.

The Golden Rule

Never ask an LLM to do something a deterministic function can do reliably. Arithmetic, date math, regex matching, schema validation — these belong in tools, not prompts. The model's job is to decide which tool to call and with what argument. The tool's job is to execute correctly. Keep that boundary explicit in every agent you build.

Agents vs. workflows — when each is warranted

Building Effective Agents makes an observation that is easy to miss: most production AI systems should be workflows, not agents. Agents trade predictability for flexibility. A multi-step form processor, a document classifier, a code-review pipeline — these have well-defined control flows that benefit from the reliability and debuggability of explicit orchestration. You reach for an agent when the task requires dynamic sequencing that cannot be anticipated at design time: open-ended research, adaptive planning, tasks where the right next step depends on what was just learned.

Core principle

The ReAct paper showed that interleaving reasoning traces with action calls produces substantially better task completion than either chain-of-thought (reasoning without acting) or vanilla action sequences (acting without explicit reasoning). The perceive → reason → act → observe loop is not just an implementation pattern — it is the pattern that makes a capable model usefully agentic. The loop gives the model a scratchpad: each observation updates the reasoning state before the next decision.

The stop condition problem

An agent with no hard stop is a liability. The decide() function can always return another tool call; the loop will run until the system crashes, the budget is exhausted, or a user intervenes. Every production agent needs at least one deterministic termination condition — a maximum step count, a token budget, a wall-clock timeout — in addition to the model's self-reported "I'm done." Sprint 0's reference agent uses max_steps=6; that is not a real production guardrail, but it is the right place to put one.

Build

What to build this sprint

The reference implementation at projects/sprint-0/agent.py is a complete, runnable example. Read it before writing your own. Your job is to understand every line, then build a version that you can explain without notes.

  1. Run the reference agent. From the repo root:
    bash
    $ python agentic-engineering/projects/sprint-0/agent.py
    14
    Operator-precedence respected: 2 + 3 * 4 = 14, not 20. The safe AST evaluator handles this correctly.
  2. Trace the loop by hand. Open agent.py and add a print() statement inside the for loop that shows the current step number, the decision returned by decide(), and the observation. Run it again. You should see exactly one iteration before the loop exits via "final". Understand why.
  3. Add a second tool. Write a reverse(s: str) -> str tool that returns the reversed string. Add it to the tools dict. Extend decide() (still no real model call — use conditionals) so that goals containing the word "reverse" route to the new tool. Verify it works with a new goal string.
  4. Write your README. In projects/sprint-0/README.md (you can extend the provided file or rewrite from scratch), explain each of the four loop phases in your own words and answer: what would break first if this agent were given a goal that required 10 sequential tool calls? What would break second?
  5. Write your production paragraph. Add one paragraph to your README titled "Where this breaks in production" — your personal hit-list for Sprint 7. Consider: input validation, output schema enforcement, prompt injection, rate limits, secrets, audit logging. You will revisit this paragraph in Sprint 7 and tick off what you fixed.
When you are done

Your agent.py runs, your README.md exists and contains the production paragraph, and you can explain decide()'s role without looking at the code. That is the Sprint 0 ship condition. The checklist below is injected automatically from the course config.