---
title: 'Run on Ollama'
description: 'Point a workspace at Ollama or another OpenAI-compatible gateway on your own hardware: the endpoint, the model id, a packaged box, and the errors you meet on the way.'
position: 8
---
# Run on Ollama
> Any OpenAI-compatible gateway can replace OpenRouter as your **model
> provider**, the endpoint the box sends every model call to. This page uses
> Ollama as the example. LM Studio, LiteLLM and vLLM take the same steps with
> their own address. Two things must agree: the box must reach the gateway, and
> every model id your project names must be one the gateway serves.
## Configure the provider
### In Studio
Open **Settings › Model provider** and pick the **Ollama** preset. It fills the
base URL with `http://localhost:11434/v1`. Keep the `/v1` at the end, because
that is the path Ollama serves its OpenAI-compatible API on. Leave **API key**
empty. Ollama answers without one.
Click **Test connection**, then **Save**. The box runs the test, not your
browser. It calls `/models` from where your agents run, so a green
result means your agents can reach the gateway too. A save applies to the
running box at once.
`localhost` is correct for `stackbone dev`, which runs your code on your own
machine. A box in a container needs another address, see
[Reach the gateway from the container](#reach-the-gateway-from-the-container).
### From the environment
The base URL alone is enough. Export it before you start `stackbone dev`:
```sh
export MODEL_PROVIDER_BASE_URL=http://localhost:11434/v1
stackbone dev
```
On a box built with [`stackbone package`](/docs/cli/reference/package), add the
same line to the deploy folder's `.env`. The compose file passes that whole
file to the agent container. Recreate the container to apply it:
```sh
docker compose up -d --force-recreate agent
```
A value the box exports outranks the one saved in Studio. The
[Gateway](/docs/home/features/gateway) page explains how the screen shows that.
## Name a model the gateway serves
A new project's agent names `openai/gpt-4o-mini`:
```ts
export default defineDeepAgent({
name: 'support',
model: 'openai/gpt-4o-mini',
tools: [addNumbers],
});
```
That is an OpenRouter id. Ollama serves no model of that name, so the first
turn fails with `400 invalid model ID`. Pull a model and write its Ollama tag
instead:
```sh
ollama pull qwen3:4b
```
```ts
export default defineDeepAgent({
name: 'support',
model: 'qwen3:4b',
tools: [addNumbers],
});
```
The **Models** tab of the Model provider screen lists every id the gateway
serves. Pick a model that supports tool calls, because every deep agent runs a
tool loop.
You can also leave the code alone and pick the model in Studio. Open the agent
in the catalogue and choose a model on the `model` row of its **Models** block.
A pick outranks the `model` in the code, and the agent rebuilds so the next
turn uses it. On a packaged box that saves a rebuild of the image. The full
order is in [`stackbone.models`](/docs/sdk/platform/models#the-resolution-order).
Other ids in your project need the same check: a `model` you pass to
[`stackbone.ai`](/docs/sdk/platform/ai), and the embedding `model` you pass to
[`stackbone.rag`](/docs/sdk/data/rag). RAG stores 1536-dimension vectors, so
its embedding model must return 1536 dimensions. Most Ollama embedding models
return fewer (`nomic-embed-text` returns 768), and ingest fails with them.
## Ship a change to a packaged box
The image contains your compiled workspace. A change to `index.ts` reaches the
box only after you package again, into the same folder, and rebuild:
```sh
stackbone package # the same flags as the first time
cd dist/deploy
docker compose build --pull
docker compose up -d
```
`stackbone package` keeps the `.env` already in the folder, so the box keeps
its secrets, and replaces the `workspace/` folder whole. Update the CLI before
you package again: an older one writes a new `.env` with new secrets, and a box
with a new `STACKBONE_SECRET_KEY` cannot decrypt the secrets it already stored.
`--pull` refreshes the runtime base image,
`ghcr.io/stackbone/stackbone-workspace-runtime:node24-base`. Without it Docker
reuses the copy it cached on your first build, and runtime fixes never reach
your box. With plain Docker, use `docker build --pull -t .`.
An `--offline` folder has no build step: `stackbone package --offline` builds
the image on your machine. Run `docker pull` on the base image above before you
package, then follow the update steps in the folder's `README.md`.
## Reach the gateway from the container
Inside the box container, `localhost` is the container itself. Use
`http://host.docker.internal:11434/v1` when Ollama runs on the Docker host, or
`http://ollama:11434/v1` when Ollama is a service named `ollama` on the same
Compose network.
## Troubleshooting
| Error | Cause | Fix |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `no model provider is configured (MODEL_PROVIDER_API_KEY is not set)` | The box runs an older runtime image, which still asks for a key. | Rebuild with `--pull` (see [above](#ship-a-change-to-a-packaged-box)). Or save any placeholder key, such as `ollama`, on the Model provider screen. Ollama ignores it. |
| `400 invalid model ID`, or `model "…" not found` | The model id in your code, or the one picked in Studio, is not a model the gateway has. | Name an Ollama tag, or pick one in Studio. See [Name a model the gateway serves](#name-a-model-the-gateway-serves). |
| `openrouter_key_missing` from a `stackbone.ai` call in a workflow step | A workflow carries the `@stackbone/sdk` your project had installed when you packaged it. An older SDK still asks for a key. | Update `@stackbone/sdk` in your project, then package and rebuild. Or save a placeholder key, as above. |
| `The model provider could not be reached`, or **Test connection** fails | The base URL does not resolve from inside the box. | Use an address the container can reach. See [Reach the gateway from the container](#reach-the-gateway-from-the-container). |
## What's next
- [Which models can I use?](/docs/faqs/general/supported-models): what a
provider resolves, and what changes when you swap one.
- [Gateway](/docs/home/features/gateway): every caller that uses the model
provider, and the models the platform tools use.
- [`stackbone package`](/docs/cli/reference/package): what the deploy folder
holds and what you set on the container.