Tier I — Foundations¶
The bar: you can get a model to return something your code can trust — and act on, once.
L0 — The Call¶
CORE — You can get a model to return something your code can trust.
Before an agent, before tools, before any of it — the atom is a single model call whose output your program can consume without a human in the loop. Most reliability problems higher in the stack are actually unsolved L0 problems. If one call can't reliably return valid structured data, nothing you stack on top will be reliable either.
Get the atom right first.
Input → Model call → Validate (schema) → pass → EMIT
fail → REPAIR ↻
The atom. A single call is only trustworthy once it's validated and can repair a bad parse — the seed of every loop above it.
What you're actually learning¶
The request/response contract — messages and roles, and how the system prompt sets durable behavior while the user turn carries the task. Then sampling and determinism: temperature and top-p, why the same prompt yields different outputs, and when to drive temperature to zero for extraction and classification versus keeping it up for generation.
The core skill of the whole rung is structured output — the difference between prose you read and data you parse. That runs from JSON mode, to using a tool/function schema as the output shape, to the deeper move of constrained (grammar-guided) decoding that makes malformed output structurally impossible rather than merely discouraged. Paired with it is schema enforcement and repair: validate against a typed model, and when it fails, feed the validation error back and retry within a bounded budget.
Underneath sits token economics: input versus output tokens, why prompt size is a cost and latency lever, and the context window as a hard budget you are already spending on turn one.
Concepts to master¶
- Roles — system vs. user vs. assistant, and what belongs in each.
- Determinism controls — temperature / top-p; when zero, when not.
- Structured output — JSON mode vs. tool-schema output vs.
constrained/grammar decoding. - Validation + repair — typed-schema (Pydantic-style) validation and the parse-error retry loop.
- Idempotent, retryable calls — a single call you can safely re-issue.
- Token accounting — input/output cost and latency; counting before you call.
- Prompt-as-contract — one call's prompt is a spec (the seed of L7).
- Output failure modes — truncation, schema drift, and detecting them.
- Format priming — few-shot examples and system prompts that lock shape.
- Prompt caching — reusing a stable system prompt to cut cost and latency.
What you build
A CLI that takes arbitrary text and returns a validated object — e.g. {summary, topics[], sentiment, confidence} — against a typed schema, with a repair path that catches a malformed response, feeds the validation error back, and retries within a bounded number of attempts before failing loudly.
Clear it when¶
- ☐ 20+ runs on varied input return 20+ valid objects, zero manual fixes.
- ☐ You can force a schema and programmatically recover from a bad parse.
- ☐ You can explain why your extraction runs at temperature zero.
- ☐ You can state the token cost of a call before you make it.
Where people get stuck¶
- ✗ String-parsing model output instead of validating structured data — the original sin; every flaky agent traces back here.
- ✗ Trusting the first response with no repair loop.
- ✗ Leaving temperature high on a task that needs determinism.
- ✗ Treating the context window as infinite.
Connects
Bottom of the model/prompt foundation — no loop yet. The repair loop here is the seed of the runtime loop at L2; prompt-as-contract is the seed of spec-driven development at L7.
L1 — The Single Action¶
CORE — The model can do one thing — not just say things.
Tool use is where a language model stops being a text generator and becomes something that can affect the world. But the first version is deliberately not a loop — it's a single round trip. Getting that round trip clean, with the model (not your code) deciding whether to act, is the whole lesson. This is the hinge between "chatbot" and "agent."
One hop, done right.
1 · Expose tool + schema → 2 · Model requests call → 3 · Code executes → 4 · Model answers
One hop, not a loop.* The model decides whether and which* — your code never routes. Master this before adding iteration.
What you're actually learning¶
The tool-calling round trip, in four steps and one hop: you expose tools with schemas; the model emits a structured tool-call request; your code executes and returns a tool-result message; the model produces its final answer using that result. Not iteration — a single exchange.
Tool schemas are contracts — name, description, typed parameters — and the description is prompt engineering, because the model routes on it. Vague descriptions cause bad routing. The competence to build is model-decides, not code-decides: the model chooses whether and which tool to call. If your code hardcodes the call, you built an if-statement in a costume.
Result formatting matters as much as the call — the model has to consume what you return, and errors should come back as tool results, not thrown exceptions, so the model can react to them. And you learn the boundary: why this is explicitly one hop, so you can isolate "can it call correctly" before adding "can it decide when to stop."
Concepts to master¶
- The four-step round trip — expose → request → execute → answer.
- Schema design — description-as-routing-signal; typed parameters.
- Argument validation — check args before execution.
- Result shaping — return model-consumable results, including errors.
- Parallel tool calls — multiple calls in one turn, and when that's safe.
- Hop vs. loop — knowing this is one exchange, not iteration.
- Result grounding — answer from the result; don't reason around it.
- Tool vs. inline reasoning — when a call earns its cost over thinking.
- Sequential vs. parallel — dependency-aware call ordering.
What you build
A one-tool (then two-tool) assistant. Give the model a calculator and a lookup function; it must decide whether the query needs a tool at all, pick the right one, call it with well-typed arguments, and answer from the result — with no hardcoded routing.
Clear it when¶
- ☐ The model correctly declines a tool when the answer doesn't need one, and calls the right one when it does.
- ☐ Malformed arguments are caught before execution; tool errors return as recoverable results.
- ☐ You can add a second tool without rewriting your control flow.
Where people get stuck¶
- ✗ Hardcoding "always call the tool" — code deciding, not the model.
- ✗ Vague tool descriptions that cause mis-routing.
- ✗ Throwing on tool failure instead of returning an error result.
- ✗ Jumping to a loop before the single hop is solid.
Connects
Top of the model foundation / the tool-dispatch primitive at the floor of the harness. The next rung turns this single hop into a cycle — and that's where the hard part lives.