Local AI API Server: Setup, Real Limits, and the Fix

How Do You Turn a Local LLM Into an API Server?

Run it through Ollama or Jan, both of which expose an OpenAI-compatible endpoint on your own machine — http://localhost:11434/v1 for Ollama, http://localhost:1337/v1 for Jan. Point any tool built for the OpenAI SDK at that URL with any placeholder API key, and it behaves exactly like a cloud provider: same request format, same streaming, same function-calling — except free, private, and offline. That includes coding agents like OpenCode, Continue, or anything else that lets you set a custom base URL.

That’s the whole trick. The harder question — the one most guides skip — is what happens when you actually push a modest GPU past a few exchanges. We ran that experiment on our own hardware. It went well, then it broke, and the way it broke is more informative than if it hadn’t.

We Tried It on a $150 PC

The test bench, priced in the neighborhood of $150 total:

ComponentSpec
MotherboardMSI B150M Mortar
CPUIntel Core i5-6600 (4 cores / 4 threads)
RAM16GB DDR4 2133MHz
GPUSapphire Nitro Radeon RX 580, 8GB GDDR5
StorageKingston 60GB SSD
OSUbuntu 26.04 LTS

We installed Ollama, pulled Gemma 4 E4B, and started with a real business problem — the kind of multi-turn analytical back-and-forth you’d actually use a chat assistant for, not a canned demo prompt. The results were fast and genuinely useful, well within what the RX 580’s memory bandwidth should support on a 4B-class model.

Then, at the seventh message, responses started cutting off mid-sentence.

Why Local Models Cut Off Mid-Response (It’s Not a Bug)

It’s the context window, and the mechanism is documented, not mysterious. Ollama sizes its default context by available VRAM: under 24GiB, the default is 4,096 tokens. An 8GB card — ours included — falls well inside that bucket.

That 4,096-token budget isn’t just for the model’s reply. It has to hold the entire conversation history and the response being generated, together. Every message you send eats into the same fixed pool. By message seven, the accumulated back-and-forth had consumed nearly all of it — leaving too little room for the model to finish a thought before hitting the ceiling. The output didn’t get slower or vaguer. It just ran out of space to keep talking.

This is the same budget our KV cache breakdown covers from the memory side — context length isn’t free, and a fixed default doesn’t know or care what your GPU can actually afford.

The Fix: Bake a Larger Context Into the Model

Ollama’s local endpoint doesn’t let you change context size per-request, so the reliable fix is building a variant with a larger context baked in. On the same machine:

nano Modelfile
FROM gemma4:e4b
PARAMETER num_ctx 16384
ollama create gemma4-16k -f Modelfile

16,384 tokens is a reasonable ceiling for an 8GB card — enough headroom for real conversations without forcing layers out to system RAM, which is its own performance cliff (Ollama will offload to CPU RAM when VRAM runs out, and generation speed drops hard when it does). If your responses start crawling, the fix is the same command with a smaller number — try 8192 to force everything back onto the GPU.

Connecting a Coding Agent to Your Local Model

ollama google gemma 4 context

With gemma4-16k built, we installed OpenCode, an open-source terminal coding agent, and pointed it at the local Ollama endpoint:

curl -fsSL https://opencode.ai/install | bash
mkdir -p ~/.config/opencode
nano ~/.config/opencode/opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama",
      "options": {
        "baseURL": "http://localhost:11434/v1"
      },
      "models": {
        "gemma4-16k": { "name": "gemma4-16k" }
      }
    }
  }
}

This matches Ollama’s own official OpenCode integration guide exactly, and it generalizes: any tool that accepts a custom OpenAI-compatible base URL — not just OpenCode — connects the same way. Restart the tool after editing the config; changes aren’t picked up live.

In the OpenCode interface, press Ctrl+P and select your local model. 

ollama gemma 4 E4B 16K

Where the Local Setup Broke Down

The task was deliberately small: a Python CLI utility called siteguard that checks a list of domains’ HTTP status and SSL certificate expiration. The kind of thing that should take a competent assistant a couple of minutes.

It started reasonably. The agent hit a pip install failure from Ubuntu’s externally-managed-environment restriction, correctly diagnosed it, and built a virtual environment to work around it — real, working troubleshooting, no complaints there.

Then the context bill came due. As error traces and correction attempts piled up inside the 16k window, the model’s grip on the task visibly slipped — but it wasn’t dishonest about it. Unable to get real SSL certificate parsing working, it said so directly and proposed dropping full certificate verification for an HTTP-only check instead; the code that followed matched that admission exactly — a hardcoded placeholder date and an explicit “SSL Check Skipped” message, not a hidden fake. Shortly after, it asked for help installing the requests and cryptography Python packages by hand. The manual assist didn’t turn things around — two messages later, it stopped responding entirely: no more edits, no more replies, just silence.

Checking the file afterward — by hand, in nano, without editing anything — the damage was clear: a genuine IndentationError on line 53, sitting on top of the placeholder SSL logic. The local model hadn’t lied. It had run out of room to finish a job it had already told us, honestly, that it couldn’t complete.

gemma 4 local api opencode

