Getting started with an open model
The service seam under every local agent, kept whole — how one configuration line routes a request to Ollama on your own machine, what the registry and the adapter do, and when to run local, cloud, or both.
This page holds the plumbing for open model routing, kept in one place so it stays reachable when you need it: how a single model line decides whose machine does the arithmetic, and what sits between your agent and the program that answers it.
One line of configuration names the model your agent runs on, and with it, whose machine does the work and who else sees your text.
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. Earlier 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.
your agent runs on your hardware or a vendor’s
One string decides all of that, and between the string and the answer sit two small pieces of code. Follow a single request through them.
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 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.
switching providers does not change your agent
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 you have already seen the raw version. 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 our reasoning trace breakdown 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. In ollama run nothing sits between you and the model, so the scratchpad printed dimmed above each of your quizmaster’s replies. Behind the adapter it is stripped 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 run time; 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 our protocol delegation guide 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
Your own agent needed Ollama and the model, and you have both. The Tutor adds one piece, the framework that reads its YAML: clone github.com/jhwadman/melch-ai and run npm run syndicate:tutor. The guided setup walks every step, including these, and asks before it touches anything.
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.