Skip to content

Lecture 3. Architectures of AI systems: agents, RAG, API

Lecture 3 · ~105 min · 67 slides

01 · "Magic pill": the myth that the model is more accurate if you ask it as an expert and complicate the prompt

Slide 1. "Magic pill": the myth that the model is more accurate if you ask it as an expert and complicate the prompt

On February 14, 2024, the Civil Resolution Tribunal of British Columbia issued its decision in Moffatt v. Air Canada. The story is simple. Passenger Jake Moffatt visited the airline's website after his grandmother's death, asked the chatbot about the bereavement fare, and got the answer: you can buy the ticket at the regular price and then, within 90 days, file a claim to get the difference back. That was untrue — Air Canada's real policy did not allow a retroactive refund under such a fare, and this was written on the very page the chatbot even linked to. Moffatt bought the tickets, filed the claim, was refused, and the case reached the tribunal. The airline defended itself with the argument that the chatbot is "a separate legal entity responsible for its own actions."[1,2] The tribunal rejected this argument and ordered Air Canada to reimburse the passenger for the difference.

What interests us in this story is not the legal side but the engineering one. The task was elementary: show the user a fixed, known-in-advance fare policy. For such a task there exists an architecture that works perfectly and costs almost nothing: a static page or a deterministic lookup in a rules table. Air Canada chose instead a generative chatbot — an architecture that is fundamentally capable of composing a nonexistent policy, because its job is to generate plausible text, not to retrieve a verified fact.

This was not a model failure. It was the wrong architecture choice for the task. And it is exactly this class of errors — the architecture choice — that this entire lecture is about. Before going further, ask yourself: if the task is merely "look up the fare rule," what architecture closes it — and is AI even needed here at all? We will return to this answer in the section on RAG.

Sources: [1] McCarthy Tétrault — Moffatt v. Air Canada (BC CRT, 14.02.2024) · [2] ABA Business Law Today — companies are liable for their AI chatbot

02 · Lecture 3. AI system architectures: agents, RAG, API

Slide 2. Lecture 3. AI system architectures: agents, RAG, API

Today's topic is AI system architectures: agents, RAG, API. This is the last overview lecture of the course's introductory module. Lecture 1 explained what an AI model is and how a prompt is structured; Lecture 2 explained why a prompt works from the inside: tokenization, embeddings, attention, sampling. This lecture answers the next engineering question in order: how do you assemble a working system out of a model — and how do you choose which system to assemble.

There is one keystone idea running through the whole lecture, and it is worth keeping in mind all the way to the end: the choice of architecture is an engineering decision for a specific task, not a matter of following fashion. Often the right answer is the simplest architecture possible. And sometimes the right answer is to not use AI at all. We will keep returning to this idea in every section: first we will look at what a single model call can do and where its limits are, then climb the ladder of complexity — RAG, fine-tuning, agents — and at each rung ask the same question: is this complexity even needed here, and what do we pay for it.

03 · The lecture route — six sections, one load-bearing line of architecture choice

Slide 3. The lecture route — six sections, one load-bearing line of architecture choice

Before diving into the individual architectures, it helps to see the route as a whole. The lecture consists of six sections, and they are arranged not as a catalog of technologies but as a single line of reasoning. Section zero is the opening: the Air Canada case, which shows that the cost of the wrong architecture choice is quite real. The first section is the prompt and its limits: the cheapest and most predictable way to apply a model, a single call, and where it hits its ceiling. The second is RAG, retrieval-augmented generation, an add-on built on the semantic search from the previous lecture. The third is fine-tuning a model and its honest place in the lineup of "prompt vs RAG vs fine-tuning." The fourth and largest is agents: how a model becomes a component of a system through API and MCP, what an assistant agent is assembled from, where its memory lives, and how all of this breaks. And the fifth is assembly: the ladder of architectural complexity, the choice route, and a short checklist you can apply to a new task in a couple of minutes.

Running through all six sections is one keystone line, and it is worth keeping this map in front of your eyes for its sake. It is not "learn six technologies" but "learn to choose which of them to apply to a specific task — and recognize the cases where the right answer is to not use AI at all." Each section ends the same way: not only "when to apply this architecture" but also "when it should not be applied." It is precisely this ability to say a well-grounded "no" to an unsuitable tool, rather than being dazzled by the most powerful one, that the lecture teaches.

04 · Four wrappers are built around a single model call — RAG stands on Lecture 2's embeddings

Slide 4. Four wrappers are built around a single model call — RAG stands on Lecture 2's embeddings

From Lecture 2 we carry two ready-made blocks over here and will not re-explain them. The first is semantic search on embeddings from Lecture 2, section 2: text is turned into a vector, closeness of vectors means closeness of meanings, so you can search by meaning without an exact word match. RAG stands entirely on this block, and we will refer to it as known. The second block is single-shot inference from Lecture 2, section 4: a single model call is one pass with no memory between calls. It is around this single pass that we will be building up tools, loops, and agents today. If semantic search or single-shot are only vaguely remembered — it is worth rereading the corresponding sections of Lecture 2 before this lecture.

The picture on the slide sets up the structure of the whole lecture. At the center — a single model call, the most basic architecture. Around it — four wrappers we will work through. The first is RAG: this is exactly that semantic search from Lecture 2 plus generation on top of what was retrieved; the arrow from embeddings to the RAG node emphasizes that the new material here is built on top of the already familiar, rather than introduced from scratch. The second is function calling: a way to give the model the ability to reach an external system. The third is MCP: the standard by which tools connect to the model. The fourth is the agent loop: many steps around a single pass. By the end of the lecture these four wrappers will be, for you, not a list of buzzwords but a set of tools with known limits of applicability, between which you can consciously choose. The details of RAG — in Section 2; here it is only important to note that it stands on a familiar foundation.

05 · The answer to "which architecture?" is a ladder of 6 rungs; climb only for a requirement

Slide 5. The answer to "which architecture?" is a ladder of 6 rungs; climb only for a requirement

This is the central question of the whole lecture, to which we will keep returning in every section: I have a task and access to an LLM — which architecture do I choose, and when is the right answer "not AI"? Note the second half of the question. It is not rhetorical. One of the things this course teaches is the ability to say "AI is not needed here," and this lecture turns that skill into a tool.

The answer will be a ladder of six rungs — it is on the slide. Bottom-up: ordinary code without AI; a single model call with a good prompt; RAG or context engineering; a workflow with predefined paths; an agent with a dynamic loop; and at the top, multi-agent. The rule for moving along this ladder is the single and central one for the whole lecture: stay on the lowest rung that closes the task's requirements, and climb to the next only when there is an explicitly stated requirement the current rung does not close. Every climb is paid for with new failure modes, cost, latency, degraded auditability, and a new attack surface.

Note that the bottom rung is ordinary code without AI. The ladder of AI system architectures begins with the question "is AI even needed here." The Air Canada case from the opening is exactly the situation where an engineer climbed to a rung with generation where the task lived on the lower rung of deterministic code. And one last, important thing: this ladder is the lecture map, not a requirement to understand everything right now. We will work through each rung separately and, for each, state when you should not climb to it. For now it is enough to remember only the structure and the rule.

06 · Section 1 — what a single call with a good prompt can do, and where its ceiling is

Slide 6. Section 1 — what a single call with a good prompt can do, and where its ceiling is

We have just posed the central question of the lecture: there is a task and access to a language model — which architecture to choose, and when the right answer is "not AI." And we saw the ladder of six rungs in full, as a map: ordinary code, a single call, RAG, workflow, agent, multi-agent. Now the first substantive section begins, and the logic here is fundamental: we go along the ladder bottom-up, not top-down. Not "what is the most powerful tool that exists," but "is the simplest one enough, and if not — for exactly which task requirement do we climb a rung higher."

The lowest rung involving a model is a single call with a good prompt. Before talking about RAG, fine-tuning, agents, and everything everyone is buzzing about, it is engineering-honest to first understand what a single call can even do, how far it stretches, and where exactly its natural ceiling lies. Because the overwhelming majority of tasks are closed right here, cheaply and predictably, while every climb up the ladder is paid for with growth in cost, latency, and the number of ways to break everything. In this section we will work through four things: why the default is a single call; what Chain-of-thought is and where it helps; why the reasoning the model verbalizes cannot be taken as its real reason; and how to curate the context rather than dumping everything into it. And this is the boundary beyond which the next rung begins.

07 · Before the prompt, a task was posed with a precise specification and a deterministic program; a prompt is posing the task to a probabilistic system in natural language

Slide 7. Before the prompt, a task was posed with a precise specification and a deterministic program; a prompt is posing the task to a probabilistic system in natural language

Before we talk about the prompt, let us fix a starting point — the way an engineer made a system do what was needed before large language models appeared, a way that has not gone anywhere. The classical answer to "how do I get exactly what I need from a machine" rests not on phrasing a wish in natural language but on a precise specification and a deterministic program. Let us reconstruct this way from scratch, because the prompt is its direct opposite along one key axis, and that axis is only visible next to the classics.

The classical discipline of task statement relies on several named tools. A formal specification describes what a system must do in a language with no double reading: pre- and post-conditions, invariants, and in the limit machine-checkable specifications (Abrial's Z-notation, Lamport's TLA+, contract programming in the Design by Contract style). A requirements spec fixes the requirements, boundaries, and acceptance criteria — the basis on which the work is later accepted. An interface contract is a precise agreement about what a method or service accepts on input and guarantees on output (type signatures, OpenAPI, Protobuf). The common trait: the result is deterministic and verifiable.

The same discipline distinguishes two styles of stating a task. The imperative answers "how to do it" — the program lists the steps. The declarative answers "what should result" — a SELECT query does not say how to search; it describes the wanted result, and the planner decides how to obtain it. In both cases the statement had a single correct meaning and a way to check it.

Now the bridge to the rest of the section. The prompt is stating a task to a probabilistic system in natural language. Herein lies both the power and the limit. The power: no need to formally specify what cannot be specified — "rewrite this letter more politely." The limit: natural language has no single correct meaning, and the executor has no determinism. Hence the practical seam rule: use a prompt for what cannot be formally specified; leave everything that can be specified to the classics.

08 · The default is a single call; the model knows only what's in the prompt plus its weights

Slide 8. The default is a single call; the model knows only what's in the prompt plus its weights

Before choosing between RAG, fine-tuning, and agents, let us fix the reference point. The cheapest, most reliable, and most predictable AI architecture is a single model call with a well-composed prompt[1]. A single call — in Lecture 2 this was single-shot inference — has neither external search, nor a loop, nor tools: a prompt in, an answer out, no memory between calls. It has minimum cost, minimum latency, and maximum predictability: no loops that diverge, no retrieval that quietly degrades.

Let us fix the boundary that is load-bearing for the whole section: the model knows only what got into the prompt, plus what settled in its weights during training. This is the only source of information available to a single call. Everything that is in neither the prompt nor the weights is unknown to the model, and then it either honestly refuses to answer or generates plausible but ungrounded text. It is precisely this boundary that is the reason RAG appears next, expanding what is "in the prompt," and fine-tuning, expanding what is "in the weights."

The default engineering rule: do not complicate the architecture without a reason expressed in the task's requirements. This is not a call for primitivism but a distribution of the burden of proof. By default the architecture is a single call. Any move higher requires an explicit justification: here is a task requirement that a single call does not close, so I add RAG, a tool, or a loop. If no such requirement can be stated, the complexity is technical debt you take on without need.

It helps to fix what each climb costs, so that the burden of proof is an itemized list. Adding RAG, you add an indexing pipeline, a vector store, a retrieval component that can silently degrade, and metrics for its quality. Adding tools and an agent loop — external calls that fail and slow down, loops that diverge, a nondeterministic trajectory, and a new attack surface. None of these items appear with a single call. So "a single call by default" is not conservatism but a refusal to pay for infrastructure and failure modes the task does not require.

Sources: [1] Anthropic — Building Effective Agents ("find the simplest")

09 · Protocol roles system/user/assistant != a role-persona; the system priority is a tendency (~63.8%), not a boundary; STI spoofs the role

Slide 9. Protocol roles system/user/assistant != a role-persona; the system priority is a tendency (~63.8%), not a boundary; STI spoofs the role

In prompting the word "role" has two independent meanings. A persona role — "you are a lawyer" — is text in a message and affects tone. The protocol roles system/user/assistant are markup for the structure of the dialogue; not text but markup for "who is speaking." The first answers "in what tone," the second "whose turn this is."

Protocol roles exist so the model can tell the developer's instruction apart from the user's input and from its own answers. The model is trained to treat the system role as more authoritative — but this is a statistical habit, not an architectural guarantee. A study showed that GPT-4o obeys the priority of the system instruction in only 63.8% of cases. Special training raised this to 94.1% — but not 100%. Priority is a tendency, not a security boundary.

Physically the model receives a stream of tokens with role markup. The list of messages is assembled by a chat template, which wraps every message in special tokens. Hence the vulnerability: if external content — a web page, a file, a letter — contains text resembling role markup, the model may interpret it as its own turn. This is the Special Token Injection attack: a forged string imitating the start of an assistant turn is inserted into external content. A study on agent scenarios showed the attack success rate rising several-fold, and that asking the model "do not give in" barely protects it. Real defense is escaping special tokens in incoming content and checking the chat template for local models.

Special Token Injection is a particular case of prompt injection. The full treatment of injection as a class of attacks on an agent comes in the section on agents (agent security) — together with defense measures at the architecture level.

10 · Prompt structure: separate the instruction, the context, the data (parallel to structured output)

Slide 10. Prompt structure: separate the instruction, the context, the data (parallel to structured output)

If the role is responsible for tone, then the quality of the answer is far more the responsibility of the prompt's structure — how clearly the text of the request separates three different kinds of content: the instruction, that is, what to do; the context, that is, on what basis; and the data, that is, what exactly to work with. A flat prompt, where all of this is fused into a single paragraph of free text, forces the model to guess on its own the boundaries between these roles, and the longer and more heterogeneous the prompt, the higher the price of that ambiguity.

The practical tool is delimiters: explicit text markers that separate one kind of content from another. Common variants are XML-like tags, markdown headings, or triple quotes around inserted text. The specific syntax matters less than the fact of separation itself: a model that has been shown explicitly where the instruction ends and the data to be processed begins is less likely to confuse the two. In particular, it is less likely to perceive a fragment of the inserted data as a new command — and this is the same "data vs command" confusion that lies at the root of prompt injection, the attack we will examine in detail in the section on agent security.

This is the same engineering principle we will meet with structured output: there the developer sets the model a strict schema for the output, here — a structure for the input. The mechanism is different, but the idea is one: a model works better when it is clearly oriented on what is what, rather than left to infer it from the meaning of the text.

11 · Frontier models tolerate the input format; forcing an output format on a reasoning task costs quality (reasoning tax: GSM8K 76.6% -> 49.3%)

Slide 11. Frontier models tolerate the input format; forcing an output format on a reasoning task costs quality (reasoning tax: GSM8K 76.6% -> 49.3%)

There are two extreme views about prompt format, and both are wrong. The first: "format is cosmetic, the model doesn't care." The second: "there is one correct format." The real picture is more complicated: format does have an effect, but it depends on three axes — the model's generation and size, the task class, and whether we're structuring the input or forcing structure onto the output. And here's the thing everyone keeps confusing: tolerance to input format and the cost of forcing output format are two different problems, and they behave differently — sometimes in exactly opposite directions.

Start with input format — how you lay out the prompt itself. The evidence here is unambiguous: the larger and newer the model, the less sensitive it is to format. In a Microsoft study, GPT-3.5-turbo's quality swung by up to forty percent between templates on a code-translation task; GPT-4 was noticeably more robust. A 2026 replication confirms the pattern: open models consistently lost quality when format was forced — about minus 6.6 percentage points on average on MATH-500 — while closed frontier models stayed close to zero. The practical takeaway: with a small or open model, input format is worth tuning and measuring; with a 2026 frontier model, the gain from a "perfect" format is small. And the vendor habits — Claude's docs favor XML tags, GPT and Gemini lean toward Markdown headings — are an artifact of how those models were trained, not a universal law.

