Posts

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.

one request · from a config line to your own processor
agent
model: “ollama/qwen3:8b”
one string in the agent’s definition
which provider?
cloud
claude-* · gemini-* · gpt-*
API key · metered per token · prompt leaves your network
local
ollama/*
HTTP to localhost:11434 · weights already in your RAM
unchanged
your prompt blocks, tools, and output schema
nothing above the adapter knows which path ran
The service seam. Everything above it is your agent; everything below it is a detail you can change with one string. What the picture keeps identical is the shape of the request and the answer. The model on each side is a different file, and the words that come back differ with it; the seam moves your agent between models without promising they will behave alike.

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 configuration line decides where the arithmetic runsmodel: ”…“cloud (claude / gpt / gemini)API key → meter → vendor serverprompts leave your networkfrontier reasoning capacityollama/qwen3:8bregistry → localhost:11434no keys · no token chargesyour own RAM or VRAMthe prompt blocks are identical on both paths
The seam, drawn as a fork. What sits above it (identity, doctrines, style, tools, output schema) does not change when you switch which side runs. The drawing shows two destinations; the registry in the repository knows more than two, and the fork is really a list of patterns tried in order. What is exact is that one string picks the branch.

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.