Skip to content

Engines: the compatibility contract

GOAT is a streaming client for compatible model engines. It does not run inference in-process. This reference describes Kid’s implemented wire contract; a preset or model name does not establish that every feature works with every server version. Use Connect an engine for setup.

What GOAT calls

EndpointUsed forRequired
GET /v1/modelsModel list, health probe, auth detection (401/403 ⇒ key prompt)Yes
GET /v1/models/{model-id}Explicit model metadata on generic, oMLX, vMLX, and Custom profilesNo; unsupported falls back to generic chat
GET /api/v1/modelsLM Studio context and capability metadataNo; LM Studio preset only
POST /api/show, GET /api/psOllama capability and effective-context metadataNo; Ollama preset only
GET /props?model=...llama.cpp template, modality, and context metadataNo; llama.cpp preset only
POST /v1/chat/completions (stream: true, SSE)Everything elseYes

Discovery always probes the saved endpoint, then only conventional ports for that preset: :8000/:8001 for oMLX or vMLX, :11434 for Ollama, :1234 for LM Studio, and :8080 for llama.cpp. Custom discovery stays on the generic adapter. Selected-model metadata calls stay on the active endpoint's origin. They contain a catalog model ID and no conversation data. Cross-origin redirects are rejected. No other inference host is contacted (see the connection-policy reference for app-wide boundaries).

Engines (Settings → Engine)

Engines are a managed list, like MCP Servers (ADR-0021): add several, switch which one is active, edit or remove any, all saved in hand-editable ~/.goat/config/engines.json. Add / Edit is seeded from the presets below (plus Custom… for anything else) and offers Test before you commit. A preset just fills the root URL (the client appends /v1/...) and picks the right model-management affordance. It is not a second transport; every engine below speaks the one dialect. One engine is active at a time (you generate from one model).

PresetRoot URLManage models
oMLX (recommended)http://127.0.0.1:8000Opens oMLX.app
vMLXhttp://127.0.0.1:8000Opens vMLX.app
Ollamahttp://127.0.0.1:11434ollama pull <model> (copyable)
LM Studiohttp://127.0.0.1:1234Opens LM Studio.app
llama.cpp serverhttp://127.0.0.1:8080llama-server -m <model.gguf> --port 8080
Custom…you type it-

Choosing a preset fills the URL and re-probes; you can still edit the port by hand. Ports are conventional defaults. Change the URL if your server listens elsewhere.

Feature matrix

Optional metadata can fall back to generic chat behavior; required endpoint or protocol failures still surface as errors. Normalization happens in one place (StreamAssembler, ADR-0016).

FeatureHow GOAT consumes itWithout it
StreamingSSE data: chunks, [DONE] terminatorRequired
Thinking<think>...</think> inline tags, reasoning_content, reasoning, or thinking deltas, and supported typed content parts, all normalized. An explicit local-Qwen engine profile also replays prior reasoning in its native field.No thinking disclosure
Effort dialEvery model gets temperature and budget-clamped max-token presets. A metadata handshake can add reasoning_effort only when the engine explicitly proves the field and allowed valueGeneric presets only
Tool callsOpenAI tool_calls deltas, fragment reassembly by index; results sent as role: "tool" turnsNo tools in that chat
VisionUser-selected images encoded as content-array image_url parts with data:image/png payloads; model-name hints never block themThe selected model or server returns its own unsupported-input error
Honest statsstream_options: {"include_usage": true} is requested; usage on the final chunk gives exact token counts. oMLX generation timing and llama.cpp timings are preferred when present.The client measures from the first real output to completion. Estimated speed or chunk-count tokens are marked ~ in the UI.
Context meterThe deterministic request plan feeds the preflight meter; complete server usage replaces the used-token estimate after generation. context_length / max_context_length / max_model_len supplies the windowConservative 8,192-token fallback. Exact usage and estimated window are marked independently

Model families