Output format is the second, sharper problem. Forcing a strict JSON schema on reasoning tasks hurts quality: in the paper "Let Me Speak Freely?", on the math benchmark GSM8K the model drops from 76.6% with a free-form answer to 49.3% with a forced format — minus 27 points. The baseline matters here: it's the same model, the same task, the only difference is the format requirement. The authors call the cause the "reasoning tax": a rigid schema forces the answer field to come before the reasoning field and breaks the chain of thought. The fix is a two-step "think free → reformat": let the model reason freely first, then reformat into JSON as a separate step — this recovers about 6.8 points. But the paradox has a flip side: on extraction and classification tasks, that same strict schema helps — parsing is unambiguous, and constrained decoding gets close to 100% compliance. Hence the rule: JSON is an interface between the model and code, not a format for thinking. Use it at the boundary with code, but don't force it onto "think it through and decide."

12 · Chain of thought helps on chained tasks — it is not a "better" toggle

Slide 12. Chain of thought helps on chained tasks — it is not a "better" toggle

Chain-of-thought, or step-by-step reasoning, is a technique in which the model is asked not to produce the answer at once but to first reason aloud step by step, and only then state the result. Technically this is still a single call: only the prompt and the form of the answer are changed. Look at the worked example about apples: there were 23, seven spoiled, two crates of six were bought. Without step-by-step reasoning the model often produces a plausible but wrong number, because sampling generates the answer token by token and the short path easily slips into an error. With CoT the model produces intermediate computations — 23 minus 7 equals 16; two times six is 12; 16 plus 12 equals 28[1] — and quality on arithmetic and multi-step logic rises noticeably, because each generated token serves as an anchor for attention on the next step. But "CoT almost always improves things" is a misconception: on direct fact retrieval or simple classification, reasoning does not help and can hurt — it lengthens the answer and leads into a plausible error. It is a tool for a class of tasks, not a switch to "make it better."

Now the limit of this technique, and it is more important than the technique itself. It is natural to assume that since the model reasons aloud, you can check by that reasoning how it arrived at the answer. This is fundamentally wrong. Faithfulness, the fidelity of the reasoning, is the degree to which the verbalized chain reflects the real factors that influenced the answer. Anthropic measured this directly: models were given a task with a hint that changes the answer, and it was observed whether the model mentions this hint in its reasoning. Claude 3.7 mentioned the actually used hint in about a quarter of cases, DeepSeek R1 — in about two out of five[2]; in the rest the model changed its answer under the influence of the hint but built an invented argument. The conclusion is structural: the chain is generated text, subject to the same mechanics of sampling, produced to be plausible, not to be a faithful protocol of the internal computation. Unfaithfulness is a property of the class, not a bug of a particular model. The practical conclusion and one of the course's through-lines: a human validator checks the result and the facts against an independent source, not the model's self-explanation.

Sources: [1] Wei et al. 2022 — Chain-of-Thought Prompting · [2] Anthropic — Reasoning Models Don't Always Say What They Think

13 · Chain of thought cannot be audited: faithfulness of Claude 3.7 ~25% / R1 ~39%; check the result, not the self-explanation

Slide 13. Chain of thought cannot be audited: faithfulness of Claude 3.7 ~25% / R1 ~39%; check the result, not the self-explanation

It is natural to assume that if the model reasons aloud, you can audit its decision by that explanation. This assumption is fundamentally wrong. Faithfulness is the degree to which the verbalized chain of reasoning actually reflects the real factors that influenced the answer. Low faithfulness means that the explanation and the actual cause are different things; the text is plausible but does not reflect the process.

Anthropic measured this in April 2025 by a method that makes the conclusion irrefutable. Models were given a task twice: without a hint and with a hint (for example, "the professor thinks the answer is C") that changed the answer. Then it was observed: when the hint changed the answer, does the model mention this in its reasoning? The result: Claude 3.7 mentioned the hint in roughly one case in four — 25%, DeepSeek R1 — in almost two out of five — 39%. In the rest of cases the model changed the answer but built a completely different argument, without mentioning the real cause. Worse: faithfulness drops on hard tasks, exactly where an error is most costly and audit is needed most.

This is structural, not merely a glitch. The chain of reasoning is generated text, like any output of the model. It is produced to be plausible, not to be a faithful protocol of the computation. Any architecture that uses self-explanation as a control inherits this defect: control based on self-assessment is not control. The takeaway: a human validator checks the result itself against an independent source — a database, a document, a calculation — not the plausibility of the explanation.

Sources: [1] Anthropic — Reasoning Models Don't Always Say What They Think (April 2025) — Claude 3.7 ≈25%, DeepSeek R1 ≈39% of mentions of the used hint in the reasoning.

14 · Minimal high-signal context is an engineering requirement (context rot = lost in the middle, L2)

Slide 14. Minimal high-signal context is an engineering requirement (context rot = lost in the middle, L2)

If chain-of-thought is about the form of a single call, then context engineering is about its content. Let us introduce a distinction. Prompt engineering, familiar from Lecture 1, is the wording of a single instruction: role, task, context in the text of the request. Context engineering is a broader and more iterative discipline: curating the whole set of tokens the model sees at inference[3], including system instructions, descriptions of available tools, loaded external data, and message history. The main principle is stated thus: find the smallest set of high-signal tokens that maximizes the probability of the desired outcome.

Why is minimal context not an aesthetic but an engineering requirement? Here we need to recall the effect from Lecture 2 that we called there "lost in the middle": a model makes worse use of information that landed in the middle of a long context compared to the beginning and the end. This phenomenon has acquired a second name — context rot: as the number of tokens grows, the accuracy with which the model retrieves the needed information falls. This is exactly what the graph shows: the horizontal axis is how many tokens are in the context, and the farther right along it (the longer the context), the lower the accuracy curve goes. This is the very same phenomenon as "lost in the middle" from Lecture 2, under a new practical name — I make this stitch explicit so the term is not perceived as a new entity. The mechanism is the same: the pairwise links of the attention mechanism grow quadratically with length.

The direct consequence: "just put everything into the context" is not a strategy. A large context window gives you the ability to fit a lot of text, but not a guarantee that the model will use that text correctly. And this, looking ahead, is one of the keys to the question "when NOT RAG," which we will examine in Section 2: sometimes the right answer is not to build retrieval infrastructure but to carefully curate a small stable context and reuse it via caching. That is the first practical criterion: if the knowledge corpus is small, stable, and fits in the window — RAG here would add fragility without a gain, and the right answer is simpler than it seems.

Sources: [1] Chroma Research — Context Rot · [2] Liu et al. 2023 — Lost in the Middle · [3] Anthropic — Effective Context Engineering

15 · Cheat sheet: how to build a prompt — 8 points, the compact form of Section 1

Slide 15. Cheat sheet: how to build a prompt — 8 points, the compact form of Section 1

Let us gather the whole section on the prompt into one practical tool — a short checklist you can apply to any prompt before its first run. It does not replace the rest of the material but fixes the minimum below which a prompt systematically underperforms. First: a role is set if you need a specific tone or register, and is explicitly not used as a promise of accuracy — if the task requires factual correctness, a role does not solve that task. Second: the task is stated as a concrete verifiable action, not a vague wish. Third: the context contains the minimum necessary, not everything that might come in handy. Fourth: the output format is stated explicitly if the answer must be machine-processed.

Fifth: delimiters are placed if the prompt contains more than one kind of content — instruction, context, inserted data. Sixth: examples are added only if the answer format is not obvious from the instruction alone; if the model manages without them, examples merely spend context. Seventh: step-by-step reasoning is turned on only where the task requires multi-step logic, and for direct fact retrieval — it is not needed. Eighth: it is checked that the prompt is no longer than necessary, because every extra paragraph is tokens you have to pay for and that risk sinking in the context. This checklist is not procedure for procedure's sake but a compressed summary of the whole section: a role is not equal to accuracy, structure helps separate inputs, reasoning is a targeted tool, and context is minimal, not maximal.

16 · An assistant with tools is a mini-ladder -- one-shot -> tool-use -> agent; the failure is jumping straight to an agent (the $4,200 loop, §4)

Slide 16. An assistant with tools is a mini-ladder -- one-shot -> tool-use -> agent; the failure is jumping straight to an agent (the $4,200 loop, §4)

The first task pattern is an assistant with tools. The setup is simple: the user isn't asking you to "write text" — they're asking you to "do something": look something up in an external system, or take an action. The right architecture here isn't a binary choice between "chat or agent" — it's the same ladder from the start of the section, applied to one class of tasks.

The first rung is a single call. If the model already knows the answer and no external action is needed (rephrase, explain, summarize), that's cheap, fast, and predictable. The second rung is tool-use or a workflow. If you need access to data or an action, but the sequence of steps is known in advance and can be laid out in code, the model formulates the tool call, while the control flow and the checkpoints live in code, not in the model's head. The third rung is a full agent. It's justified only when the steps aren't known in advance, on-the-fly adaptation is needed, and there's a way to check progress. The cost of climbing each rung is rising latency, cost, and the risk of compounding errors.

For this to be an engineering recipe rather than a wish, let's name what you control and how you validate it. The parameters of this class: tool granularity (coarse operations vs. atomic ones), strict input schemas validated at the boundary, the tool_choice mode (auto, forced, or disabled), and a mandatory iteration limit with a token budget — a guard against a runaway loop. Validation is two-stage: first, check the tool call's arguments before hitting the external system — reject a malformed request at the boundary and return the model a structured error it can interpret; second, check that the final answer relies on the tools' results, not on the model's memory. The second check removes what's called parametric fallback: after a tool failure, the model sometimes "decides" its own knowledge is good enough and stops searching — breaking exactly the freshness guarantee the tool was wired in for.

The most common mistake in this class is jumping straight to an agent where the task is predictable and a single tool call would have been enough. That's exactly the failure we'll walk through in the agents section: the four-thousand-two-hundred-dollar loop, where a predictable sync job was handed to an agent instead of a simple retry script. The rule: climb the mini-ladder only when the task requires it — not because "an agent sounds more powerful."

17 · Text in a given tone is few-shot from 3-5 samples; the boundary -- detectors can't be trusted (some under 80% accurate, +30% false positives on non-native writers)

Slide 17. Text in a given tone is few-shot from 3-5 samples; the boundary -- detectors can't be trusted (some under 80% accurate, +30% false positives on non-native writers)

The second class is generating text in a given tone, style, or register: a marketing email "in our brand voice," a support reply in the company's signature tone, a draft that reads "like a human wrote it." The right architecture here is few-shot style transfer: give three to five samples of the author's writing wrapped in examples, and ask for generation in the same style. This is the most reliable lever for tone and voice, and it's exactly where a persona role works the way people usually assume it does — it shapes tone, not facts.

But the boundaries of this class matter more than the technique itself, and there are two of them. First: models copy public figures and fictional characters reasonably well, but struggle with an ordinary author's individual style — personal style doesn't reduce to a handful of sliders. Second, and sharper: AI detectors are unreliable as sole evidence. Vendors themselves admit this in their documentation. Independent studies put some detectors' accuracy below eighty percent; texts by non-native speakers get flagged as machine-written noticeably more often — the baseline here is the false-positive rate relative to native speakers — and accuracy drops sharply after simple paraphrasing.

As with the previous class, let's name the parameters and validation so this is a recipe, not just advice. Parameters: formality (from "academic" to "friendly"), emotional coloring, a specific persona, the number and quality of style samples, and explicit prohibitions — no bureaucratic phrasing, no emoji, no superlatives. Validation is harder here because style is weakly formalizable: teams use an LLM judge for tone match, checks against concrete markers (sentence length, presence or absence of specific vocabulary), and spot-check human review. A typical failure with fine-grained multi-attribute control: the attributes conflict — "formal, but warm, but brief, but detailed" pull in different directions, and the model underperforms on some dimensions; on long dialogues, persona drift adds on top.

The engineering conclusion is twofold. Generating human-like text is technically possible, but passing it off as your own is an ethical and academic risk. And a detector can't be trusted either as a shield to prove a text is AI-written, or as a sword to reliably hide its AI origin. This is the same lesson as the whole chapter — observable doesn't equal guaranteed — applied to detection.

18 · "Asking for JSON" != "specifying a contract": two levels of control (prompt ~80% / decoder ~100%), three ways to specify a schema, the invariant "valid JSON != correct data"

Slide 18. "Asking for JSON" != "specifying a contract": two levels of control (prompt ~80% / decoder ~100%), three ways to specify a schema, the invariant "valid JSON != correct data"

The fourth class is structured extraction, the most common integration point between a model and code. There's a direct editorial call behind this slide: show a technique instead of a meme — how to give a JSON spec in a prompt correctly. Start with the framing that gets confused most often: there are two different levels of control with different guarantees. At the prompt level, you simply ask in text, "return JSON matching this schema" — this gives you about eighty percent validity and strictly guarantees nothing: not the syntax, not the set of fields, not the types. At the decoder level (structured outputs, or constrained decoding), the schema compiles into a grammar, and at every generation step, tokens that violate the grammar physically cannot be selected — hence near-100% schema compliance. Support is still moving as of 2026, so check on the day of the lecture: OpenAI's Structured Outputs with strict mode, Anthropic brought structured outputs to general availability on Claude 4.5, Google Gemini's responseSchema, and from open source — Outlines, XGrammar, GBNF grammars.

Next — how to describe the shape itself, three approaches with trade-offs. An example object is easy for the model to grasp but doesn't express types or enums. JSON Schema is a machine-checkable contract, but it's verbose and degrades on complex schemas. A type in code (TypeScript, Pydantic, Zod) is compact and type-safe, but needs a converter. Field descriptions carry micro-instructions: for enumerable values, spell out every option as an enum, explicitly mark required fields, keep nesting shallow. On top of that — few-shot examples of two or three "input → expected JSON" pairs, which pin down the shape better than any prose, plus two small things with an outsized effect: put the schema at the end of the prompt, and add "return ONLY JSON, no markdown."

Two nuances, and these are the real technique. Reasoning tax: strict JSON on a reasoning task hurts quality (the full breakdown with GSM8K numbers is on the formats slide), and the fix is the same "think free → reformat" two-step. And a complex schema: extraction accuracy drops even with valid JSON — the direction matters here, not the exact magnitude. The invariant that closes out this class: valid JSON ≠ correct data — the grammar guarantees the shape, not the truth of the values, so every JSON payload still gets validated in code. A strict schema reliably helps with extraction, classification, and function calling — and only there.

19 · Section 2 — RAG: retrieval-augmented generation on top of Lecture 2's embeddings

Slide 19. Section 2 — RAG: retrieval-augmented generation on top of Lecture 2's embeddings

We finished the first section: the default is a single call, it can be strengthened with step-by-step reasoning, but reasoning has a limit of faithfulness, and the context needs to be curated rather than dumped. Now — the next rung of the ladder.

A single call with a good prompt runs into a natural boundary: the model knows only what got into its weights during training, plus what you manually put into the context. If the task requires knowledge that is not in the weights — for example, a company's private database — or that changes faster than new model versions come out — for example, current prices or documents — a single call will not handle it. This is where RAG begins: retrieval-augmented generation.

In one phrase, the principle is this: before calling the model, the system first retrieves relevant fragments from an external knowledge store, puts them into the context together with the question, and only then does the model generate an answer, grounded in these fragments. In this section we will work through: how RAG is structured in three steps and why its search mechanism is exactly the semantic search from Lecture 2; when RAG is the right choice and when it is not, and why the latter matters more; and how RAG quietly breaks at scale, closing the section back to the Air Canada case from the opening.

20 · The R in RAG is retrieval: inverted index, boolean search, TF-IDF, BM25; RAG adds a semantic layer on top, the classics do not vanish

Slide 20. The R in RAG is retrieval: inverted index, boolean search, TF-IDF, BM25; RAG adds a semantic layer on top, the classics do not vanish

RAG is usually presented as a new technology grown out of embeddings. This hides something essential: the R in RAG is retrieval, search — a discipline with half a century of history, and it is exactly its design that determines where RAG works and where it breaks. Let us reconstruct classical information retrieval from scratch, how text was searched before embeddings, because without this baseline semantic search looks like magic, and it is not magic but the next layer on top of an understood foundation.

The everyday ancestor of machine search is the library catalog: cards ordered by author, title, and subject heading, plus "see also" references. Exactly this idea a machine reproduces through an inverted index — a structure that, for each word, stores a list of documents where it occurs. Instead of scanning all texts, the system looks up the query words in the index and instantly obtains candidates. This is the foundation of any full-text system and to this day the workhorse of industrial operation.

