OpenAI-compatible · function calling · 100% local

Use Outlier as the engine behind your tools

Outlier exposes a standard /v1/chat/completions API on your own Mac. Point Cursor, LangChain, LiteLLM, Codex, or anything built on the OpenAI SDK at it — same code you already have, but the model runs locally and nothing leaves your machine.

1 · Turn it on

In Outlier: Settings → Advanced → Developer → OpenAI-compatible API. Flip the toggle and copy your endpoint and API key. The endpoint is loopback-only (http://127.0.0.1:8766/v1) — nothing is exposed to your network.

2 · OpenAI SDK — drop-in

from openai import OpenAI

client = OpenAI(
    base_url="http://127.0.0.1:8766/v1",
    api_key="YOUR-OUTLIER-KEY",   # Settings → Developer
)

r = client.chat.completions.create(
    model="outlier-nano",          # outlier-lite / outlier-quick / outlier-compact (Core)
                                   # outlier-plus
                                   # Vision 3.8 answers text here too, but this
                                   # endpoint takes no images — see below.
    messages=[{"role": "user", "content": "Three taglines for a coffee truck"}],
)
print(r.choices[0].message.content)

Streaming, max_tokens, temperature, and finish_reason behave like the reference API.

Images do not go through this endpoint. Sending OpenAI's multimodal form — a content array of {"type": "image_url", ...} parts — returns 400 messages.0.content: Input should be a valid string, because /v1/chat/completions takes text only. Vision 3.8 will answer a text prompt here like any other tier; it just cannot see anything you send it this way. Pictures go to Outlier's own endpoint instead:

POST http://127.0.0.1:8766/chat/vision
Authorization: Bearer YOUR-OUTLIER-KEY

Verified against 1.11.808 rather than assumed, which is why the error text above is quoted rather than described.

3 · Function calling (tools)

r = client.chat.completions.create(
    model="outlier-nano",
    messages=[{"role": "user", "content": "What's the weather in Paris?"}],
    tools=[{
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        },
    }],
)
tc = r.choices[0].message.tool_calls[0]
print(tc.function.name, tc.function.arguments)
# → get_weather {"city": "Paris"}

Run your function, then send the result back as a role:"tool" message — multi-turn tool loops work the way the OpenAI docs describe, including streaming (delta.tool_calls, finish_reason:"tool_calls").

4 · LangChain

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    base_url="http://127.0.0.1:8766/v1",
    api_key="YOUR-OUTLIER-KEY",
    model="outlier-nano",
).bind_tools(my_tools)

msg = llm.invoke("What's the weather in Berlin?")
print(msg.tool_calls)

5 · Cursor / Continue

In the model settings, add a custom OpenAI-compatible model: base URL http://127.0.0.1:8766/v1, your Outlier key, model outlier-compact (the Core tier, the strongest one that fits most Macs) or outlier-nano for speed.

6 · Codex CLI

# ~/.codex/config.toml
model = "outlier-compact"
model_provider = "outlier"

[model_providers.outlier]
name = "Outlier (local)"
base_url = "http://127.0.0.1:8766/v1"
env_key = "OUTLIER_API_KEY"
wire_api = "chat"   # Outlier serves chat completions, not the Responses API
export OUTLIER_API_KEY="YOUR-OUTLIER-KEY"
codex

7 · LiteLLM

import litellm
r = litellm.completion(
    model="openai/outlier-nano",
    api_base="http://127.0.0.1:8766/v1",
    api_key="YOUR-OUTLIER-KEY",
    messages=[{"role": "user", "content": "hi"}],
)
Privacy note: requests to this endpoint are handled entirely on your Mac by the locally-running model. Your prompts, code, and tool results never leave your machine.

8 · What the app does that this endpoint does not

The endpoint runs the same models as the app, and deliberately not the same product around them. If you compare an answer here against the same question typed into Outlier and they differ, this is usually why:

None of this is a limitation of the model; it is the line between an application and an API. It is listed because the difference is invisible until an answer surprises you.

9 · Which parameters actually do something

A drop-in endpoint that accepts a parameter and then ignores it is worse than one that rejects it, because your code carries on believing the constraint applied. Every field below was sent to a running 1.11.808 engine and the reply read back on 1 September 2026, so this is what was observed rather than what the schema permits.

Honoured — the effect was measured, not assumed.

Refused on purpose. n greater than 1 returns 400 and says why: this endpoint returns a single choice. Silently handing back one choice would have been the easier behaviour and the wrong one.

Images do not travel through this endpoint. A message whose content is a list containing an image_url part is refused with an error naming POST /chat/vision, which is where Outlier Vision 3.8 reads pictures. The model list says the same thing in the tier's own description, so a client that reads the catalogue before choosing is not misled.

Accepted, effect not measured here. top_p, seed, presence_penalty, frequency_penalty, logit_bias, logprobs, user, metadata and parallel_tool_calls are all accepted without error. They are listed separately because accepting a field is not the same as acting on it, and only the ones above were checked end to end.

← outlier.host

New models worth running

Open weights ship constantly and most are not worth your disk. When one beats a tier Outlier already has, on hardware you already own, we say so and what it replaces. That is the only reason we email.

Your address and which site you sent it from. No IP, no user agent, no referer. Nothing is sent until you press the button. Privacy.