The Cloud Fix: DeepSeek V4 Flash

Rather than trying to hand-fix it, we swapped OpenCode’s backend to DeepSeek V4 Flash — selected through OpenCode’s default provider option, no custom API key configured — and asked it to pick up the same task.

It didn’t start from a blank file, and it didn’t try to patch the IndentationError in place either. It kept the roughly three sections of the existing code that were still sound, rewrote the rest — including the SSL logic the local model had given up on — and ran it. By our own watch, the passing test completed in under ten seconds:

--- Scan Results ---
Domain               HTTP Status   SSL Expiration
--------------------------------------------------------------------------------
vramcalculator.com   200           Expires: 2026-XX-XX 13:58:49 (OK)
google.com            200           Expires: 2026-09-21 08:37:24 (OK)

That’s the honest shape of the result: not a faster version of the same fix, a more decisive one. Where the local model spent its last useful turns asking for help and then ran out of room to finish, DeepSeek triaged the file in a single pass — keep what works, replace what doesn’t — the kind of judgment call a model already most of the way through a 16k local context window doesn’t have headroom left to make.

What Are the Advantages of an On-Device AI API?

Three that held up in this test, and one that didn’t:

  • Privacy. Nothing about the business problem we asked it to analyze, or the code it wrote, left the machine. For anything sensitive, that’s not a minor convenience.
  • No metering. Cloud aggregators like OpenRouter charge a percentage on credit purchases plus per-request fees once free usage caps are exceeded. A local server has no equivalent bill — the cost is the electricity and the hardware you already own.
  • Works offline. No connection required, no vendor rate limit, no outage risk.
  • Doesn’t scale with task complexity — this is the limit we hit. A local API server is a real, capable backend for chat, short scripting, and single-turn or lightly-multi-turn work. It is not, on 8–16GB-class hardware, a drop-in replacement for an autonomous coding loop that needs to track sprawling error histories and multi-file state. That ceiling is architectural, not a configuration mistake.

Comparing Local AI API Servers

 OllamaJanllama.cpp server
Endpointlocalhost:11434/v1localhost:1337/v1Your chosen host:port
InterfaceCLI-first, runs as a background serviceGUI-first, OpenAI-compatible server toggled in SettingsCLI, closest to the metal
Default contextVRAM-tiered (4K under 24GB, 32K to 48GB, 256K above)Set per-model in the UISet explicitly via -c
Model managementollama pull, Modelfile variantsBuilt-in model browserManual GGUF download
Best forScriptable setups, exactly what we used hereUsers who want a GUI and don’t want to touch a terminalMaximum control — see our performance flags guide for -ngl, KV cache quantization, and speculative decoding

All three solve “how do I integrate AI into an application without cloud access” the same way: they speak the OpenAI API dialect on localhost, so your application code doesn’t know or care that it isn’t talking to a cloud vendor.

How Much Context Can Your GPU Actually Afford?

Don’t guess at a num_ctx value the way we initially had to. Gemma 4 uses hybrid sliding-window attention — most of its layers cache only a short window rather than the full conversation — which is exactly the kind of detail a generic default can’t account for. Check what your GPU can run — the RX 580 8GB from this test is in the catalog — or run your exact model and context length through the full calculator to see the real KV cache cost before you pick a number.

FAQ

What are the advantages of using an on-device AI API?

Privacy (nothing leaves your machine), no per-token metering the way cloud aggregators charge, and offline availability. The trade-off is capacity: modest local hardware handles chat and light scripting well but hits a real ceiling on long, multi-turn autonomous tasks.

How do I compare solutions for running large language models locally?

Ollama, Jan, and llama.cpp server all expose an OpenAI-compatible local endpoint, so the practical differences are interface (CLI vs GUI) and default context handling. Ollama sizes its default context by available VRAM — under 24GB, that’s 4,096 tokens — while Jan and llama.cpp server require the context to be set explicitly.

How do I integrate AI capabilities into an application without cloud access?

Run a local server (Ollama or Jan) and point your application at its OpenAI-compatible endpoint — localhost:11434/v1 for Ollama, localhost:1337/v1 for Jan — using the OpenAI SDK with any placeholder API key. This works for custom applications and for existing tools like coding agents that support a custom base URL.

How do I set up Jan as a local AI API server?

Install Jan, enable the local server in Settings, and it serves an OpenAI-compatible endpoint at localhost:1337/v1 by default. Point any OpenAI SDK-compatible client at that URL to use your local models through the same interface a cloud API would expect.

Why does my local model cut off mid-response after several messages?

You’ve likely hit the context window limit. Ollama defaults to 4,096 tokens on GPUs under 24GB VRAM, and that budget covers the entire conversation plus the response being generated. As history accumulates, less room is left to finish a reply. Raise it with a custom Modelfile (PARAMETER num_ctx 16384) sized to what your VRAM can actually hold.

Is a local AI API server a real alternative to OpenRouter?

For privacy-sensitive or offline use cases, yes — same OpenAI-compatible interface, no per-request fees. For complex, long-running agentic tasks, cloud models still have the edge on hardware in the 8–16GB range, where local context ceilings become the limiting factor.