On top of the index the classics solve two tasks — selection and ranking. Selection is set by boolean search: a query as a logical expression selects documents precisely and explainably. Ranking answers in what order to show what was selected. TF-IDF weights a word the more strongly the more frequent it is in this document and the rarer across the whole collection. The industry standard to this day is BM25 from the Okapi family: a development of TF-IDF with frequency saturation and length normalization. BM25 is not an obsolete artifact but a strong, cheap baseline.

The key property of these classics — they work on lexical match: they find documents with the same words as in the query. Hence the strength on codes and identifiers and the limit on synonyms. Semantic search on embeddings adds the missing layer of meaning, but the classics do not disappear: strong RAG systems of 2026 are a hybrid of BM25 and vectors, not dense-only. RAG is an extension of classical search, and its failures are largely where the classical foundation was forgotten.

21 · RAG = indexing -> retrieval -> grounded generation; "I don't know" is a correct answer, a made-up one is a defect

Slide 21. RAG = indexing -> retrieval -> grounded generation; "I don't know" is a correct answer, a made-up one is a defect

RAG — retrieval-augmented generation — is an architecture in which, before calling the model, the system first retrieves relevant fragments from an external store, puts them into the context together with the question, and only then does the model generate an answer grounded in these fragments[1]. Let us introduce a term: retrieval — the stage of searching for and extracting relevant fragments; it is precisely this that distinguishes RAG from "put the document into the prompt manually."

The key point: the retrieval mechanism in RAG is exactly that semantic search on embeddings that we built in Lecture 2, and we will not re-explain it. A reminder in one phrase: text is turned into a vector, closeness of vectors means closeness of meaning, so a fragment can be found by the meaning of the question rather than by a word match. RAG builds up three steps. The first is indexing, in advance, offline: the corpus is cut into fragments, each is turned into an embedding and placed into a vector store. The second is retrieval, on the query: the question is turned into an embedding, and by closeness of vectors the k relevant fragments are pulled. The third is grounded generation: the fragments are placed into the context together with the question, the model answers relying on them, and in a good implementation — with a reference to the source.

Let us introduce one more term that carries the main load in this section. Grounding — the property of an answer being derived from specific retrieved fragments, rather than composed by the model out of thin air, with the ability to show which fragment each fact was taken from. A good RAG system is designed so that the answer is grounded, and so that to a question for which the retrieved fragments contain no answer, the system says "I don't know" or "see the source," rather than composing one. Let us state it as an engineering invariant: "I don't know" is a correct answer of a RAG system; a plausible answer under irrelevant retrieval is a defect, not "better than nothing." The distinction between "an answer with grounding and a citation" versus "plausible text" will turn out to be central further on and directly explains the Air Canada case.

Sources: [1] Lewis et al. 2020 — Retrieval-Augmented Generation (NeurIPS)

22 · Hybrid search = BM25 + dense vectors fused by rank (RRF), plus cross-encoder reranking; adopted for a measured gap, not by default

Slide 22. Hybrid search = BM25 + dense vectors fused by rank (RRF), plus cross-encoder reranking; adopted for a measured gap, not by default

Earlier we established: strong RAG brings classical search back on top of the semantic layer. Here that conclusion unfolds into hybrid search, which has become the production default. Why combine the two: BM25 finds exact word matches — codes, identifiers, names, error numbers — but is powerless against a synonym: "broken login" won't match "authentication failure." Dense search does the opposite: it catches meaning but blurs on rare exact tokens. Hybrid search takes both sources of recall at once.

Let's clear up two questions first. The first is "hybrid of what with what," and here it's easy to get tangled in the word "vector." Sparse search is classical lexical search: BM25 or TF-IDF, plus the learned SPLADE and ELSER, on an inverted index; the unit is the word. When people say "sparse vector," they don't mean searching by the meaning of a vector — just a way of writing word-level search: a vector as long as the entire vocabulary, with almost all coordinates at zero. It's still lexical, not semantic. Dense search is the opposite: an embedding of 384–1024 floats, meaning encoded across all coordinates, approximate search (ANN), not interpretable, catches paraphrase. In one phrase: BM25 is sparse, embeddings are dense, SPLADE is sparse too — a neural network just assigns the term weights.

The second question: the word "hybrid" carries three different senses, and they get mixed up. Sense (a), the basic one, is a fusion of two distinct branches: sparse (lexical, BM25) and dense (semantic, embedding), merged by rank via RRF. Sense (b) is semantics plus a strict metadata filter (jurisdiction, date): an orthogonal lever, not a fusion of retrievers. Sense (c) is BM25 plus SPLADE or ELSER: both branches are sparse, both are lexical — one classical, one neural-weighted; there are no semantic dense vectors here. What follows is the mechanics of sense (a).

Now the mechanics, step by step. Both retrievers run in parallel: BM25 returns its top-N from the inverted index, dense search returns its own from ANN. Then they need to be merged, and here's the trap: BM25 scores are unbounded and corpus-dependent, while cosine similarity lies in the zero-to-one range — the scales aren't comparable. Reciprocal Rank Fusion sidesteps this by merging on rank rather than score: a document's weight is the sum, across retrievers, of one divided by "k plus rank." Only the order matters, so scale incomparability stops being a problem. The default k is around sixty — that's a convention, and it's worth tuning.

The reranker is the second stage, and the distinction between the two encoder types carries the weight here. A bi-encoder encodes the query and the document separately and in advance: at query time it's a fast comparison of ready-made vectors — cheap but coarse. A cross-encoder runs the "query plus document" pair together, in a single transformer pass: more accurate, but it can't be precomputed. Hence the rule: it's expensive, so it's applied only to reranking the top fifty-to-one-hundred candidates the hybrid stage selected.

We read the gains against a baseline, and skeptically. On WANDS, hybrid search gives NDCG 0.7497 against 0.6983 for BM25 — about a seven-percent gain over a tuned baseline. The large gains show up where lexical or semantic matching breaks down on its own: at Anthropic, the miss rate dropped from 5.7 to 1.9 percent. The payoff depends on the corpus: measure the gap on your own queries first, then add complexity.

Sources: [1] denser.ai — Hybrid Search for RAG (WANDS / financial-table deltas) · [2] Anthropic — Contextual Retrieval (miss-rate cascade 5.7→1.9%)

23 · The vector engine is chosen for scale: pgvector ~50M, Milvus 100M+; frameworks (LlamaIndex/LangGraph) are added for agentic complexity, not by default

Slide 23. The vector engine is chosen for scale: pgvector ~50M, Milvus 100M+; frameworks (LlamaIndex/LangGraph) are added for agentic complexity, not by default

Once hybrid search is justified and the corpus has grown, the question becomes "where do you store and search the vectors." It's easy to overcomplicate here: the sub-catalog of engines is large, but the right choice for most systems is boring. Let's clear up right away a question the owner rightly raised: Elasticsearch and OpenSearch are also full-fledged vector stores, not something outside the landscape. Both hold dense vectors and search over them: Elastic via the dense_vector field type and kNN over HNSW; OpenSearch via a k-NN plugin with a choice of engine. It's just more honest to place them on their own axis — "a search engine that also does vectors" — as opposed to vector-native engines (Qdrant, Milvus, Weaviate), which were built around approximate nearest-neighbor search from day one. Both categories are vector databases; what tells them apart is their origin, and that origin brings a set of strengths with it. Let's run through the 2026 cheat sheet, keeping in mind that scale ceilings keep moving and are worth checking on the day of the lecture.

pgvector is a Postgres extension. You reach for it when the data is already in Postgres and you need one system with transactional consistency. It comfortably holds on the order of fifty million vectors, and degrades past fifty-to-one-hundred million without special add-ons. Qdrant is a dedicated engine with minimal operational overhead, with native sparse and multi-vector primitives. Weaviate carries a built-in hybrid: vector, BM25, and metadata filters out of the box. Milvus is built for hundreds of millions and billions of vectors, with compute and storage split apart, but it requires a real operational investment. FAISS is a library, not a database: raw speed and full control, but you write persistence, CRUD, and filters yourself. Chroma and LanceDB cover prototyping, notebooks, and the local edge scenario.

Frameworks are a separate topic. The 2026 consensus: LlamaIndex and LangChain aren't competitors but complementary layers. LlamaIndex is strong when the hard part is retrieval over messy private documents: ingestion, indexing, sensible defaults. LangGraph provides orchestration: durable execution, checkpointing, human-in-the-loop with pauses of hours or days.

And a skeptical caveat that ties back to the ladder rule: for a simple RAG endpoint, where everything comes down to "retrieve, then generate," you don't need any framework at all. A few hundred lines of your own glue code spare you version churn and leaky abstractions. A framework gets added for agentic, multi-step complexity, not by default.

Sources: [1] firecrawl — Best Vector Databases 2026 (engine ceilings) · [2] TigerData — pgvector vs Qdrant (vendor benchmark, read skeptically)

24 · Three tiers: plain BM25 is enough / the built-in Elastic-OpenSearch hybrid is enough / a dedicated vector database only at 100M+, multi-vector, or a latency SLA

Slide 24. Three tiers: plain BM25 is enough / the built-in Elastic-OpenSearch hybrid is enough / a dedicated vector database only at 100M+, multi-vector, or a latency SLA

This is a choice made in the open — for your scale and your requirements, not an assumption that you already have something in place. Three tiers, from the bottom up; you move up to the next one only when the previous one isn't enough for the actual workload.

The first tier: plain BM25 is enough. This is the case when queries and documents share a vocabulary — internal tools, search over logs, code, identifiers, curated knowledge bases. Here you need neither embeddings nor a vector store at all, and reindexing is cheap and observable — a real operational advantage, not a compromise. Before you build vector infrastructure, honestly check whether this is your case.

The second tier: a search engine that also does vectors is enough. This is when you need meaning on top of lexical matching at a scale of millions or tens of millions of vectors, but standing up a separate specialized store is still premature. Elasticsearch and OpenSearch are among the options for such an engine: both natively support an RRF hybrid and a linear combination of keyword and vector. Elasticsearch carries the dense_vector field type and kNN over HNSW, and ELSER — a sparse neural model that runs inside the cluster with no external GPU inference — is claimed to beat BM25 recall by ten to twenty percent on domain content. OpenSearch offers k-NN via FAISS and Lucene and allows a higher vector dimensionality. The point of this tier is to get semantics without standing up a separate GPU embedding service and a second store.

The third tier: you need a dedicated vector database. That's at a hundred million vectors or more, when you need multi-vector or late-interaction primitives, under a hard latency SLA on the product's hot path, or when you want to decouple the vector store from operating a logging cluster.

The anti-hype takeaway: a huge share of RAG systems never exceed a few million chunks. At that scale, pgvector or the Elastic/OpenSearch hybrid is the boring right answer, and a dedicated vector database is often a premature optimization.

Sources: [1] Pureinsights — From Vector Hype to Hybrid Reality (do you need a vector database) · [2] bigdataboutique — Elastic/OpenSearch vector search (native RRF hybrid)

25 · Chunking strategies from simple to complex (fixed/recursive/sentence-window/semantic/parent-document/late/contextual); there's no single correct default -- you tune it to the corpus

Slide 25. Chunking strategies from simple to complex (fixed/recursive/sentence-window/semantic/parent-document/late/contextual); there's no single correct default -- you tune it to the corpus

Of the three steps in RAG, chunking is the one most underrated, and its leverage is high: how you cut a document into fragments determines what can even be retrieved. We already named poor chunking as one of the three technical roots of RAG failures; let's go through the strategies in order, from simple to complex.

Fixed-size cuts every N tokens or characters. It's crude, but fast, reproducible, and a surprisingly strong baseline. Recursive, or the character strategy, cuts along a hierarchy of separators — paragraph, then sentence, then word — respecting structure while bounding size; it's the pragmatic default. Sentence-window embeds a single sentence for precision but returns a window of neighboring sentences to the model for context. Semantic places the boundary where the embedding similarity of neighboring sentences drops sharply, i.e. at a topic shift; it sounds intuitive but often doesn't pay off — more on that on the next slide. Parent-document, also called small-to-big, indexes small chunks for retrieval precision but returns the larger parent block for generation — a widely recommended cure for lost context. Late chunking first embeds the whole document at the token level, then pools it into chunk embeddings so each one is context-aware, preserving pronouns and references.

Contextual Retrieval stands apart: an LLM prepends fifty to a hundred tokens of document-level context to each chunk before embedding and before BM25 indexing. This is exactly the technique that produced the miss-cascade drop from 5.7 to 1.9 percent that we saw on the RAG-principle slide.

Keep the main point in mind: neither chunk size nor strategy has a single correct default. You tune them to your corpus, and tuning without a metric is flying blind. Metrics come on the system-design slide.

Sources: [1] firecrawl — Best Chunking Strategies for RAG · [2] Anthropic — Contextual Retrieval (50–100 tokens of context per chunk)

26 · Studies on the effect of chunking disagree: recursive-512 69% vs semantic 54%; don't cargo-cult semantic; the silent retrieval failure is tables

Slide 26. Studies on the effect of chunking disagree: recursive-512 69% vs semantic 54%; don't cargo-cult semantic; the silent retrieval failure is tables

Here is the most instructive slide for judgment: studies on the effect of chunking openly disagree, and that disagreement is itself a lesson. Take three measurements, each with a baseline. A February 2026 benchmark compared seven strategies on fifty scientific papers: recursive chunking at 512 tokens came out first at 69 percent accuracy, while semantic chunking gave only 54 — and produced tiny fragments of about forty-three tokens each. In an MDPI clinical study from November 2025, adaptive and topic-boundary chunking gave 87 percent against 13 for fixed-size — a huge gap, but that's a narrow clinical domain. And NAACL 2025 Findings states outright that the computational cost of semantic chunking isn't justified by a stable gain: fixed chunks of two hundred words matched or beat semantic.

Read it this way: claims that "smart chunking wins" are domain-specific and inconsistent. On many corpora, plain recursive fixed-size is a strong baseline, and semantic chunking loses on both quality and cost. The engineering takeaway, verbatim: don't cargo-cult semantic chunking. Recursive fixed-size is cheap and strong as a starting point; add complexity only for a gap you've measured on your own corpus.

And this subsection's named failure, right on point for our failure thread: tables. They are the single most common cause of silent retrieval failures. Flattening a table into text destroys the row-column relationships — the model can't recover them, and this doesn't fail with an error, it silently corrupts the answer. The fix is to treat tables as structured objects rather than flattening them into a string. The meta-lesson from the strongest teams: the ones who went from months stuck on a RAG use case to a reliable deployment stopped fiddling with chunk size and started managing the knowledge layer — document quality, table handling, freshness, and metadata.

Sources: [1] firecrawl — chunking benchmark (recursive-512 69% vs semantic 54%) · [2] firecrawl — chunking eval (recall@k in isolation can mislead)

27 · The silent chunking failure: naive splitting flattens a table into a "bare row of numbers" with no headers -- the system doesn't crash, it just quietly answers wrong

Slide 27. The silent chunking failure: naive splitting flattens a table into a "bare row of numbers" with no headers -- the system doesn't crash, it just quietly answers wrong

The previous slide said: don't cargo-cult someone else's recipe, measure on your own data. This slide shows exactly how chunking breaks — and why it's the most treacherous kind of RAG failure: it's silent. Take a specific corpus: three hundred PDF manuals for industrial equipment — explanatory text plus spec tables ("Model / Voltage / Current / Tightening torque") plus safety warnings. A typical question: "what's the tightening torque for model X-500?" — and the answer lives in a table cell.

What would a naive engineer pick: RecursiveCharacterTextSplitter, five hundred twelve tokens, overlap fifty — that works for prose. But the parser detects the table and flattens it into a stream, and the character splitter cuts it at an arbitrary byte on the five-hundred-twelve-token boundary. The result: the first piece has the column headers and the first rows, and every piece after that is rows of numbers with no headers: "twelve, four hundred eighty, eight point five, thirty-four" with no labels. Why this is a silent failure: the system doesn't crash — the embedding gets computed, retrieval finds the chunk with the number thirty-four, an answer gets generated. It's just wrong: the model has no way to know that thirty-four is the tightening torque for X-500, not the current for X-700. The dashboard says "retrieval is working"; in production, it's a workplace injury.