If a model prints Qwen tool-call markup as text instead of returning structured calls, GOAT detects the malformed attempt and requests one corrected response. It never executes the printed markup. A corrected structured call still requires the usual permission checks; repeated malformed output stops with a parser/template error. This does not retry tool execution failures or timeouts. See ADR-0065.

Model support follows the endpoint contract. Compatible models use the same generic request path when the selected engine exposes them through the endpoints above. A model family name alone does not establish compatibility.

Dedicated coder variants are the primary workflow. Devstral, Qwen Coder, DeepSeek Coder, Codestral, Code Llama, StarCoder, Granite Code, CodeGemma, OpenCoder, Kimi Dev, and similarly named dedicated variants lead the picker. If a saved default is missing, GOAT chooses a coder variant before the server's first general model. This ordering hint never changes the request body by itself. General Phi, GLM, Kimi, Llama, Gemma, Mistral, and other models remain fully selectable.

Vision-name recognition powers only the model label and a gentle composer warning. It never drops an attached image. User-selected images are always encoded on the generic content-array path, including for unknown or newly released multimodal models.

The Effort dial always works at that generic layer:

EffortTemperatureRequested output ceiling before context clamp
Graze0.71,024
Trot0.72,048
Climb0.64,096
Summit0.68,192

Native controls are capability-gated additions. Startup, engine changes, and model changes show a short checking state while GOAT reads fresh bounded metadata for the selected model. The hard wall-clock deadline is two seconds; unsupported, oversized, malformed, or absent metadata falls back to the generic path and does not make the engine unhealthy. These calls use an isolated non-caching session with no cookie or shared credential state. GOAT never sends a synthetic completion to test a capability.

Capabilities are supported, unsupported, or unknown. Unknown preserves the generic request. Generic capability arrays provide positive evidence only; an omitted member is not a rejection. Explicitly unsupported tool-template metadata omits MCP schemas. Vision metadata improves the hint but does not strip attachments. reasoning_effort is emitted only when an explicit supported_parameters declaration or a documented preset adapter proves it and reasoning support is unambiguous. The Qwen name-derived /think and /no_think controls have been removed.

For a local server using Qwen's chat template, choose Qwen local chat template in that engine's editor. It is an explicit engine contract, never a model-name guess: GOAT sends chat_template_kwargs.enable_thinking and preserve_thinking, maps Graze/Trot/Climb/Summit to off/low/medium/xhigh, uses Qwen's recommended thinking temperature, and replays each prior assistant reasoning trace in reasoning_content. Use it only with a server that documents those fields; generic engines remain on the portable path.

LM Studio's native model list reports reasoning availability and options for its native chat API, but that alone does not prove the OpenAI Chat Completions field, so GOAT records the hint without sending a native control. Ollama's documented OpenAI compatibility plus a model's thinking capability enables none, low, medium, high, or max. llama.cpp enables none, low, medium, or high only when supports_reasoning_effort is true. Explicit generic metadata may advertise a different allowed set, which GOAT clamps to before encoding. Graze and Summit choose the advertised extremes.

GOAT stores normalized reasoning locally for transcript disclosure. Generic engines never receive it again. The explicit local-Qwen profile is the narrow exception: it returns a prior assistant trace through reasoning_content, rather than concatenating it into visible message content. Ordinary chat and OpenAI-style tool calls remain available.

Compatibility evidence

ServerStatus
oMLXLocal development has exercised authentication and discovery. Versioned release qualification for chat, tools, vision and reasoning remains separate.
vMLXEarlier development exercised its wire format; requalify the selected version for a release.
Ollama · LM Studio · llama.cpp server · vLLM · mlx-lmPreset-provided (Ollama/LM Studio/llama.cpp) or same-dialect: expected compatible, unverified; versioned compatibility reports and PRs welcome

Remote engines

Configured HTTP endpoints can be on this Mac, a local network or the internet, subject to JUDAS policy. A remote endpoint receives the context submitted for its work. Local servers can also make independent outbound connections. Do not treat generic API compatibility as a local-only network restriction; see Privacy and Connection policy.