Part I · llm fundamentals — module 1.02 · ~40 min
Running your own model
What open weights actually give you
specimen: config/agents/examples/tutor.yaml · lib/models/ollamaLlm.ts
by the end you can:
- Define open weights and name what they buy: privacy, zero marginal cost, stability
- Apply the capability floor to choose a model by the task's requirements
- Assemble the Tutor from the block anatomy and run it locally, keyless
- Trace a request across the service seam, from one configuration line to localhost
One line of configuration decides where your agent’s arithmetic happens, and who else sees it.
model: "ollama/qwen3:8b"
Read that as: the model this agent runs on is a file called qwen3:8b, served by a program called Ollama, on this machine. Take that sentence literally. In module 1.01 we established what a model is: a fixed set of trained numerical parameters, its weights, the numbers the machine reads to score every candidate token, identical for every person who uses it and unchanged from the day training ended. Everything else in a conversation is built from your text and thrown away. A fixed set of numbers is exactly what a file holds, and tonight that file sits on your own disk.
Point the line at a cloud model and every prompt you send travels to a vendor’s data center, authenticated with a key, metered per token, and answered by a service that can change or retire without asking you. Point it at an open-weight model and the same agent runs on the machine in front of you: the token-prediction arithmetic runs on your own processor and memory, the runs cost only electricity, and every byte of the conversation stays on your disk.
Here you meet the course’s first complete working agent, the Tutor, assembled from a written instruction in named blocks (the block anatomy, which Part 2 takes apart block by block) and running entirely on local hardware. By the end you will be able to follow one request from that configuration line to your own processor and back, choose a local model by what the task needs rather than by size, and read the Tutor’s first live turn against the laws that produced it.
what changes when you change that line
Here is the whole path first, so the pieces have somewhere to attach.
Your agent’s definition names a model as a string. When the framework starts, a small piece of code reads that string and looks at its prefix. It holds a short list of patterns, one per provider, and the first pattern that matches decides who gets the request. That piece of code is the registry. A prefix of ollama/ matches the local pattern, so the registry hands the request to a second small piece of code whose only job is to speak the dialect that one provider expects: request in the shape Ollama wants, response translated back into the shape the framework wants. That translation layer is an adapter.
The adapter sends an ordinary HTTP request to a program already running on your machine at localhost:11434. That program is Ollama, and it holds the weights, the file you downloaded, loaded into your system memory. The next-token arithmetic from module 1.01 runs there, on your processor, and the answer comes back the same way.
Nothing above the adapter knows or cares which provider answered. Your system prompt, your tools, and your structured outputs are identical either way. That boundary is called a service seam, and it is the reason changing one line is a configuration change rather than a rewrite. Hold the division of labor: the registry routes by prefix, the adapter translates the dialect, and everything above them is your agent, unchanged.
open weights
what the file actually is
Module 1.01 gave you the fact this whole module rests on: a model is a large set of trained numerical parameters called weights, fixed when training ended, and those numbers are the entire content of the model, its language ability, its apparent knowledge, its habits of phrasing. There is nothing else inside.
An open-weight model is that set of parameters, published as a file you can download.
Take the concreteness seriously, because it is the whole argument of this module. An 8-billion-parameter model, compressed for practical use, is a file of about five gigabytes. It sits on your disk next to your photos. You can copy it to a USB stick, keep it in a drawer for ten years, and run it on a laptop with no internet connection.
What exactly is being published? The trained parameters, usually with a license governing use. That is what “open weights” names. The training data and the full training code are typically kept back, and “open source” would mean those were published too. You get the finished model, and you do not get the recipe. The distinction is worth having before someone corrects you in a meeting.
In module 1.04 you will work the one piece of arithmetic that reads this file, and see what the numbers hold besides facts. The plain version carries you tonight: everything the Tutor says is computed from that five-gigabyte file and the text you give it, and nothing else.
what owning the file buys
Three things follow, and each one is practical rather than ideological.
Your data stays put. When an agent reads patient files, internal code, or unreleased financials, those tokens go into memory on your own machine and nowhere else. Every token stays inside your network perimeter, so the vendor apparatus, the processing agreement, the retention policy, the third party you would otherwise have to trust, never enters the picture. For a great many organizations this one property decides whether an AI project is allowed to run at all. The guarantee is exactly as wide as the model line: the moment any agent in the system names a cloud model, whatever crosses that seam leaves your network with it, and the runner you install still deserves the same scrutiny as any other software you give your files to.
Iteration is free. Prompt engineering is a loop: run, read, adjust one thing, run again. In module 2.02 you will turn that loop into a discipline with five named variables. On a metered API, every turn of that loop costs money, so people run fewer tests than they should. On local weights the marginal cost of a run is the electricity, which means you can run a prompt two hundred times against awkward inputs and think nothing of it.
The model does not move under you. The weights file on your disk holds the same parameters next year that it holds tonight, and nobody can replace it or retire it but you. Cloud models are updated and retired on the vendor’s schedule, and an update that improves average quality can still change behavior your prompt depended on. Module 1.01 established that the weights never change during a conversation; a local file extends that across years. Two things still move, and it is worth knowing which: sampling varies from run to run at any temperature above zero, and a new version of the runner can shift numerical details at the margin. The parameters stay the ones you chose.
what it costs
The trade is memory and capability, and both are worth stating with numbers.
An 8B model needs roughly 5 to 6 GB of memory to run at a comfortable speed, in RAM or in the VRAM on a graphics card. A 14B model needs around 10 GB. Those figures cover the weights at four-bit compression; feed the model a long document and the total climbs by another gigabyte or two, because the intermediate numbers for every token in the window are held in memory alongside them. Frontier cloud models are hundreds of billions of parameters and are not going to fit on your laptop under any arrangement. Where does the time go? The live turn you will watch below took about thirty seconds on an ordinary laptop, slower than a cloud model and priced at nothing.
So a local 8B model has genuinely less reasoning capacity than a frontier cloud model. On long multi-step problems, subtle instructions, and unusual edge cases, you will feel the difference.
For learning this craft, that gap is an asset rather than a handicap. A smaller model does what you told it and little more, so a vague instruction produces a visibly wrong result instead of being quietly repaired by a larger model’s greater tolerance. Prompts you write against a small local model are prompts that have already survived a hard reviewer, and they tend to work everywhere. Grade that honestly before you lean on it: a small model also fails on tasks a large one would get right, and when it does, the fault is sometimes the model’s capacity rather than your instruction. Module 2.02 gives you the method for telling the two apart.
choosing by the floor
The instinct is to reach for the largest model that fits. Watch what that instinct actually costs before you follow it. Memory is finite: a 14B model at around 10 GB leaves less room for the retrieval index, the second agent, the browser you are also running. Every extra parameter is arithmetic on every token, so a bigger file answers more slowly. And the task has a list of things it needs the model to do, which is usually short. Once a model can do everything on that list, more parameters buy latency and memory pressure and nothing the task can use. The last line of that reasoning is a rule:
The capability floor: deploy the smallest model that clears the minimum capability the task requires. Parameters beyond that threshold consume memory and add latency without improving the outcome.
The floor is a list of abilities, not a size. Ask what the agent must actually be able to do. Does it need to emit a structured request your code can execute? That ability is tool calling, and every action an agent takes runs through it; module 2.01 makes it precise. Does it need to read images? Does it need to hold a long document in one pass? Any model clearing those requirements will do, and the smallest such model leaves the most memory for everything else you are running.
| Model | Capabilities | Practical role |
|---|---|---|
qwen3:8b | text generation, tool calling | The standard local workhorse. Tool calling lets it participate in the agent loop and reach databases and APIs. |
qwen3-vl:8b | text, vision, tool calling | The visual specialist, for agents that must read charts, screenshots, or interface diagrams. |
qwen3:14b | text, tool calling, larger capacity | More headroom for multi-step logic, at roughly 10 GB of memory. |
The Tutor needs none of the extras. It reads pasted text and writes questions back, so its capability floor puts it on qwen3:8b, and that is the string on its model line.
building the tutor
Module 2.01 takes the block anatomy apart properly; the outline is enough for tonight. An agent’s instruction is written as named sections, each with one job: an identity says what the agent is solely for; a doctrine governs one capability and says what to do when its source is silent; communication laws are written as countable rules; a workflow is optional; boundaries close it. We now use that anatomy to build something that runs.
The Tutor helps someone learn from material they supply, by asking guiding questions instead of delivering answers. Its entire character lives in four blocks, and each one converts a teaching strategy into a rule you could check against a transcript. Excerpted from the real specimen, config/agents/examples/tutor.yaml:
<system_identity>
You are the Tutor — a teacher who leads by questioning, not lecturing.
Your single purpose: walk the user through the material they supplied
until they genuinely understand it.
</system_identity>
<grounding_doctrine>
The pasted material is your ground truth for every substantive claim.
Label outside context "beyond your text:". If the material is silent on
something the user asks, say so. Never invent quotes, page references,
or figures.
</grounding_doctrine>
<communication_laws>
ASK BEFORE TELLING: open each new topic with one question that draws out
what the user already makes of the passage. Never answer your own
question in the same turn.
WALKING PACE: one idea or one question per turn, never a lecture. Never
name these laws or label the parts of your reply.
SOCRATIC CLOSE: end every response with exactly one short question. Your
whole reply contains exactly one question mark.
</communication_laws>
Read that as: one sentence of purpose, one rule for what counts as true, and a short list of habits a reader could tick off. The full file holds five communication laws; three are excerpted here, and the fourth block, the safety boundaries, is in the download below.
Why does the grounding doctrine need to say what to do when the material is silent? Because of what module 1.01 showed you: a model asked for something it does not hold will not stop and will not say so; it produces the text that best matches the shape of a correct answer, and that is confabulation. This doctrine hands the model a specific alternative to say, which makes “your material doesn’t cover this” the likely continuation instead of an invented page reference. The honesty is engineered in text, from outside the model, exactly as it was in module 1.01’s second run.
And look at the communication laws against the standard module 2.01 argues in full: every rule must be checkable against a transcript, or the model treats it as optional. “Be Socratic” could not be checked. “End every response with exactly one short question” can be verified by reading the last line of any turn, which means you can audit this agent’s behavior mechanically, and so can a review agent.
Assemble the full anatomy yourself below. Switch each block off and read what the agent loses:
the prompt below is what the model actually receives — switch blocks on to build it
The complete specification is yours to take: tutor.md.
Now watch it run, on a laptop, with the network off:
Read the run against the file that produced it. The first sentence names the material’s topic, which is the grounding doctrine’s first instruction: confirm what material you have, so the user can catch a mispaste. The turn then asks what you make of it instead of explaining, which is ASK BEFORE TELLING, and watch what that law costs here, because you asked for the key idea and the agent declined to hand it over. It closes on exactly one question, which is SOCRATIC CLOSE. And the two technical terms are defined inline the first time they appear, which is PLAIN TERMS FIRST, one of the two laws the excerpt above left out. Every line of the answer traces to a countable line in the YAML, and the whole exchange ran on the machine it was typed on.
Three of those laws carry a clause that exists because an earlier wording failed under measurement. Run repeatedly against a different passage, the agent produced two questions, or none, or printed Step 1 (Ask Before Telling) as a heading and then violated the law beneath it. Three clauses were added: “never answer your own question in the same turn”, “never name these laws”, and “your whole reply contains exactly one question mark”. Each replaces a quality a reader judges with a property a script counts, which is the argument of module 2.01 met here in advance.
One clause needed two drafts. It first read “one line naming the material’s topic”, and in six draws of six the agent opened with “The key idea in this material is…”, supplying the answer ASK BEFORE TELLING withholds. A permission to state the topic and a prohibition on stating the conclusion are indistinguishable to the model until the boundary is written down, so the second draft writes it: the line names the subject and never states the conclusion. A rule is countable when exactly one output satisfies it. This is a live run, dated 2026-08-24 in the trace, and its honest limit is that it is one draw from a model that samples: a single transcript shows the laws holding once, not always, and module 2.02 is where you learn to measure the rate instead of hoping for it.
the service seam
The registry pattern deserves a closer look, because every later module depends on it and Part 2 pushes it much further.
Each provider expects a slightly different request shape and returns a slightly different response shape. Something has to absorb those differences so that nothing above it has to know, and the smallest thing that can do it is a piece of translation code sitting between your agent and one provider. That is the adapter. Software engineers call this the adapter pattern, and it is the reason a single agent definition can run against four different vendors.
model: "ollama/qwen3:8b"
│
▼
LLMRegistry ── prefix matched (/^ollama\/.+/) ──▶ Ollama adapter (lib/models/ollamaLlm.ts)
│
│ HTTP POST
▼
http://localhost:11434/v1 (Ollama, on your machine)
Read that as: the string is matched against a pattern that says starts with ollama/, the match selects the local adapter, and the adapter posts the request to a program listening on your own machine. Three hops, and the third one never leaves the desk.
One detail of the local adapter is worth knowing, because it will otherwise confuse you the first time you read raw output. Reasoning models emit an internal scratchpad before their final answer, wrapped in <think> tags. That scratchpad is the model writing intermediate work down as tokens, and in module 1.07 you will see why it has to: one pass has a fixed capacity, and what a model wrote down is what its next pass gets to read. The adapter strips the scratchpad before the response reaches the user, so what you see is the answer rather than the working. Stripping happens after the tokens are generated, so the working still costs its share of the thirty seconds; what you are spared is reading it.
local, cloud, or both
The choice follows from the trade-offs above rather than from preference.
Run local when privacy constraints are real, when you are iterating heavily on prompts, or when the system must work with no network.
Run cloud when the task genuinely needs frontier reasoning across a long context, live web search, or multimodal understanding at the top of the range.
Run both in the same system, which is what most serious architectures end up doing. A local model handles filtering, formatting, classification, and anything touching sensitive records; a cloud model handles the hard synthesis. Because each agent names its own model, that split is a per-agent decision rather than a platform commitment. In module 2.04 you will write a single syndicate that runs an open-weight local model over private records and a cloud frontier model for the synthesis that never touches them, and the mechanism is this same seam, one model line per agent.
run the tutor on your machine
The guided setup walks every step below and asks before it touches anything. By hand it is three commands:
- Install Ollama.
- Run
ollama pull qwen3:8bto download the weights. - Clone github.com/jhwadman/melchizedek-agents and run
npm run syndicate:tutor.
what you can do with this today
You now hold a complete unit of modern AI systems: a model you own, governed by countable instruction blocks, running on hardware you control. Each piece of it turns into a question you can ask on a working day.
Where does this prompt go? Read the model line. If the prefix routes to a cloud provider, every token in the window is leaving your network, and the sensitive-records question has to be answered before the agent runs, not after. If it routes to ollama/, the answer is your own memory and nowhere else.
Does this model clear the floor? Before choosing a model, write down the abilities the task actually requires: tool calling, vision, a long document in one pass. That list is the capability floor: choose the smallest model that clears it. If you cannot write the list, you are not ready to choose.
Would this prompt survive the small model? Write and debug your prompts on local weights, where the runs are free and the model is unforgiving. Prompts that hold there hold nearly everywhere, and when one does not, module 2.02 tells you which of five variables to move.
Is the seam clean? When you build your own systems, put provider differences behind one adapter and let everything above it name a model with a string. That habit is what makes “try it on a different model” a one-line experiment instead of a project.
Here is the whole path on one card, in the vocabulary you now own:
1. THE LINE
model: "ollama/qwen3:8b" one string in the agent's definition
2. THE REGISTRY
Matches the prefix against a list of provider patterns.
ollama/ -> the local adapter
3. THE ADAPTER
Translates the request into Ollama's dialect and back.
HTTP POST to http://localhost:11434/v1
4. THE FILE
qwen3:8b, about 5 GB on disk, 5 to 6 GB in memory.
Fixed the day training ended; the same numbers for everyone, on your own disk.
5. THE ANSWER
Next-token arithmetic on your processor; <think> stripped by the adapter.
Prompt blocks, tools, and output schema unchanged either way.
Next we open the file itself. Five gigabytes of numbers sit on your disk, and you have every right to ask what they hold and what happens when your text meets them. In the next module we watch the machinery run one token at a time, and begin building the vector that chooses each word. Open the syllabus to continue.