The right fix isn't a "smart" semantic split, it's the mundane act of respecting structure[1]: table-aware splitting, where the table becomes its own chunk, and if it's over the limit, it's split by row with the headers repeated in every piece so each row is self-contained. Add parent-document for the text so warnings don't get separated from the procedure, plus metadata for filtering by model and version.

And three things you can't afford to forget. Anaphora: "it", "this city", "this policy" lose their antecedent when a cut lands between them — fixed with parent-document or contextual prepending. Changing the embedding model means re-chunking the entire corpus[2], not editing a line in a config file. And evaluating chunking itself is sensitive to k: recall@k can lie (ninety-two percent recall at fifty-four percent correct answers), which is why teams measure end-to-end too. The check for a silent failure is simple: generate twenty to thirty questions whose answers live in tables and manually confirm that the top-k results bring back a chunk with headers, not a bare row of numbers.

Sources: [1] Anthropic — Contextual Retrieval (tables are a silent retrieval failure) · [2] firecrawl — Chunking Strategies (re-chunk when changing embedders, k-sensitivity)

28 · POC -> production is a different architecture: a dual pipeline (ingestion is the first bottleneck), freshness, a full re-embed on model change, eval; the counterfactual "<200k tokens -- you don't need RAG"

Slide 28. POC -> production is a different architecture: a dual pipeline (ingestion is the first bottleneck), freshness, a full re-embed on model change, eval; the counterfactual "<200k tokens -- you don't need RAG"

So far, RAG has been discussed as logic. Here — what breaks when that logic becomes a production system. And right away let's clear up a skew that the course owner rightly flagged: production problems aren't only at indexing. There are three groups: building the index, the query, and operations. We'll go through all three, because "production" breaks in any one of them.

The index side — building and maintaining it. In production, the ingest-chunk-embed-index pipeline becomes dual: an offline batch for bulk indexing and an incremental one for updates. The first bottleneck is usually ingestion, not search: at millions of documents, chunk and embed don't fit on a single machine; the intuition that search itself is slow is misleading — it's index preparation that's slow, not the query against it. Freshness has a real cost: batch reindexing is simple but goes stale, CDC sync is close to real time but triples operational complexity; one case — moving from batch to CDC improved the freshness SLA from twenty-four hours to sub-minute. A separate migration event: changing the embedding model requires re-embedding every vector — old and new ones aren't comparable; that's an index migration, not a line in a config. And evaluating the build: without a labeled set, degradation is invisible — recall@k with a target around zero point eight, nDCG, plus an LLM judge like RAGAS.

The query side — what happens at the query itself. First: retrieval quality degrades at scale — as the corpus grows, recall falls and drifts, and "found something" stops meaning "found the right thing." Second: latency and throughput. Thousands of concurrent queries plus a cross-encoder reranker computed on every query hit a hardware wall; autoscaling lags behind a spike, and the latency tail grows exactly when load is at its peak.

Operations — what stays invisible until it breaks. Observability: retrieval fails silently, with no exception and no stack trace — the system answers confidently on irrelevant context, so you need quality metrics on live traffic and tracing on every request, or users will notice the failure before your monitoring does. Security and access: who's allowed to retrieve what; personal data sitting in chunks; the permissions filter has to sit before the vector search, or semantic similarity will pull in someone else's fragment — that's a data-architecture problem, not a model setting.

And the load-bearing counterfactual: for a knowledge base under two hundred thousand tokens, everything goes into the prompt with caching — up to a ninety percent cost cut — and retrieval is skipped altogether. The first question before any of this infrastructure is whether you need RAG at all.

Sources: [1] Redis — RAG at Scale (ingestion bottleneck, CDC 24h→sub-minute, cache ~69%) · [2] futureagi — RAG Evaluation Metrics (recall@k ~0.8, nDCG, RAGAS)

29 · "RAG" doesn't exist in a vacuum -- there's RAG for support/code/contracts/enterprise; the retrieval design follows from the nature of the data; 2 cases show "RAG was the wrong tool"

Slide 29. "RAG" doesn't exist in a vacuum -- there's RAG for support/code/contracts/enterprise; the retrieval design follows from the nature of the data; 2 cases show "RAG was the wrong tool"

Up to this point we've treated RAG as a mechanism: the principle, when it fits, how it breaks, what a correct build is made of. Now let's unfold that into five real archetypes, because «RAG» doesn't exist in a vacuum — there's «RAG for support», «RAG for code», «RAG for contracts», and their retrieval design is different. One shared quantitative anchor for all of them: according to practitioners, naive dense RAG misses retrieval[1] on the order of forty percent of the time, and three techniques — context attached to the chunk, hybrid search, reranking — close most of that gap.

The support and internal-knowledge-base case: kapa.ai runs documentation assistants for Docker, Reddit, and OpenAI; Stripe has an assistant built on top of its documentation. A typical failure: the embeddings decide that «exponential backoff» and «dead-letter queue» are semantically close, and the assistant confidently states the wrong retry policy — hybrid search saves it because BM25 catches the exact term that dense search blurred. The documentation case: the Vercel AI SDK docs-copilot builds an «answer with sources or refuse» contract and keeps an eval set right in CI, so a retrieval regression after a docs update doesn't slip into production unnoticed.

The code case is the most instructive. Cursor indexes the codebase with embeddings, but Sourcegraph Cody did the opposite on Enterprise: it removed embeddings and went back to classic lexical[3] and structural search. The reasons — code was leaving the perimeter into a third-party API (a security risk), vectors have to be stored and kept up to date, and at a hundred thousand repositories vector search is expensive and doesn't scale. Classic search gave equal or better quality, cheaper and safer. This is a direct example of «RAG-as-dense-vectors was the wrong tool»: for code and exact identifiers, classic search often beats dense RAG.

The legal case shows the high-stakes boundary: a preregistered Stanford study of commercial legal-AI tools (LexisNexis, Westlaw — all built on RAG) found seventeen to thirty-three percent hallucinations[2], despite «hallucination-free» marketing. RAG reduces but doesn't zero out hallucinations — you can't deploy it without citation verification and a human in the loop. And the enterprise case with mixed data: the question «total Q3 expenses» can't be closed with vector search over a table — that's SQL aggregation, so you need a «structured vs. text» router. The general takeaway: retrieval design follows from the nature of the data, it isn't copied from someone else's blog post.

Sources: [1] Barnett et al. 2024 — Seven Failure Points (RAG archetypes) · [2] Stanford HAI/RegLab — Legal-AI hallucinates 17–33% (Lexis/Westlaw) · [3] Sourcegraph Cody — context without embeddings (classic search)

30 · Deep research is RAG + an agentic loop + citation verification, not a "big prompt"; the typical failure -- 3-13% fabricated citations (worse than search: 10.7% vs 4.8%)

Slide 30. Deep research is RAG + an agentic loop + citation verification, not a "big prompt"; the typical failure -- 3-13% fabricated citations (worse than search: 10.7% vs 4.8%)

Here's an important reorganization from the course owner's feedback: we moved deep research out of the prompting section and into RAG. Why — deep research is often mistakenly filed under prompting tasks: «write one big prompt and it'll assemble the report.» That's wrong. The defining component here is retrieval and orchestration, not prompt phrasing — the prompt is just one detail in it. So this is a RAG case, and it belongs in the RAG section.

The setup: one complex question — «compare the market across five dimensions, with sources» — and the system plans its own sub-questions, searches many times, reads sources, and synthesizes a report with citations. The architectural pattern is a reasoning model plus an agentic RAG loop[1]: reasoning steers the search, new findings refine the reasoning, and it's a closed loop, unlike the static «retrieve top-k, then generate». The generalized schema for the slide: plan sub-questions, then several iterations of «search, read, refine the reasoning», then synthesis and a separate citation-verification step. OpenAI Deep Research runs one powerful reasoning model through a plan-search-backtrack-synthesize loop; Perplexity does real-time web RAG with source annotation. I'm naming products to illustrate the class, not as a recommendation.

The boundary of this class matters for judgment: deep-research agents fabricate citations. Measurements put it at three to thirteen percent of fabricated URLs. And a counterintuitive fact: a deep-research agent hallucinates citations worse than plain search with augmentation[2] — ten point seven percent versus four point eight percent. The baseline for comparison is the share of fake citations per query; the agent does worse precisely because it generates far more links. The fix is a separate verification layer after synthesis: check that every URL resolves and that the cited text actually supports the claim — exactly as in the legal case.

Against a human analyst, deep research is faster and cheaper, but without a verification layer, three to thirteen percent of the citations are false, and in a high-stakes report that's more expensive than a slower human. A direct tie-in to the course rule about baselines: deep research loves producing numbers with no baseline — «minus fifty percent», «five million acres» — and propping them up with a plausible but nonexistent link. The takeaway that closes this section: recheck any number from AI research against a resolving primary source, and treat a number with no baseline as a red flag, not a fact.

Sources: [1] Anthropic — Multi-Agent Research System (agentic RAG loop) · [2] arXiv:2604.03173 — citation fabrication in retrieval-augmented (3–13%)

31 · RAG is justified given a strong signal on the features — and no blockers, with a "when not"

Slide 31. RAG is justified given a strong signal on the features — and no blockers, with a "when not"

RAG is the right choice when there is a strong signal on one or more of the criteria[1] and at the same time there are no blockers from the neighboring "when NOT" criteria. The first criterion: the knowledge is large or growing — the corpus does not fit in the window as a whole, or it does fit, but putting it into every query is expensive and slow. The second: the knowledge changes — documents, prices, regulations update more often than model versions come out; RAG reads the current store at query time, and a new document is available right after indexing. The third: freshness and provenance are needed — the answer must rest on a verifiable source, and you need to show where the fact came from; regulated domains almost always require provenance. The fourth: the database is private — the company's knowledge is not in the weights of a public model.

The logic of application matters. A single clear criterion is already a reason to take a look at RAG, but not a reason to build it automatically: before deciding, check the task against the "when NOT" criteria — is there a blocker there. The knowledge is large but does not change and fits in the window — a candidate for a long context, not RAG. The knowledge changes, but the task reduces to returning a fixed value — a candidate for a deterministic lookup. The criteria usually reinforce each other: knowledge that is at once large, changing, requiring provenance, and private — that is exactly the profile RAG is designed for, and the more criteria that converge, the more confident the choice. The formula is short: a strong signal plus the absence of blockers.

A worked example we will return to as a checklist walkthrough at the end: a corporate database of thousands of regulations, updated weekly, natural-language questions, a mandatory reference to the source clause. All four criteria converged, and no simpler mechanism closes them jointly, while a check against the "when NOT" criteria overturns nothing. This is a model RAG profile. And a practical observation: RAG's gain over a direct answer is especially large for smaller models — external retrieval compensates for what a smaller model lacks in its weights, so RAG often delivers the needed quality on a cheaper model.

Sources: [1] IBM — RAG vs Fine-Tuning (vendor-neutral) · [2] U-NIAH — RAG win-rate is higher for smaller models

32 · When RAG is not needed: fits the window -> full-context; fixed policy -> lookup; live data via API/MCP -> the tool directly

Slide 32. When RAG is not needed: fits the window -> full-context; fixed policy -> lookup; live data via API/MCP -> the tool directly

Knowing when RAG is not needed is more valuable than knowing when it is, because RAG is a fashionable architecture, and it is put where it does harm. Three clear "not RAG" criteria[1].

First. The corpus fits in the window — a rough guide of the order of under two hundred thousand tokens — and does not change often. The right answer is full-context with prefix caching, not RAG infrastructure. This is simpler, cheaper, and does not introduce the risk of "retrieval pulled the wrong thing": there is no vector store, no indexing pipeline, no retrieval component that can break. RAG here is bought without need.

Second. The task is to return a fixed policy or value: a fare, a price, a regulation clause, a rule. If the answer is deterministic and known in advance, the right architecture is a deterministic lookup or a static page, not "retrieval plus generation on top." Generation on top of a fragment always carries the risk that the model will paraphrase, generalize, or make things up — this is exactly what happened in the Air Canada case.

The third criterion is often missed. The data is already available directly and live via API, MCP, or search in another system. If the knowledge already sits in an internal service with a REST interface or in a database accessible through MCP — building a separate RAG index on top of it is redundant. RAG exists to give access to knowledge for which there is no direct path; if the path already exists, RAG adds an extra, more fragile, and aging layer. The difference is strategic: a direct tool call returns the data as of the query moment, while a RAG index — as of the last indexing. The signal is simple: if to the question "why doesn't the model just ask system X directly through a tool?" the answer is "indeed, why not," — RAG is not needed.

Let us fold it into a rule: RAG is redundant if the corpus fits in the window and is stable, if the task reduces to a fixed value, or if the knowledge is already available live through a tool. Any of the three is met — a signal to stop. And even when none of them triggered and RAG is justified, this does not guarantee it will work well at scale — a separate question.

Sources: [1] Red Hat — RAG vs Fine-Tuning (when not RAG) · [2] McCarthy Tétrault — Air Canada ("generation on top of a fixed policy")

33 · "Returned something != returned the right thing": RAG without observability quietly degrades; Air Canada — a grounding failure

Slide 33. "Returned something != returned the right thing": RAG without observability quietly degrades; Air Canada — a grounding failure

The main lesson of the section in one phrase: "the system returned something" does not mean "the system returned the right thing"[1,2]. RAG has no signal "I found nothing suitable" — by default it always returns the k nearest fragments, even if they are irrelevant. Then the model honestly does its job: given garbage, it will compose a plausible answer on top of the garbage.

This is not a hypothetical risk but a known pattern of RAG engineering — seven failure points are systematized in Barnett et al. (arXiv:2401.05856, 2024). Three classes. Legal-AI pulls "the nearest k" cases; by vector, cases with matching words are close but legally irrelevant — a different jurisdiction, an overturned precedent; the model builds them in as grounding. Vector closeness is closeness of wording, not of applicability. Medical-RAG: a question about one patient retrieves fragments close by symptoms but from other patients; the model combines what clinically cannot be combined. Support bot: worked on hundreds of articles, after growth to thousands the quality quietly sagged — degradation at scale, because there is no "close enough" threshold. The alternative everywhere is not "remove RAG" but make it an observable system: a reference verification set and alerts, chunking along semantic boundaries, hybrid search with re-ranking.

Now let us return to Air Canada[3] (the case Moffatt v. Air Canada, BC CRT, decision 14.02.2024) — with the section's tools. The bot reported a refund of the difference and referred to a page with the real policy; the policy on the very same page did not allow such a refund. A source of truth existed, was available — but the answer was not derived from it, it was generated as plausible text. This is a model grounding failure: generated text in a role that required a retrieved fact. The correct architecture: for a fixed policy — a deterministic page or lookup; if a dialogue is needed — RAG with strict grounding, a mandatory citation, an explicit "I don't know," and human review. Air Canada is not "the AI hallucinates," it is the decision to put a generative architecture on a deterministic task. A short question for you: RAG returned an answer — how do you know it is right? Only by measurement; by eye, the plausible cannot be told from the correct.

Sources: [1] Barnett et al. 2024 — Seven Failure Points (RAG) · [2] Kore.ai — Seven RAG Engineering Failure Points · [3] McCarthy Tétrault — Air Canada (grounding failure)

34 · Section 3 — fine-tuning against the prompt and RAG: the problem isn't knowledge, but the model's behavior

Slide 34. Section 3 — fine-tuning against the prompt and RAG: the problem isn't knowledge, but the model's behavior

In the previous section we worked through RAG and closed with it one specific class of problems — the problem of knowledge. When a model lacks facts: they are private, or they change faster than new model versions come out, or provenance is needed — we do not retrain the model, we slip the needed documents into the context. We also honestly worked through when RAG is not needed and how it quietly breaks at scale, and closed the section back onto the Air Canada case.

But not every problem is a problem of knowledge. It happens that the model has enough facts, but the behavior itself is not satisfactory: it answers in the wrong tone, in the wrong format, does not follow a domain policy, or you need a small cheap model that repeats the behavior of a large one. This is a different class of task, and RAG does not solve it — no matter how many documents you slip in, the tone will not change from that. Here the third tool enters the stage — fine-tuning. And immediately an important note on the structure of the section: the next slide is not criticism and not "when you should not," but a definition. Before working through where fine-tuning has narrowed, where it fails through catastrophic forgetting, and by what criteria to choose between it, RAG, and the prompt, we need to understand equally what it even is and how it fundamentally differs from the two already familiar tools. And we will start with the definition.

