Architecture

Ollama Architecture: How It Actually Works

ollama/ollama MIT 1 diagram
How to read this page

Symvanta parsed this repository into a code graph: every function, class, and method is a node, and every call or import between them is an edge. Everything on this page is computed from that graph at the commit shown above. The terms:

Module (or cluster)
A group of symbols that call each other far more than they call anything else. An algorithm called Louvain community detection finds these groups from the call traffic alone; nobody draws them by hand.
Modularity (the Q number)
A 0-to-1 score of how cleanly those groups separate. Higher means more call traffic stays inside its own group; scores around 0.7 and above read as clean boundaries.
Hub
The most depended-upon symbol inside one module.
Load-bearing symbols
PageRank, the algorithm Google originally used to rank web pages, run over the call graph instead: it surfaces the functions the rest of the codebase leans on hardest.
Arrows and their numbers
How many calls cross from one module into another. A heavier arrow means tighter coupling between those two parts.
Dependency cycle
File A imports B, which imports A again, sometimes through a longer loop. Cycles are not bugs, but a change inside one tends to ripple around the whole loop.
Mutually recursive symbols
Functions that call each other, usually the natural shape of parsers and tree-walking code.

Ollama is a local model runtime with an HTTP server in front of it: it resolves a model reference, loads the weights, schedules a runner, and streams tokens back. Symvanta's graph of the repo at 26936be detects 52 functional modules at modularity Q=0.76, and the largest are the ones that description predicts: chat request handling and prompt templating, model names and manifests, the launcher that manages installed models, and an MLX runner for Apple silicon.

Two things about the shape stand out. The chat path concentrates in a single handler: server.Server.ChatHandler runs from line 2417 to line 2911 of server/routes.go, and GenerateHandler above it is a similar size. And the MLX cluster is almost as large as the chat cluster, 793 symbols against 804, which is what a second inference path for one hardware family costs in a codebase.

Module map

The diagram shows the 10 largest of the 52 detected modules, with edges weighted by how many calls cross between them. Module names come from the packages their members live in; the symbol counts, hubs, and edge weights are what the graph computed.

ollama/ollama module map: the 10 largest of 52 detected modules with call-weighted edges, generated by Symvanta
Module map of ollama/ollama, generated by Symvanta. Link to this diagram Open full size

Where to start reading

These are the most depended-upon symbols by PageRank over the call graph, followed by the HTTP surface registered in server/routes.go. Two entries from the raw ranking are left out below: Set and Error are one-word Go methods that many packages define independently, and the graph groups them by name, so they rank high without pointing anywhere useful.

  • template.Template.Contains
  • mlx.DefaultStream
  • agent.SkillCatalog.Dir
  • mlxthread.Thread.Do
  • mlxthread.Thread.enqueue
  • mlx.Array.Equal
  • dialog.MsgBuilder.Info
  • envconfig.Var
  • model.Name.EqualFold
  • KV
  • POST /api/chat
  • POST /api/generate
  • GET /api/version
  • POST /v1/chat/completions
  • POST /v1/completions
  • POST /v1/embeddings
  • GET /v1/models
  • GET /v1/models/:model
  • POST /v1/responses
  • POST /v1/audio/transcriptions
  • POST /v1/messages

The endpoint list is worth a second look. Alongside its own /api/* surface, Ollama serves an OpenAI-compatible /v1/chat/completions and an Anthropic-compatible /v1/messages, which is why the codebase carries dedicated translation clusters for both.

Key subsystems

Chat rendering and templates

Prompt templating sits with terminal chat rendering (chat.wrapChatText, chat.stripANSI, chat.chatDisplayWidthCut) in the largest cluster on the map, 804 symbols behind the hub template.Template.Contains. The same package builds the prompt and paints the reply.

MLX arrays and devices

Apple silicon runtime: mlx.DefaultStream, mlx.DefaultDevice, the array operations, and the Cocoa bindings. At 793 symbols it is within a rounding error of the chat cluster, and it calls into the MLX parameter and decode cluster 78 times.

API message and tool-call types

The wire types live here, 750 symbols of Message, ToolCall, ToolCallFunction, ThinkValue, and their conversion helpers. Every surface, native or compatibility, funnels through them.

Model launcher

Which models are installed and which one starts: launch.fallbackLaunchModel, launch.launchModelsFromNames, launch.lookupCloudModelLimit, and the environment host resolution around them, 647 symbols in total.

Model names and manifests

Parsing and validating model references (model.ParseName, model.Name.IsFullyQualified, model.isValidPart) and finding their blobs on disk (manifest.BlobsPath). 451 symbols, and all of it runs before a single weight is loaded.

Canonical request flow

A chat request enters at the gin route and stays inside one handler for most of its life. Every step below is a call edge out of server.Server.ChatHandler.

  1. r.POST./api/chat (server/routes.go:1891)
  2. server.Server.ChatHandler
  3. server.parseAndValidateModelRef
  4. server.GetModel
  5. server.Model.Capabilities
  6. server.chatModeForModel
  7. server.chatPrompt
  8. server.filterThinkTags

Health signals

Symvanta detected 2 dependency cycles across 52 modules (modularity Q=0.76). The largest cycle spans 2 files in the components area. 7 sets of mutually recursive symbols were also detected, the largest being mlxrunner (3 symbols).

Both cycles sit in the desktop UI, under app/ui/app/src. The Go server has none.

See your own codebase mapped like this.

Book a demo →

Auto-generated by Symvanta from the public repo ollama/ollama at commit 26936be , licensed MIT .

Machine-readable companion: data.json (module counts, subsystems, load-bearing symbols, health signals).

Get this for your codebase →