35 · Classical ML: training set, reference labels, train/val/test split, transfer learning; PEFT/LoRA is the same transfer learning, cheap, on top of a pre-trained model

Slide 35. Classical ML: training set, reference labels, train/val/test split, transfer learning; PEFT/LoRA is the same transfer learning, cheap, on top of a pre-trained model

Classical machine learning solves the task like this. Training a model for a task in the pre-LLM paradigm is building your own model on your own data: the engineer collects a labeled set of "input → correct answer" examples and tunes the parameters so the model reproduces these answers and then generalizes to new ones. The central term is the training set: the collection of labeled examples on which the model learns. The labels are called ground-truth labels, ground truth — the known correct answer against which the prediction is compared. Before the era of large models, solving an AI task almost always meant collecting your own dataset, choosing an architecture for the task, and training your own narrow, controlled model.

The second load-bearing structure is the discipline of splitting the data. It is divided into three non-overlapping parts: training, validation, and test. On the training part the model learns, on the validation part hyperparameters are tuned, and on the test part — only once, at the end — the true quality is measured on data the model has not seen. The iron rule: you may not test on the training data, otherwise the accuracy comes out inflated and collapses in production. Quality is measured by an explicit metric fixed before training.

The third classical idea, and it is exactly the one that leads to this section's theme, is transfer learning. Long before large models, engineers noticed: training from scratch is expensive, but if you take a model pretrained on a huge general corpus and fine-tune it on your small task, the result comes out faster and more accurate. This is the classical two-phase pretraining–fine-tuning scheme.

This is exactly what the transition to fine-tuning large models should rest on. PEFT and LoRA are the same transfer learning, only taken to the limit of cheapness and on top of an incomparably larger model. The idea is not new — what became new is the scale of the base model and the cost of the fine-tuning step. So fine-tuning a large model is not an exotic thing of a new era but a direct continuation of the classical scheme, and all its cautions (train/test discipline, a metric, versions, drift monitoring) remain in force.

36 · Fine-tuning changes THE WEIGHTS THEMSELVES; in practice it's almost always LoRA/PEFT, not full-FT

Slide 36. Fine-tuning changes THE WEIGHTS THEMSELVES; in practice it's almost always LoRA/PEFT, not full-FT

Before saying anything about where fine-tuning has narrowed, where it is dangerous, and by what criteria to choose it, we need to understand equally what it is. Fine-tuning is the continuation of training an already ready, pretrained model[1] on your own data. In Lecture 1, fine-tuning was mentioned in passing as one of the usage types of AI; here it appears in its true role — as an architectural choice, one of the rungs of the same ladder of complexity.

The mechanics on the diagram: you take a pretrained model with its general weights, you take your dataset — a set of examples of the behavior you want to obtain — and the fine-tuning process shifts the model's weights toward these examples. The output is already a different model: the same architecture and size, but different numbers inside. This is exactly the key difference for which a separate definition slide is needed. The prompt and RAG do not touch the weights at all: they change only the context, that is, what you feed the model as input right now. The effect of a prompt or a slipped-in RAG fragment lives exactly within the scope of a single request and disappears with the next one. Fine-tuning changes the model itself: the change is built into the weights, is in effect on every request by default, and it is precisely for this reason that it costs more and rolls back harder than anything that changes only the context.

An important practical note right away: in practice "fine-tune a model" almost always means not retraining all the weights but parameter-efficient fine-tuning, usually called by the acronym PEFT and most often implemented by the LoRA method. Full fine-tuning of all the weights in 2026 is rare, and in the next slides we will work through why this is so. For now, remember the difference as a formula: the prompt and RAG are "what to show the model," fine-tuning is "change the model itself." In the next slides we will rely on this definition as we work through why in 2026 fine-tuning narrowed to behavior rather than knowledge, and where it turns from a tool into a source of problems.

Sources: [1] IBM — RAG vs Fine-Tuning (fine-tuning changes the weights)

37 · Training cost is a function of model size: Full-FT VRAM ~ 16-20B x N (grows linearly), LoRA ~ baseline + ε (nearly flat). LoRA is the default: under $10, ~7 orders of magnitude cheaper than pretraining

Slide 37. Training cost is a function of model size: Full-FT VRAM ~ 16-20B x N (grows linearly), LoRA ~ baseline + ε (nearly flat). LoRA is the default: under $10, ~7 orders of magnitude cheaper than pretraining

Let's put together the training-cost axis so it's easier to keep in your head: not in absolute dollars, which keep moving, but in relative terms. We take Full-FT as the baseline and count it as a unit — ×1 on memory, on money, and on compute. Everything else is a fraction of that unit. So what matters isn't the exact price tag but the order of magnitude and the shape of the growth: in some places it's a thousand times more expensive, in others it's hundredths of that. That's exactly what the engineer needs to decide: which option to take.

Let's go through the rows of the table. Trainable parameters: pretraining from scratch trains all the weights, Full-FT also trains one hundred percent, LoRA and QLoRA train a tiny adapter of 0.1–1% of parameters, and prompt with RAG doesn't change the weights at all. From there this projects directly onto memory, money, and compute. On VRAM, Full-FT is the baseline ×1; LoRA is roughly ×0.2 of that, because you don't have to keep gradients and optimizer states for the whole model, only the frozen base weights plus the adapter; QLoRA is even lower, around ×0.05, because the base is compressed to four bits. On money and compute the contrast is even sharper: LoRA and QLoRA are on the order of ×0.01 of Full-FT, that is, a hundred times cheaper, while pretraining from scratch is the opposite — over a thousand times more expensive than the baseline. To tie this to real life: a useful LoRA fine-tune of a small model costs less than ten dollars[1], while pretraining a frontier model costs tens of millions. Hence the headline contrast: LoRA is cheaper than frontier pretraining by roughly seven orders of magnitude. The "pretraining from scratch" row is in the table only to set the scale — nobody in the room is pretraining.

Let's be honest about QLoRA: it isn't a separate competing method, it's a modifier on top of LoRA. It doesn't change what gets trained — the same LoRA adapters — it cuts the weight of the frozen base by roughly a factor of four via 4-bit quantization. That's why it has the same relative parameters as LoRA in the table, only memory is even lower: for example, a 65B model fits on a single 48-gigabyte card[2]. The picture for data volume and speed follows the same shape: pretraining needs trillions of tokens and months, Full-FT and LoRA get by on thousands to tens of thousands of examples, and prompt with RAG works on a few-shot set of just a handful of examples and can be fixed instantly. Conclusion: training is cheap and getting cheaper; Full-FT is justified only when the dataset exceeds LoRA's capacity, and for narrow behavioral adaptation it buys nothing over LoRA while adding memory and forgetting risk.

Sources: [1] Thinking Machines — LoRA Without Regret (LoRA ≈ Full-FT under the right conditions) · [2] Dettmers et al. 2023 — QLoRA (65B on a single 48 GB card)

38 · PEFT (LoRA/QLoRA) is almost always better than full-FT; 98.4% of PEFT-tagged models are LoRA

Slide 38. PEFT (LoRA/QLoRA) is almost always better than full-FT; 98.4% of PEFT-tagged models are LoRA

The phrase "fine-tune a model" for many is associated with updating all the weights — this is full fine-tuning. In 2026 this is almost never what is needed. PEFT, parameter-efficient fine-tuning, is a family of methods in which the base weights are frozen and only a small set of additional parameters, adapters, is trained[1]. The most widespread method is LoRA: small low-rank adapter matrices are added into selected layers, and only they are trained. QLoRA is the same idea on top of a quantized base model, which radically lowers memory requirements.

Why PEFT is almost always preferable to full fine-tuning — three reasons, and the third is the most important. First: cheaper and faster — millions of adapter parameters are trained instead of billions of weights; QLoRA allows fine-tuning large models on a single GPU. Second: modularity — the adapters are small, megabytes against gigabytes, and you can keep several adapters for different tasks on one frozen base. Third, the main architectural argument about reliability: the base weights are frozen, physically not overwritten under the new signal, so what the model could do before fine-tuning is largely preserved — the training lives in the small additional adapters. This directly lowers the risk of catastrophic forgetting, to which we will now turn.

How widespread LoRA is — not an eyeball estimate but a measurable fact. According to the Hugging Face PEFT team, among 20,834 model cards tagged PEFT, 98.4 percent[3] use LoRA specifically. A caveat is mandatory: this is the share among those already tagged PEFT, not among all fine-tuning — full fine-tuning is tagged less carefully and may not be visible in the sample. Nevertheless, among those who chose the parameter-efficient path, LoRA is practically the no-alternative default. And the boundary: both full FT and PEFT are a change of the weights, unlike RAG, the prompt, and the context, which do not touch the weights. This is the watershed between "place knowledge" — RAG and context — and "encode behavior" — PEFT. In the narrative it is enough: full FT — almost never, PEFT and LoRA — the workhorse of 2026.

Sources: [1] Hu et al. 2021 — LoRA · [2] Dettmers et al. 2023 — QLoRA · [3] HF PEFT — Beyond LoRA (LoRA 98.4% of 20,834 cards)

39 · Fine-tuning narrowed to behavior: knowledge -> RAG, behavior -> PEFT, deterministic -> code; a hybrid is the norm

Slide 39. Fine-tuning narrowed to behavior: knowledge -> RAG, behavior -> PEFT, deterministic -> code; a hybrid is the norm

Let us break down the question that is constantly confused in practice: not "RAG or fine-tuning" but "what here is knowledge and what is behavior." If the task requires knowledge that changes or needs freshness and provenance, the right tool is RAG or a long context, not fine-tuning: knowledge in the weights will go stale by the next change of the corpus, retraining is expensive, and there is a risk of catastrophic forgetting. If the task requires stable behavior, tone, output format, or following a policy rather than new facts, the right tool is fine-tuning in the form of PEFT, not RAG: RAG feeds knowledge into the context but does not change the model's manner of answering. If the goal is to lower cost and latency on a narrow task while keeping quality, a pairing of two separate techniques works: first you fine-tune a large teacher model for the required behavior, and then you distill from it a compact student model. This is not "distillation as a variety of fine-tuning" — taxonomically these are different operations that in practice often go together. And if the answer must be deterministic and verifiable, the right tool is ordinary code with no AI at all: neither RAG nor fine-tuning is needed here, they would add only non-determinism.

The 2026 takeaway removes the false dichotomy: a clean "one of them" choice is rare, the norm is a hybrid. A typical mature system combines RAG for knowledge that changes, PEFT fine-tuning for stable behavior, and context engineering on top of both. But a caveat matters here, so that "hybrid is the norm" does not turn into a new cargo cult of "do everything at once": a hybrid is justified only where a task simultaneously has both a knowledge problem and a behavior problem. If there is no behavior problem, fine-tuning is not needed, even if RAG is already there. If the knowledge does not change and there is little of it, RAG is not needed either. A hybrid is not "more components — more correct," it is "knowledge and behavior separated into the right mechanisms, each added for its own requirement" rather than out of inertia or fashion.

40 · Distillation is fine-tuning a small student model; it differs in GOAL (matching the teacher's distribution, soft logits) and DATA (generated by the teacher) -- not in being "not training". DistilBERT -40%/97%, Alpaca 52k/<$600

Slide 40. Distillation is fine-tuning a small student model; it differs in GOAL (matching the teacher's distribution, soft logits) and DATA (generated by the teacher) -- not in being "not training". DistilBERT -40%/97%, Alpaca 52k/<$600

On the previous slide we fixed the definition: fine-tuning changes the weights themselves, whereas the prompt and RAG touch only the context. Relying on this, let us work through its domain of application in 2026. Among engineers the phrasing goes "in 2026 fine-tuning died — RAG and long context solve everything." This is inaccurate. Fine-tuning did not die — it narrowed[1] and stopped being the default setting. It narrowed precisely because it changes the weights: knowledge — facts, documents, everything that changes — lies poorly in the weights and went to RAG and long context, where it can be cited and updated. What stayed with fine-tuning is a narrow but important domain — stable behavior, style, output format, policy adherence, rather than the model's knowledge.

Separately and carefully about distillation[2,3], because here there is frequent confusion. Distillation is an independent technique of knowledge transfer and model compression (Hinton, Vinyals, Dean, 2015): a student model learns to imitate the outputs of a teacher model through a separate loss function. Taxonomically it is not a kind of fine-tuning — method surveys place them in different categories. In practice the two techniques are often combined: first the teacher model is fine-tuned for the desired behavior, and then a compact student model is distilled from it. Hold this as "fine-tune teacher, then distillation of student — two separate techniques in tandem," rather than "distillation as a kind of fine-tuning."

Hence the what-goes-where criterion. Knowledge changes or provenance is needed — RAG or long context, not fine-tuning: the knowledge will go stale, retraining is expensive, there is a risk of forgetting. You need stable behavior, tone, format, policy — this is fine-tuning in the form of PEFT, not RAG. You need to lower cost on a narrow task — the tandem of fine-tune teacher plus distillation of student. The answer is deterministic and verifiable — ordinary code without AI. In other words, fine-tuning in 2026 is a narrow tool for behavior, format, policy, and efficiency, not a way to teach the model a domain; "teach the domain" in the sense of facts is RAG, in the sense of manner is PEFT, and almost never full fine-tuning.

Sources: [1] BigData Boutique — Fine-Tuning When RAG Isn't Enough · [2] Hinton, Vinyals, Dean 2015 — Distilling the Knowledge · [3] PEFT survey — taxonomy of tuning methods

41 · Narrow aggressive fine-tuning breaks general abilities; without an eval loop and versions — a "don't do it" criterion

Slide 41. Narrow aggressive fine-tuning breaks general abilities; without an eval loop and versions — a "don't do it" criterion

Let us introduce the term through a documented failure. Catastrophic forgetting is the degradation of the model's general abilities[1] as a result of narrow aggressive fine-tuning: by training the model to be very good at one narrow task, you can break what it could do before that.

How this looks as a case. A team fine-tunes a model on a narrow dataset — for example, classifying tickets into their format. On the target metric there is growth: the model classifies excellently. In parallel, imperceptibly, general abilities sag: reasoning on non-target tasks, following complex instructions. On the graph these are two lines: the solid one going up — the target metric (rises), and the dashed one going down — general abilities (fall imperceptibly). If the team measured only the target metric, the degradation is invisible until the model starts being used on something other than the narrow task. And then "why did it suddenly get worse at reasoning?" turns out to be a consequence of a month-old fine-tuning, for which there are already neither the old weights nor the dataset version. Mechanically: training for a narrow task moves the weights toward it, and the parameters that encoded general abilities are overwritten under aggressive full-FT. This is empirically observed under continual fine-tuning (Luo et al., arXiv:2308.08747, 2023), moreover with a counterintuitive feature: as the model's scale grows, the severity of forgetting tends to increase. "Let's take a bigger model to be more reliable" here works in reverse.

Why this belongs in the section on the choice of architecture rather than among curiosities. Forgetting by itself is a manageable risk. What makes it catastrophic is the absence of engineering discipline: there is no evaluation loop that would show degradation on a representative set of general tasks; there is no versioning of the dataset and weights for a rollback. Without an eval loop you will not notice that you broke general abilities until it surfaces in production; without versioning you will not return to a working version. The rule: if there is no eval loop and dataset versioning — do not do fine-tuning. This is not a "risk," it is a criterion: there will be neither a signal of the breakage nor a rollback button. The right alternatives: PEFT, where frozen weights give a lower risk; and for changing knowledge — RAG, not fine-tuning at all.

Sources: [1] Luo et al. 2023 — Catastrophic Forgetting in LLM Continual FT

42 · Evaluating training is more expensive than the training itself and unsolved: none of the SIX methods is self-sufficient (MMLU ~29%, GSM8K -> GSM1k -13 pp, judge position bias 75%, human κ>=0.6 $300-1200, BLEU r~0.25-0.52); the lab -> prod gap ~37% -- a benchmark gain is a hypothesis, not a result

Slide 42. Evaluating training is more expensive than the training itself and unsolved: none of the SIX methods is self-sufficient (MMLU ~29%, GSM8K -> GSM1k -13 pp, judge position bias 75%, human κ>=0.6 $300-1200, BLEU r~0.25-0.52); the lab -> prod gap ~37% -- a benchmark gain is a hypothesis, not a result

Here the intuition flips: engineers worry about the cost of training, but the real budget line is evaluation. A useful 7B LoRA costs a few dollars, while a rigorous evaluation of that same adapter is $300–1200 of human labor for a single round — and it can still fail to predict production. Let's go through six methods, each on the same hard scheme: how it works step by step, when it's valid, when it breaks, what it costs.

First — public benchmarks: MMLU, GSM8K, HELM. A fixed set of questions with known answers, the metric is the share answered correctly, the run is cheap and needs no people. Valid for checking broad capabilities and catching forgetting. It breaks on two things. Contamination: test questions leaked into pretraining — about 29% of MMLU items showed signs of contamination[1], and on a clean mirror of GSM8K, that is GSM1k, accuracy drops by thirteen points[2], which means you're measuring memory, not reasoning. And irrelevance: a domain-specific LoRA can be better on your domain and worse on MMLU. Second — the held-out test set: you select and label examples from your own task before training, freeze them, and run every version against them. This is the only thing that measures your actual task — the highest ROI; it breaks only on leakage into training or drift. Third — LLM-as-judge: a strong model judges the output, pairwise is more reliable than pointwise. It gives over 80% agreement with humans, but it's systematically biased: position bias up to 75% preference for the first answer, self-enhancement adding 10–25% in favor of its own model family. The key point here: reproducibility of a verdict is not the same as its correctness.

Fourth — human evaluation: a rubric, two to three annotators, inter-rater agreement (kappa). There's a meaningful threshold — kappa no lower than 0.6, otherwise the rubric needs to be rewritten. The gold standard for open-ended quality, but expensive and doesn't scale: a set of 200 examples across three raters is $300–1200 per round. Fifth — task metrics: exact-match, F1, BLEU, ROUGE. Valid for closed tasks with a single correct answer. On open generation they break: they measure n-gram overlap, not meaning, correlation with humans is r from 0.25 to 0.52 — a correct paraphrase gets penalized. Sixth — A/B online: a canary on 1–5% of traffic with guardrail metrics. The only method that measures real behavior; it breaks because it's not applicable before production, and because of LLM non-determinism you need roughly four times more samples.

The through-line: no single method is self-sufficient. The cheap ones have the worst validity, the valid ones are expensive. The measured gap between a lab benchmark and production is about 37% — that's mechanics, not an anomaly: a benchmark gain is a hypothesis, not a result; only a clean held-out set plus A/B on real traffic confirm it, and you need to budget for that gap.

Sources: [1] Pebblous — LLM Benchmark Contamination (MMLU ~29%) · [2] Zhang et al. 2024 — GSM1k (clean mirror of GSM8K −13 pp)

43 · Section 4 — Agents: the loop, the equipment, memory, tool access — and where all of it breaks

Slide 43. Section 4 — Agents: the loop, the equipment, memory, tool access — and where all of it breaks

This is the largest section of the lecture, and it is about how AI stops being an interlocutor in a chat window and becomes a component of a system. Up to now we discussed a single call and RAG as a way to get text; here the model gains the ability to return machine-processable data, reach out to external systems, and work in a loop. We will work through the mechanics of the API layer and the standard for connecting tools, then the agent loop itself and the distinction between a workflow and an agent, then — what a real assistant agent is assembled from, where its memory lives, and how all of this breaks. It is here too that the through-line theme of security truly stands up: as soon as the model gains tools, a question appears that a single call did not have — who sees the data at each step and what happens when untrusted content enters the context as a command. This is the section where the price of the wrong choice of architecture is measured not only in money but in leaks.

44 · Classical automation: finite-state machine, workflow engines (BPMN/DAG/RPA), a control loop plan->act->check (OODA); an agent = the same loop, but the LLM generates the steps non-deterministically

Slide 44. Classical automation: finite-state machine, workflow engines (BPMN/DAG/RPA), a control loop plan->act->check (OODA); an agent = the same loop, but the LLM generates the steps non-deterministically

The word "agent" sounds like an invention of the era of large models, but controlled process automation is a mature engineering discipline with many years of history, and without it you cannot honestly assess what an LLM agent adds and what it breaks. Let us restore the baseline from scratch. The simplest classical model of controlled behavior is the finite-state machine: a system is described by a finite set of states and rules of transition between them on events. Request created, in processing, approved or rejected, closed — this is a finite-state machine; in each state a strictly defined set of transitions is allowed. The behavior is fully predictable and checkable: impossible transitions are excluded by construction, not by hope.

When a process is more complex than a single state machine, classical engineering applies workflow engines, orchestrators — systems that execute a pre-described multi-step process along a fixed scheme. Let us name them concretely: BPMN — a standard for the graphical description of a process executed by an engine; Airflow-like orchestrators execute a process as a directed acyclic graph of tasks; RPA automates routine on top of existing interfaces along a rigid script. One thing unites all of these: the sequence of steps is defined in advance, not decided on the fly. Such a pipeline is deterministic, auditable, and repeatable.

The third classical idea, and it is exactly the one that leads to the agent loop, is the control loop plan→act→check as a feedback loop. This is a direct inheritance from control theory and robotics: a system measures the state of the environment, computes an action, applies it, measures again, and corrects. The military-engineering analogue is the OODA loop. The essence is one: not a single action, but a loop — plan, do, check, correct.

An LLM agent is the same control loop, but its steps are generated by the model non-deterministically rather than selected by a fixed rule of a state machine. Hence both the power and the fragility are visible: a deterministic loop always makes a predictable step, whereas a model can invent a step that was not in the scheme. And the classical reliability practices — determinism where possible, idempotency, limits, audit, least privilege — do not go anywhere.

45 · An agent = a loop plan -> act -> check -> iterate; every step is a place of failure; check must not be self-assessment

Slide 45. An agent = a loop plan -> act -> check -> iterate; every step is a place of failure; check must not be self-assessment

Now there is everything for the next rung. A single call can reason; RAG pulls knowledge; function calling reaches external systems; MCP standardizes connection. An agent is an architecture in which the model does not make one pass but works in a loop[1]: it plans a step, acts — calls a tool, observes the result, checks whether the goal is reached, and iterates, dynamically determining the sequence itself. The canonical formulation is plan, act, check, repeat; this is the ReAct pattern, alternating reasoning and actions, while Reflexion adds an explicit self-assessment after a failure. This is a "different AI" compared to a single call: there the model answered once, here it directs a process of many steps.

Let us work through the loop step by step, because each step is a place of a specific failure mode. Plan: the model states a step based on the goal and history; the failure mode is a myopic or looping plan, the model does not see the accumulated cost and time. Act: a tool is called; the failure mode is the tool failing or returning an error, and if there is no plan for it, a loop begins. Check: the result is assessed; the failure mode is no check or one that reduces to the model's self-assessment. Iterate: the loop repeats; the failure mode is no external limit on iterations, cost, or time. "An agent" is not one abstraction but four steps, each with its own way to break; to design an agent means to design defenses at each of the four.

Let me emphasize the element that carries the main through-line load of the course — the check step[2]. And here the lesson about the faithfulness of reasoning returns starkly: the check must not be "the model asked itself and answered itself that everything is fine." Self-assessment is subject to the same unfaithfulness that we saw on the slide about the limit of chain-of-thought — it is an illusion of control: the explanation "I checked" is produced by the same sampling as the answer itself. A reliable check is validation against an external criterion: a schema, a test, an invariant check, a comparison against a source of truth, and in significant decisions — a human validator. Without an external check, the agent loop is a loop that confidently goes in the wrong direction. This is a direct bridge to agent failures.

Sources: [1] Yao et al. 2022 — ReAct (plan→act→check→iterate) · [2] Anthropic — Reasoning Models faithfulness (check ≠ self-assessment)

46 · The model becomes a system component: structured output / function calling / prompt caching + MCP

Slide 46. The model becomes a system component: structured output / function calling / prompt caching + MCP

For AI to become part of a system, three mechanisms of the API layer are needed. The first is structured output: a mode in which the model is obliged to return an answer strictly by a given schema, for example JSON, rather than free text. Technically the schema is compiled into a constraint on sampling, so the model cannot produce a structurally invalid answer; the output turns from text that has to be parsed with regexes into data guaranteed to be valid in form. This makes the model embeddable. A subtlety: validity of form is guaranteed, but not of content — a field may be factually wrong. The second is function calling: instead of answering with text, the model can return a request "call tool X with arguments Y," and your code executes the call, not the model. The model only states an intention — this makes it active and will be key for security. The third is prompt caching: reusing the already computed state of an unchanged prefix so as not to recompute it each time; the state is cached, not the text of the answer. This makes the model economically viable at volume and makes full-context for a small stable corpus a real competitor to RAG. None of the three makes the model more reliable or auditable — they expand capabilities without changing the nondeterministic nature, and they do not repeal the rule of the ladder.

There remains the question of how a tool connects to the model. Until the end of 2024, each integration solved this in its own way. MCP, the Model Context Protocol, is an open standard for a unified way to connect[1] tools to a model; the metaphor is "USB-C for tools." The essence is in the arithmetic: with N models and M tools, naively you need N times M integrations, and MCP reduces this to N plus M. But here is a critical pivot: standardizing connection does not mean the security of what is connected and even aggravates the trust problem. Every connected tool is code in your environment and a channel through which untrusted text enters the context. "Connect in a minute" and "trust what is connected" are different questions; MCP solved the first and made the second sharper. Ease of connection is not an argument for connecting.

Sources: [1] Anthropic — MCP donation / Agentic AI Foundation (N×M→N+M)

47 · Economics: an agent is xN tokens vs chat, multi-agent another x15; caching goes from a guideline to a necessity

Slide 47. Economics: an agent is xN tokens vs chat, multi-agent another x15; caching goes from a guideline to a necessity

Cost on the architectural ladder does not grow the way an engineer intuitively expects. The base: one chat turn costs cents. The move to an agent is not a surcharge but a multiplicative jump: the context accumulates tool outputs, the model reasons at every step, the tokens are many times more. Multi-agent is another ×15 on top of a single one. The key point: the multipliers multiply, they do not add. Each step multiplies the budget, it does not add to it.

That is why prompt caching — reusing an unchanged prefix instead of recomputing it on every request — changes its status from an option to a necessity inside an agent loop. On an isolated call the cache is pleasant but not critical. Inside a loop with dozens of accesses to the same prefix (instructions, descriptions, context) the absence of a cache means paying for every recompute. The cache does not remove the multiplier, but it removes the unneeded recompute.

The takeaway: compute the economics before deciding to step up the ladder, not after the API bill. "An agent is more expensive" is a multiplicative rule, and multi-agent multiplies again. Before adding a step, ask yourself: does the value of the task justify this multiplier.

48 · MCP NxM -> N+M; ~11% of the catalog is actually runnable; ease of connection != security

Slide 48. MCP NxM -> N+M; ~11% of the catalog is actually runnable; ease of connection != security

Function calling decides how the model formulates a call. MCP decides how the tool physically connects. Before 2024 each vendor solved this in its own way, producing a combinatorial explosion. MCP is an open standard: N models × M tools = N×M integrations → N+M. The metaphor: USB-C for tools. Anthropic opened it in November 2024, OpenAI and Google adopted it in 2025 — a de facto industry standard.

Read the scale critically. Catalogs name up to 90,000 servers, but the actually runnable ones number about 10,000 — 11%. The rest are duplicates, broken, stubs. Even the working ones are not checked for security.

The critical turn: standardizing the connection does not mean the connected thing is secure — it worsens the problem. Every tool is code that runs in your environment, a channel for untrusted text. Over 60 days: 30+ CVEs on MCP servers, 43% — command injection, 82% of implementations vulnerable to path traversal. "Connect it in a minute" and "trust the connected thing" are different questions. MCP solved the first and made the second sharper. Convenience is not an argument for connecting.

49 · MCP or a direct API -- not alternatives: MCP is a thin discovery/portability layer ON TOP of REST; NxM -> N+M pays off only when N,M>=2-3; ~25% of the registry are unusable, 43.7% top MCP-Universe

Slide 49. MCP or a direct API -- not alternatives: MCP is a thin discovery/portability layer ON TOP of REST; NxM -> N+M pays off only when N,M>=2-3; ~25% of the registry are unusable, 43.7% top MCP-Universe

Having introduced both function calling and MCP, let's honestly ask the question that comes up for an engineer right away: do I actually need MCP, or is it simpler to just hit the API directly? Let's start with the basics, because there's a common misconception here — "MCP replaces REST." That's wrong. REST and gRPC are the transport layer that actually does the work: it hits the database, calls the service. MCP is a thin standard layer on top, which lets an agent discover the available tools at runtime through a tools/list request and call them. In the overwhelming majority of real deployments, an MCP server wraps an already-existing REST API rather than replacing it. So the question isn't "MCP or API" — those aren't alternatives at the same level — it's "do I need a discovery-and-portability layer on top of the API, or is a hard-coded function call enough?"

The headline argument for MCP is integration arithmetic. Before MCP, to connect N applications with M tools, in the worst case you need N times M separate integrations. MCP makes it so each side implements the protocol once: the application becomes a client, the tool becomes a server, and all you need is N plus M implementations. But that also shows the threshold: the payoff only materializes once both N and M are at least two or three. For one application and one or two known tools, N times M equals two and N plus M equals three — so a direct function call is simpler. Below the threshold, MCP is pure overhead. What else the MCP layer gives you: dynamic discovery, when the catalog changes often; stateful sessions; portability across model vendors.

The flip side is the cost of the layer, and it isn't zero, which is why the decision goes by the table. An updated scan of all roughly 10,700 registry servers found that about a quarter of registry servers[2] are unusable, and the authors explicitly call this a floor, not a ceiling: part of it sits behind an auth wall and couldn't even be tested. Even among the ones that work, real-world success is low: on the MCP-Universe benchmark, the top-tested model scored forty-three point seven[1] percent successful tasks — meaning even the top result fails more than half of real MCP tasks. And security hasn't been settled either: the specific audit numbers (command injection, path traversal) we covered on the slide about MCP and the trust pivot — here it's enough to keep in mind that this is a separate trust boundary, not a solved question.

The one-line rule: MCP is an interoperability standard, not a performance upgrade. It pays off as a fleet and an ecosystem — many agents, many tools, reuse, switching vendors. For a single agent with a single tool, a plain function call is simpler, faster, and safer — and skipping MCP here is the correct engineering judgment, not a cut corner. This is exactly the ladder rule, applied to the connection layer.

Sources: [1] MCP-Universe (arXiv:2508.14704) — top result 43.7% · [2] DEV/theopslog audit 2026 — ~25% of registry servers unusable

50 · A workflow is not a primitive: five patterns for the predictable (prompt chaining / routing / parallelization / orchestrator-workers / evaluator-optimizer)

Slide 50. A workflow is not a primitive: five patterns for the predictable (prompt chaining / routing / parallelization / orchestrator-workers / evaluator-optimizer)

Before working through how agents break, we need to introduce a distinction that is, for the lecture's main learning goal, one of the most important. Anthropic in "Building Effective Agents" separates two concepts[1] that in everyday use are often conflated. A workflow is a system where the model and tools are orchestrated along paths predefined in code; the sequence of steps is known in advance and hardcoded, the model is called at specific steps but does not decide which steps to do and in what order. An agent is a system where the model dynamically determines its own process; the sequence is not fixed in advance.

The distinction is operational and gives a direct choice criterion. The task is predictable, the sequence is known — workflow. Unpredictable, the sequence depends on intermediate results, and the value justifies a multiple increase in cost — agent. Anthropic states the trade-off directly: agentic systems trade latency and cost for quality. Let us translate the criterion into one practical question: can I, in advance, before the run, write out the sequence of steps? If yes, even with known branches — it is a workflow. If the sequence fundamentally depends on intermediate results, and the value justifies the increase in risk — an agent. "Too lazy to formalize" does not make a task unpredictable. This is perhaps the industry's most expensive mistake: building a dynamic agent where a workflow would have sufficed.

An important note: the boundary runs not only along the task as a whole but also along what happens inside a specific step — workflow and agent nest inside each other, and this is the norm. An agent at the action step can call a whole workflow as a single tool: a code review agent itself decides what to check, but calls the step "linter, tests, formatting" as a single deterministic subprocess. And vice versa: a claims-processing workflow routes along fixed rules, but delegates the step "figure out a free-form complaint" to a mini-agent. This is not a third architecture but the recognition that the question "workflow or agent" is about a specific place in the system: dynamism is added only where it is needed. The full debate about multi-agents[2] stays in the chapter; in the narrative it is enough: multi-agent by default is not an upgrade.

Sources: [1] Anthropic — Building Effective Agents (workflow vs agent) · [2] Cognition — Don't Build Multi-Agents

51 · An agent framework is an abstraction tax; adopted for a requirement. LangGraph / CrewAI / AG2 / OpenAI Agents SDK / Claude Agent SDK / smolagents / LlamaIndex / Pydantic AI -- and "none: plain code"

Slide 51. An agent framework is an abstraction tax; adopted for a requirement. LangGraph / CrewAI / AG2 / OpenAI Agents SDK / Claude Agent SDK / smolagents / LlamaIndex / Pydantic AI -- and "none: plain code"

The engineer has decided an agent is justified — now the question is what to build it on. A frame-level thesis holds the whole slide: Anthropic's "Building Effective Agents" writes that many patterns can be implemented in a few lines of direct API calls[1], and frameworks add layers of abstraction that hide the underlying prompts and responses and make debugging harder. A framework is an abstraction tax; you pay it only when it demonstrably improves the outcome, not by default. So first — the five drawbacks common to every framework, because marketing stays silent about them, and that is exactly the judgment content of this slide.

The first is a limit on behavior customization. A highly abstract framework accrues technical debt right at the moment you need to go past the "happy path": override a built-in prompt, change the control flow. The second is transparency and debuggability: a framework hides the actual prompts and control flow, and debugging a stuck agent in a five-agent pipeline becomes painful. The third is lock-in: vendor SDKs tie you to a single model ecosystem, and portability costs a rewrite. The fourth is version churn: the LangChain ecosystem has had too many breaking API changes across its history, and an upgrade breaks working code. The fifth is overhead: a benchmark found that a three-agent "crew" on CrewAI spent roughly 18% more tokens than an equivalent build on LangGraph — abstraction is not free at runtime either.

Now, by the stable schema "core abstraction, what it fits, one honest drawback." LangGraph is a stateful graph[2], for production with control over flow and state; the drawback — a steep learning curve, over-engineering for a single loop. CrewAI is role-based crews, for fast prototyping; the drawback — the "role" masks what is actually happening. AutoGen turned into AG2 and Microsoft Agent Framework — this is exactly version churn and rename churn, a risk at adoption time. OpenAI Agents SDK — handoffs, but OpenAI-centric. Claude Agent SDK — the same loop that powers Claude Code, for coding and computer-use; the drawback — a heavy harness versus the bare API. smolagents — code agents, the drawback — code execution is an attack surface. LlamaIndex — an agent on top of a RAG stack. Pydantic AI — a type-safe loop. And the bottom row is not there for completeness: a deterministic path plus known steps plus cost sensitivity is plain code, without an agent and without a framework. The five drawbacks above apply to every row: the tooling complexity is paid for by the demands of the task, not taken on in advance.

Sources: [1] Anthropic — Building Effective Agents (framework = abstraction tax) · [2] LangGraph (LangChain) — stateful graph, production orchestration

52 · An agent fits an open, unpredictable task; a predictable one -> workflow; multi-agent only under a trigger. p^n: 0.95^10~60%, 0.95^20~36%; tau-bench 61% -> 25% pass@1 -> pass@8

Slide 52. An agent fits an open, unpredictable task; a predictable one -> workflow; multi-agent only under a trigger. p^n: 0.95^10~60%, 0.95^20~36%; tau-bench 61% -> 25% pass@1 -> pass@8

This is a judgment slide: when to use an agent, when a workflow, when several agents. The logic runs top-down. If the task is predictable — the steps are known in advance — use a workflow: paths predefined in code, auditability. If it is unpredictable and the value justifies the multiple-fold cost — a single agent: the steps depend on intermediate results, and that needs the flexibility of a loop. And only for a specific case — several agents. It matters not to settle for the word "trigger" but to name those cases explicitly, because outside them multi-agent is the wrong tool.

There are three conditions under which multi-agent is justified. The first — widely-parallel independent reads, not decisions: for example, reading a hundred sources in parallel and rolling them into one report — that is how Anthropic's research agent is built, where the reading subtasks do not depend on each other. The second — independent perspectives for cross-checking: for example, five agents independently search for an answer, and the result is then taken by vote; disagreement between them is itself a signal. The third — isolated sub-domains with separate tools and permissions: for example, a separate agent for billing and a separate one for infrastructure, each with its own set of access rights, and mixing them is dangerous. If your task does not fall into any of these three cases — stay with a single agent.

Why such caution about the number of steps — because reliability drops as p to the power of n, not averaged out. In a chain of n steps where a failure at any one spoils the result, reliabilities multiply rather than average. Every extra agent adds steps and connections, which means it lowers overall reliability. The specific numbers and a live benchmark measurement are on the next slide; here the principle itself matters: "almost always" at each step multiplies into "fairly often not" at the output of the whole system.

Topology here is not a detail but a decisive factor. By the measurement of Kim and co-authors, preprint 2512.08296, a decentralized "swarm" of peer agents with no single center amplifies errors noticeably more than a single coordinator does: more connections between agents means a faster collapse, and we will look at the specific multipliers on the next slide. And separately, two claims that students often hear as a contradiction need to be reconciled. Anthropic says multi-agent wins research tasks; Cognition writes "don't build multi-agents." There is no contradiction: parallelize independent reads — a broad search where subtasks don't depend on each other — but not decisions with dependencies, where parallel subagents make conflicting implicit choices and spoil the result. Anthropic states the win literally: multi-agent works mainly because it helps spend enough tokens on the task, not because of coordination magic[1].

The practical takeaway: start with one strong agent. Multi-agent buys quality by burning tokens, not by coordination magic; the multiple-fold cost estimates are on the next slide. If a task does not decompose into widely-parallel independent reads and the value does not justify the multiple-fold cost, it is the wrong tool.

Sources: [1] Anthropic — Multi-Agent Research System (spend enough tokens) · [2] Kim et al. 2026 (arXiv:2512.08296) — topology: swarm vs coordinator

53 · Multi-agent by default is NOT an upgrade: p^n (95%x10=60%); swarm 17.2x vs coordinator 4.4x

Slide 53. Multi-agent by default is NOT an upgrade: p^n (95%x10=60%); swarm 17.2x vs coordinator 4.4x

Let us take on separately why multi-agent is not a win by default, because this is one of the frequent architectural mistakes, and it has a simple, vivid math. In a pipeline of n sequential steps where a failure of any step spoils the outcome, the reliabilities multiply rather than average: the overall chance of success is approximately p to the power of n. Hence the counterintuitive numbers: even at ninety-five percent reliability per step, ten steps in a row yield only about sixty percent overall reliability, and at ninety percent per step — already about thirty-five. The engineer's intuition "each step almost always works, so the whole chain almost always works" is mathematically false: "almost always" per step multiplies into "fairly often not" at the output of the whole system.

Next — the question of topology, that is, how exactly several agents are organized among themselves. With the same number of agents, independent "swarms" of equal-rank agents working without a single center amplified errors nearly seventeen times, whereas centralized orchestration with a single coordinator held error amplification to under five times. The conclusion is direct: orchestration with a single coordinator is more reliable than a "swarm" of equal-rank agents, and not the other way around, even though intuitively a "swarm" seems the more flexible and scalable solution.

Here it is worth quoting Anthropic's position verbatim, because it is sobering: multi-agent systems work mainly because they help spend enough tokens to solve the problem — that is, the gain is largely explained by the volume of computation, not by some special coordination magic between agents. The practical advice from the same sources is to start with a single strong agent: for many tasks, single calls with good retrieval and examples suffice, while teams spent months on complex multi-agent architectures only to find that more precise prompting of one agent gave an equivalent result more cheaply. Hence the criterion: do not build multi-agent unless the task decomposes into broadly parallel, independent, high-value subtasks — otherwise the coordination overhead and the manyfold growth in token cost will outweigh any benefit from parallelism.

54 · Each equipment slot of the agent is a trade-off, not a default upgrade

Slide 54. Each equipment slot of the agent is a trade-off, not a default upgrade

So far we have talked about an agent as an abstract loop: plan, act, check, repeat. But a real assistant agent, the one an engineer works with every day, is not a bare loop but a loop plus a harness[1]. A set of additional mechanisms that determine what the agent remembers, what it follows, which procedures it can reuse, whom it can delegate work to, and which external systems it has access to. Further in this section we will repeatedly rely on data from the agent-harness-registry — an independent public registry that tests agent harnesses (memory, skills, subagents, MCP) through live-eval benchmarks on real tasks, rather than through vendor self-reports of capabilities. By its data one can distinguish five typical slots of this harness. The first is memory: what the agent remembers between sessions. The second is instruction-rules: the project's convention files and a progress log. The third is skills, reusable procedures for repeating tasks. The fourth is subagents, delegated sub-agents with their own context window. The fifth is access to external tools through MCP.

Before working through each slot separately, let us fix a thesis that rhymes with the central rule of the whole lecture and with the ladder of architectural complexity. Each harness slot is a trade-off between cost, complexity, and fault tolerance, not an upgrade by default. Exactly as one should not climb the ladder of architectures without a requirement of the task, one should not add memory, subagents, or new access to an agent just in case: each added slot carries its own cost — operational complexity, a new failure surface, a new trust boundary — and must answer a concrete, not an abstract, trigger. Next we will walk along this map slot by slot and at each check this thesis.

Sources: [1] agent-harness-registry — map of the agent's equipment slots

55 · "An agent that remembers" is not always better: Letta Tier D and even a 17% tail on the best system

Slide 55. "An agent that remembers" is not always better: Letta Tier D and even a 17% tail on the best system

Having memory intuitively seems like a pure improvement — an agent that remembers should be more useful than an agent that starts from scratch every time. Data from the agent-harness-registry, an independent registry[1] that tests systems on real tasks, shows that this is not always so, and sometimes dramatically not so. On the slide the systems are marked with a Tier letter — this is the registry's rating category from A (the best results) to D (the worst) by the sum of live-eval benchmarks; the closer to A, the more stably the system showed itself on the full set of tests. The first case is the Letta system, Tier D. By the registry's data it loses both to the bare model with no memory at all and to a trivial flat file on all fully tested benchmarks: on persistbench the bare model gave 1.000, the flat file 0.833, and Letta only 0.750, while being an order of magnitude slower. Three failure mechanisms were identified: capitulation under pressure, when on a repeated question the system changes an already given correct answer to an uncertain one; verbosity, when a long embellished answer hides the short correct fact; and a fact noticed but not committed to memory. A freshness caveat is mandatory: a version about eighteen months old was tested due to an installer limitation, not due to cutting a corner, so this is an assessment of a specific outdated version.

The second case is more important, because it is the best tested system. The Anthropic Memory Tool is strong overall, but even it recorded information loss in four tasks out of twenty-four, that is, in 17 percent: an explicit refusal to record a fact deemed ephemeral; a refusal as "out of scope"; and quiet summarization, when specific facts are imperceptibly absorbed into general categories. The most alarming detail is irreproducibility: the same conversation, submitted twice, produced different behavior. This is not a bug but documented design: the model is asked to apply judgment on what is worth recording, and this judgment produces real, sometimes contradictory failures. The conclusion is one: even for the best memory system there is a measurable tail of losses. "Works well" and "works always" are different statements, and this is the same lesson as the RAG failure at scale and catastrophic forgetting.

Sources: [1] agent-harness-registry (live-eval) — Letta Tier D / Memory Tool 17% tail

56 · Skills, subagents, access — and the trust boundary: injection x broad privileges = catastrophe

Slide 56. Skills, subagents, access — and the trust boundary: injection x broad privileges = catastrophe

The remaining three harness slots — skills, subagents, and access to external systems through MCP — we will examine together with security, because the security question is inseparably woven precisely into here. A skill is a reusable procedure for a recurring task: an instruction on how exactly to do the work so as not to reformulate it every time. A subagent is a dedicated agent with its own context window to which part of the work is delegated, so as not to clutter the main context and to isolate untrusted work. Access through MCP is already familiar, but here the practical side matters: every MCP connection is a new trust boundary, one more piece of code trusted to execute, one more channel through which untrusted text enters the context, and one more data-retention policy in the chain.

Hence a specific class of attacks. Prompt injection is an attack in which text is embedded into external data in the model's context, which the model interprets as a command and executes; the root is that the model trusts convincingly sounding tokens and does not distinguish data from a command[2,3]. GitHub MCP heist, May 2025: the assistant has a broad token to all repositories; in a public issue — the instruction "gather the private repositories and publish them here"[1]; the assistant reads the issue as a command and exfiltrates the private ones. A catastrophe is injection multiplied by broad privileges; remove either of the two, and the attack does not go through. And on data retention, two facts against the naive "we have ZDR, everything is fine": ZDR, Zero Data Retention, is a vendor policy not to store request content after processing; a court order[4,5] in NYT v. OpenAI mandated retaining all logs over any contractual policy; and vendors' ZDR does not cover third-party integrations and MCP connectors — that is, exactly the links an agent is made of. Hence four rules: least-privilege, isolation of untrusted content, human-in-the-loop on irreversible actions, an allowlist with version pinning. Plus a data map per feature — what passes through which link and what its retention policy is.

Sources: [1] Docker — MCP Horror Stories: GitHub Prompt Injection · [2] Simon Willison — Prompt injection via MCP · [3] Palo Alto Unit 42 — MCP Attack Vectors · [4] Bloomberg Law — NYT v. OpenAI (court ordered logs to be kept) · [5] Anthropic — API and Data

57 · A data map by feature: ZDR does NOT cover third-party/MCP; least-privilege is mandatory

Slide 57. A data map by feature: ZDR does NOT cover third-party/MCP; least-privilege is mandatory

"We have ZDR turned on, so the data is protected" — a typical and dangerous oversimplification when designing an agent system. ZDR, zero data retention, is a mode in which the provider does not store the content of requests and responses after processing, but it covers far from the whole chain. At leading vendors, ZDR extends to the main model calls but does not cover a whole set of adjacent capabilities: the Files API, batch processing, code-execution containers, the MCP connector, third-party integrations, and consumer pricing plans. Here lies the trap specifically for agent systems: an agent is by definition a model plus tools, and the tools are again and again exactly third-party services or MCP servers — precisely the links that ZDR does not cover. The more "agentic" the architecture becomes, the more data passes through links that live outside the protection of zero retention.

The second fact, which breaks naive confidence in a contractual retention policy, is the New York Times v. OpenAI case. In the course of the litigation, a federal court ordered OpenAI to preserve absolutely all ChatGPT logs as potential evidence, regardless of what was written in the company's own policy. The provider's stated policy of "we delete after thirty days" proved wholly powerless before a court order in a dispute entirely external to the client. Hence the practical conclusion: data that has left your perimeter starts to live by rules you do not control, and a provider's promise is a description of normal conditions, not a guarantee for every case.

The design rule that follows from both facts: before releasing a feature into production you need to build a data map — which data exactly passes through which link of the chain, what the link's real retention policy is, and which links belong to a third party at all. For regulated or highly sensitive data the only reliable option is to work only through links with ZDR or a signed data-processing agreement, or to deploy the model on your own infrastructure. "We turned ZDR on" is not a project checkbox but one item from a map you need to build in full.

58 · Real coding agents — through the equipment frame: Claude Code / Aider / Cursor / OpenHands

Slide 58. Real coding agents — through the equipment frame: Claude Code / Aider / Cursor / OpenHands

Let us gather the whole conceptual apparatus of the section — API and MCP, the agent loop, the distinction between a workflow and an agent, the five harness slots — into one practical reference point: how real coding agents of 2026 look through these concepts. We show each tool not through marketing but through the harness frame[1]: what harness it has by the map of five slots. Claude Code — a broad harness: its own memory between sessions, support for instruction files, built-in skills, full-fledged subagents with a separate context window, access to external systems through MCP; almost all slots are filled, which gives capabilities at the price of greater operational complexity. Aider — the opposite point: minimal file simplicity, no developed memory, no subagents, no formal skills; open-source, CLI-first. It demonstrates an important thesis: a thin harness is not an underdeveloped version of a full one but a deliberate working choice for tasks where a broad harness is not needed.

Cursor — the third point: not a terminal but a desktop editor with a built-in agent, a VS Code fork. It shows that the harness is not the only axis: the form of integration into the workflow, terminal versus IDE, is a separate architectural decision. OpenHands — a self-hosted autonomous platform with an MIT license, deploys locally or in Docker. By profile — open source, autonomy, MIT license — this is a likely candidate for the tool mentioned by ear as "OpenClaw"; this is a working hypothesis by profile match, not an established fact, and it is worth confirming. The general conclusion of the overview: the difference between real coding agents is not in the quality of the model inside them but in which harness slots are filled and where the agent physically lives. This is a direct application of the whole section map and of the same logic "do not take the most equipped option by default."

Sources: [1] agent-harness-registry — a survey through the equipment frame

59 · Six typical agentic tasks on one schema (coding / support at Air Canada+Klarna / ETL / research / browser-Operator / SRE ITBench): task -> loop shape -> where it breaks -> would a workflow be better?

Slide 59. Six typical agentic tasks on one schema (coding / support at Air Canada+Klarna / ETL / research / browser-Operator / SRE ITBench): task -> loop shape -> where it breaks -> would a workflow be better?

Let's walk through six typical agentic tasks on one schema: task, loop shape, where it breaks, would a workflow be better. This translates the general ladder principle into concrete working scenarios, with real anchors. Individual figures are illustrative, but the classes and anchors are real.

First — a coding agent, Claude Code or Cursor. The task is to implement or fix code across an entire repository from a natural-language statement. The loop: read the repo, plan, edit files, run tests, see failures, iterate, open a PR. It breaks on large, ambiguous refactors and on getting stuck looping on flaky tests. Would a workflow be better? No — open-ended code search genuinely requires agency; this is the canonical case where an agent is justified.

Second — customer support, and here there are two instructive cases. Air Canada[1]: a support bot invented a 90-day refund window, and the tribunal ruled the airline liable to pay out — a policy hallucination became legally binding. Klarna publicly celebrated an AI that replaced 700 agents, then rebuilt human capacity, because edge cases and escalation judgment brought people back into the loop. Would a workflow be better? Often yes for the risky part: refunds and policy answers want deterministic routing with guardrails, not free generation.

Third — an ETL agent, a self-healing pipeline. The loop: spot a schema drift, analyze the impact, generate a transform, validate, apply under a guardrail. It breaks because silent bad transforms corrupt data at scale, and nondeterminism is dangerous in a pipeline that needs to be auditable. Mostly yes — the trunk is deterministic, and an agent belongs only on the narrow step of fixing the drift. Fourth — a research agent, Deep Research. It breaks with a cost blow-up of roughly fifteen times in tokens and with hallucinated citations. No for genuinely open-ended broad research, yes if it's actually a fixed lookup.

Fifth — a browser agent, Operator. The loop: a screenshot and the DOM, plan a UI action, click, observe. On the OSWorld benchmark the first generation scored around thirty-eight percent[2] of tasks completed, and the Operator product itself was discontinued — a live lesson in "hype — market exit." For any consequential action, payments and forms — yes, use a real API if one exists. Sixth — an SRE agent. On the ITBench benchmark, frontier models autonomously resolve only about 14% of scenarios, so the real value is narrowing the search space and leaving the judgment to people. The cross-cutting principle: an agent — for the adaptive edge, a workflow with gates — for the trunk and for consequential actions; the Operator and ITBench numbers mean "narrow the search," not "replace the person."

Sources: [1] McCarthy Tétrault — Air Canada (bot invented a policy) · [2] OSWorld / WebArena / ITBench — agentic-task benchmarks

60 · A catalog of 10 CLASSES of failures as a table: class -> case -> lesson (188 of 344 — the agent broke it itself)

Slide 60. A catalog of 10 CLASSES of failures as a table: class -> case -> lesson (188 of 344 — the agent broke it itself)

The agent loop plan-act-check-repeat has four points of failure, and next we work through these modes in dated cases — each with a lesson and an alternative. But before going through the cases, it is important to fix the way to read the whole catalog: the learning unit here is the failure class, not the individual incident; the concrete cases are illustrations of a class, not material for memorizing dates and sums. On meeting a new incident in practice, the useful skill is to name which failure class exactly it belongs to, because the class determines the countermeasure: restricting privileges, isolating untrusted content, validation between steps.

The scale is set by the anchor number: of seven thousand two hundred forty-six publicly documented AI incidents, three hundred forty-four are selected as relevant to business systems, and already among those, in one hundred eighty-eight — about fifty-five percent — an autonomous system did the harm right in production without any attacker in the chain: the agent broke everything itself, with no one else's malice. This changes the intuitive picture of the risks of agent systems: most often the danger comes not from an external attack but from the agent's own logic meeting a situation no one anticipated.

The ten classes from the table cover the whole failure map of the section: a destructive action combined with excessive privileges, injection via untrusted content without a single click by the victim, uncontrolled cost growth, delivery of malicious code through hallucinated package names, an untrusted MCP server, a cascade of errors in a multi-agent system, the company's legal liability for the words of its own bot, a loop without budget limits, the mathematical accumulation of errors along a chain of steps, and the general fragility of multi-agent architectures on dependent subtasks. Each of them will be worked through separately with a concrete case, but keep in mind the key point: the goal is to recognize the class, not to remember the numbers by heart.

61 · Deep-dive of the classes: PocketOS 9 sec, runaway $48k/$1.3M, slopsquatting 19.7%, cascade 61%

Slide 61. Deep-dive of the classes: PocketOS 9 sec, runaway $48k/$1.3M, slopsquatting 19.7%, cascade 61%

Let us work through four classes in more detail, each with a concrete comparison baseline. The first — destruction under excessive privileges. A coding agent in a test environment found a token with unlimited privileges and deleted the production volume with all its backups in nine seconds; the nearest backup was three months old. Lesson: the system prompt is not a security control; only an architectural boundary and least-privilege reliably stop an agent.

The second — uncontrolled cost. A research agent with no success criterion spent $48k in 14 hours, 100 instances burned $1.3M in a month. Baseline: an ordinary session costs cents to dollars, this is 3–5 orders of magnitude higher. Lesson: a termination criterion, a hard budget cap, an emergency stop.

The third — slopsquatting: agents invent package names, attackers register them with malicious payloads. Almost one in five generated imports pointed to a nonexistent package. Lesson: do not install dependency names without verification against a registry.

The fourth — multi-agent cascade: one agent's error passes down the chain as a fact, the following agents rely on it. In real incidents the root is often not where the failure is visible but at an upstream step — in retrieval or planning. The general conclusion: the agent was applied without an external boundary. Such a boundary sits outside the agent and is not replaced by a prompt.

62 · Section 5 — gather all the architectures and their failures into one choice tool

Slide 62. Section 5 — gather all the architectures and their failures into one choice tool

By this point we have gone up the ladder from the bottom and examined each rung separately: a single call and its limits; RAG and when it is not needed; fine-tuning, its narrowing and its failure through catastrophic forgetting; the API layer, MCP, the agent loop, the difference between a workflow and an agent, agent failures, and the security of the chain. For each architecture we deliberately examined not only "when it is right" but also "when it fails" and "when the right answer is a completely different tool." That was preparation.

Now — the final section, for the sake of which everything else was undertaken. Separate knowledge about RAG, agents, and fine-tuning does not by itself give the lecture's main skill — the skill of choosing with justification. The fifth section gathers everything examined into a single working tool: the ladder of complexity with the rule "climb only for a task requirement," the choice matrix along axes with an explicit lower bound "when not AI at all," an eight-step checklist that folds the ladder and the matrix into a two-minute procedure, and the rule of the human validator. This is the payoff of the central question: by the end of the section, for any task you will be able to name an architecture, give at least two reasons along the axes, indicate at least one condition under which the choice would be different, and say under which signs AI is not needed here at all. And on this same checklist slide you will try to apply the tool yourself — on a new task.

63 · Classical technology choice: from the requirement, not the tool; build-vs-buy, KISS, YAGNI, the principle of least power; the architecture ladder is the same "simplest that works" principle

Slide 63. Classical technology choice: from the requirement, not the tool; build-vs-buy, KISS, YAGNI, the principle of least power; the architecture ladder is the same "simplest that works" principle

Before building the framework for choosing an AI architecture, let us restore what it grew out of — the classical engineering discipline of technology choice, which existed long before the AI hype and has not gone anywhere. Every previous section already showed the same figure of thought: from the classical base to what AI adds, and to what remains mandatory from the classics. This section closes the chapter with the same move at the top level: the choice of architecture itself is not a new AI-specific procedure but a direct application of the classical principles of engineering decision-making.

The classical discipline of choice rests on several named principles. Requirements engineering is the starting point: first you fix what the system must do, and only then pick the tool for the requirement, not the other way around. The choice goes from the requirement, not from the tool: a technology is taken because it meets the requirement, not because it is new or fashionable. Build-vs-buy is the analysis of whether to solve the task with your own development or take a ready-made one. KISS demands choosing the simplest solution that meets the requirement. YAGNI forbids building in capacity for the future without a concrete requirement. The rule of least power from the W3C notes of Berners-Lee and Mendelsohn: choose the least powerful of the sufficient tools, because it is easier to analyze and maintain.

How this worked in practice before the AI hype. An engineer started not with "which tool would be interesting to try" but with the requirement: is a database needed or does a file suffice; is a microservice needed or is this a module of a monolith. Whoever put a distributed system where one process sufficed made a mistake that was not technical but disciplinary — took capacity without a requirement.

Now the bridge to the ladder. The architecture ladder is the same classical principle "the simplest thing that works", applied to the choice of an AI architecture. The rule for moving up it — do not climb without a requirement that the rung below cannot meet — is literally KISS and YAGNI in the language of AI systems. The AI era repeals none of these principles — it makes them costlier to violate, because the price of an extra rung is higher than the classical one: nondeterminism, tokens, latency, a new attack surface. The on-point failure of the section, the MIT NANDA report, is a direct illustration of the price of violation: pilots without ROI take AI without a formulated requirement.

64 · The complexity ladder: stay on the bottom rung, climb only for a requirement; the bottom is code without AI

Slide 64. The complexity ladder: stay on the bottom rung, climb only for a requirement; the bottom is code without AI

Let us gather everything we have covered into one structure — the ladder of architectural complexity[1]. Each rung is an architecture we examined. Bottom-up: ordinary code without AI; a single model call with a prompt, possibly with step-by-step reasoning and examples; RAG or context engineering, and for a small stable corpus — long context with caching; a workflow with predefined paths; an agent with a dynamic loop and mandatory limits on budget and iterations; and at the top a multi-agent.

The rule for moving along the ladder is the load-bearing rule of the whole lecture: stay on the lowest rung that closes the task's requirements; climb to the next one only for an explicitly stated requirement that the current rung does not close. Each climb is paid for with new failure modes, cost, latency, degraded auditability, and a new attack surface. "Climbed because I could" is technical debt; "climbed because here is a requirement not closed by the rung below" is an engineering decision. Note that the bottom rung is ordinary code without AI: the ladder of AI system architectures begins with "maybe AI is not needed here at all."

Let us gather exactly which requirement opens each climb — this is the transition from a ladder-picture to a ladder-tool. Code to a single call: a requirement appeared to process natural language, unstructured input, fuzzy matching, which cannot be expressed with deterministic rules. A single call to RAG: a requirement for knowledge appeared that is not in the weights and that is large, and changing, and requiring provenance, and private simultaneously. To a workflow: the task became multi-step, but the sequence of steps is known in advance. A workflow to an agent: the sequence fundamentally depends on intermediate results such that it cannot be written out in advance, and the task's value justifies the multiplied cost, latency, and loss of auditability. An agent to a multi-agent: the subtasks are broadly parallel, independent, and high-value enough that the gain of parallelism outweighs the multiplied growth of tokens and the fragility of coordination. Each arrow is not an "improvement" but a trade: more capabilities in exchange for cost, latency, auditability, attack surface. An engineer who has this skill can name both sides of the trade, not only the left one.

Sources: [1] Anthropic — Building Effective Agents (the ladder rule)

65 · The agent starter kit — a thin default + justified triggers for adding complexity

Slide 65. The agent starter kit — a thin default + justified triggers for adding complexity

The ladder gave a rule for the architecture of the whole system. The same principle must be applied inside a single rung — "agent" — to the question of exactly which harness to equip it with by the map of five slots. This is not a new idea but the same ladder one level down. The default is a thin agent. By the harness registry's data, the starting point for a new assistant agent is one instruction file and flat memory, without subagents, without a complex set of skills, with minimal access to external tools. This is exactly the same default as "a single call" on the ladder of architectures: not because a thin harness is always sufficient, but because the burden of proof lies on complication, not on simplicity.

The triggers for complication are explicit, and each answers a concrete question rather than a general "will come in handy." A memory backend instead of a flat file is added when the history has outgrown what fits in the context, or when structured retrieval by facts is needed — this is verbatim the same criterion that determines the transition from a prompt to RAG, only applied to the agent's own history. Subagents are added when a concrete subtask requires a separate context window or isolation of untrusted work; an abstract "let it be there for flexibility" is not a trigger. More access through MCP is added when a concrete task requires a concrete tool, not just in case, because every connection is a new trust boundary. And an important detail: the presence-paradox study directly shows that adding an instruction file as a ritual does not work without a real gap that it fills. Giving the agent everything at once is that very cargo cult the whole ladder works against.

66 · Next — industries, starting with software development; the SDLCxAI axis; this frame is the base of Lectures 4–17

Slide 66. Next — industries, starting with software development; the SDLCxAI axis; this frame is the base of Lectures 4–17

Lecture 3 closes the course's overview module, which went in an ascending order: Lecture 1 — what AI is and how a prompt is built; Lecture 2 — why a prompt works: tokenization, embeddings, attention, sampling; Lecture 3 — how to assemble a system out of a model and how to choose which system to assemble. These three lectures are a common foundation; next the course moves to the industry lectures, where AI is applied to concrete subject tasks.

This lecture's framework — the ladder of complexity, the choice route, the eight-step checklist, the rule "when not AI," the agent starter kit, the rule of the human validator — is the base for all subsequent lectures, not material that ends with this lecture. In every industry topic the same question will repeat in a new wrapper: here is a subject task — which architecture and why exactly this one, and under what condition the answer would be different. Now you have the apparatus to answer it. A practical piece of advice for the rest of the course: at every industry lecture, hearing "here they apply RAG, an agent, or fine-tuning," mentally run the checklist — does the task requirement really raise you to this rung, or is it inertia.

Lecture 4 takes this apparatus and applies it to the first industry topic — AI in software development. There the question "which architecture and why" will meet you again, now on concrete tools and tasks of a developer: the same coding agents we examined through the harness frame — Claude Code, Aider, Cursor, OpenHands — will there be considered from the side of engineering development practice. The assignment — for Seminar 3. The paired seminar "Architectural choice: chat, agent, RAG, API — three cases" is the place for full mastery of the application learning goal. You will apply the eight-step checklist to three cases and for each formulate: the architecture, at least two reasons along the axes, at least one condition under which the choice would be different, and an explicit criterion "here it would be NOT so." Mini-apply task B from the previous slide is a warm-up before the seminar.

67 · Q&A

Slide 67. Q&A

This is the lecture's final slide, set aside for questions. The substantive part of all five sections is finished: we have gone the path from the central question — there is a task and access to a model, which architecture to choose and when the right answer is "not AI" — through the prompt and its limits, RAG, fine-tuning, API with agents and security, to the decision framework. The best time to ask a question is now, while the whole picture is fresh and held in mind as a whole.

A few directions along which questions arise most often, to give something to start from. First: the boundary between RAG and fine-tuning on a concrete task — if it is unclear what in your case is "knowledge" and what is "behavior," this is a typical and correct point for a question, because it is precisely here that people most often err in practice. Second: where the boundary "AI is not needed here at all" runs — how on a real task to tell a case requiring ordinary deterministic code from a case where AI is truly justified. Third: the security of the data chain and injections through tools — what of this applies to your current projects. And fourth, organizational: the assignment for Seminar 3 — "Architectural choice: chat, agent, RAG, API, three cases" — where you will apply the eight-step checklist; if something in the wording of the assignment is unclear, this is also a good question to ask now rather than a day before the seminar. The seminar is in a week; additional questions can be sent by email.


Comments