Provider Protocols Reference

A "provider" is a single entry in the providers: list of custos.yaml. Each provider uses a protocol: to determine how CUST/OS communicates with it. This page documents every supported protocol and the fields each one needs.

See the configuration reference for fields and defaults. Tested models lists recorded results and combinations that still need verification.

Protocols at a glance

Protocol Used for URL scheme
ollama LAN Ollama servers http://, https://
openai Anything that speaks the OpenAI chat completions API (llama-cpp-python, koboldcpp, OpenAI, xAI, etc.) and on-device llama.cpp http://, https://, file://
vllm vLLM servers (separate adapter — vLLM's reasoning-content format is not OpenAI-compatible) http://, https://
anthropic Anthropic Claude API https://
litert LiteRT-LM in-process on-device inference file://
vision Vision server (ONNX-based detection) http://, file://
cot Cross-device delegation over the TAK CoT mesh (WIP) cot://

Tasks at a glance

Task Supported protocols
chat ollama, openai, anthropic, litert, cot
embedding ollama, openai
transcription openai (Whisper-compatible API)
tts openai (network TTS endpoints), or no provider (falls back to Android TTS)
vision / detection vision

protocol: ollama

Native Ollama API. Use this when pointing at a LAN Ollama instance.

- name: "ollama-m4"
  task: "chat"
  protocol: "ollama"
  url: "http://192.168.1.50"
  port: 11434
  model: "qwen2.5:7b"
  taskPriority: 2
  tier: "mobile"

Required: name, task, protocol, url, model. Default Ollama port is 11434.

protocol: openai

OpenAI-compatible chat completions API. The most common protocol — use it for OpenAI, xAI, llama-cpp-python, koboldcpp, Oobabooga, and on-device llama.cpp.

Cloud / LAN example

- name: "openai-gpt"
  task: "chat"
  protocol: "openai"
  url: "https://api.openai.com"
  model: "gpt-5"
  taskPriority: 5
  tier: "cloud"
  auth: true

Self-hosted OpenAI-compatible example

- name: "local-openai-compat"
  task: "chat"
  protocol: "openai"
  url: "http://10.0.2.2"
  port: 8000
  model: "Qwen/Qwen2.5-7B-Instruct"
  taskPriority: 2
  tier: "mounted"

protocol: vllm

vLLM servers speak OpenAI-compatible, but they surface reasoning content in a specific shape (reasoning_content field or <think> tags inside content) that the generic adapter does not strip cleanly. Use protocol: vllm when your server is actually vLLM:

- name: "vllm-server"
  task: "chat"
  protocol: "vllm"
  url: "http://10.0.2.2"
  port: 8000
  model: "RedHatAI/Qwen3-8B-quantized.w4a16"
  taskPriority: 2
  tier: "mounted"

Use protocol: openai for every other OpenAI-compatible server.

On-device llama.cpp

For on-device inference, use url: file:// with a runtime: hint. CUST/OS spawns a native llama-server subprocess on the specified port.

- name: "on-device-llm"
  task: "chat"
  protocol: "openai"
  runtime: "llama.cpp"
  url: "file:///sdcard/atak/custos/models/qwen3-4b.gguf"
  port: 8411
  model: "qwen3-4b"
  contextSize: 4096
  threads: 4
  chatTemplatePath: "/sdcard/atak/custos/models/qwen3-tool-calling.jinja"
  requestTimeoutMs: 120000
  taskPriority: 100
  tier: "handheld"

Required for on-device: runtime, url, port, model, chatTemplatePath.

The runtime: accepts llama.cpp, whisper.cpp, or onnxruntime. It is auto-detected from file extension if omitted (.gguf = llama.cpp, .bin for transcription = whisper.cpp, .onnx = onnxruntime).

protocol: anthropic

Anthropic Claude API. Has its own message format, so it uses a dedicated protocol rather than the OpenAI-compatible one.

- name: "anthropic-claude"
  task: "chat"
  protocol: "anthropic"
  url: "https://api.anthropic.com"
  model: "claude-sonnet-4-6"
  taskPriority: 1
  tier: "cloud"
  auth: true

Required: name, task, protocol, url, model, auth: true.

protocol: litert

LiteRT-LM runs in process on the device. It retains the KV cache across reasoning iterations to reduce repeated prompt processing. Gemma 4 E2B-it has been tested with this backend on Samsung S26 Ultra.

- name: "on-device-gemma4"
  task: "chat"
  protocol: "litert"
  url: "file:///sdcard/atak/custos/models/gemma-4-E2B-it.litertlm"
  model: "gemma-4-E2B-it"
  tier: "handheld"
  taskPriority: 1
  contextSize: 16384
  threads: 4
  properties:
    backend: "cpu"

Required: name, task, protocol, url, model.

The backend property accepts:

  • "cpu" — default for initial setup; test speed and output accuracy on the target device.
  • "gpu" — verified numerically stable on Samsung S26 Ultra (Adreno 840) with our custom LiteRT-LM build. Validate on your specific device before relying on it.
  • "npu" — experimental Hexagon / dedicated NPU path. Not verified.

protocol: vision

On-device vision server for object detection (ONNX Runtime).

- name: "on-device-detection"
  task: "detection"
  protocol: "vision"
  runtime: "onnxruntime"
  url: "file:///sdcard/atak/custos/models/yolo11m.onnx"
  port: 8413
  model: "yolo11m"
  threads: 4
  confidence: 0.15
  inputSize: 640
  taskPriority: 1
  tier: "handheld"
  properties:
    labels: "/sdcard/atak/custos/models/labels.txt"
Field Meaning
confidence Detection confidence threshold (0-1)
inputSize Model input dimensions (square)
threads CPU threads for inference
properties Free-form passthrough converted to CLI flags for the native server

protocol: cot — WIP

Status: the transport is wired but has not been vetted end-to-end against a second CUST/OS node. Message framing and response matching may still change. Configure to experiment, not to depend on.

Delegation over the TAK CoT mesh. Packages an inference request as a CoT broadcast and waits for the response from a remote CUST/OS node.

- name: "command-post-llm"
  task: "chat"
  protocol: "cot"
  url: "cot://command-post"
  model: "remote"
  taskPriority: 50
  tier: "command-post"

The url is a label (cot://<hostname>); routing is handled by the TAK mesh. Tools stay local on each side -- only the inference call hops the mesh.


Per-provider override fields

Any of these defaults: values may be overridden per provider:

Override Default source
maxTokens defaults.maxTokens (2048)
requestTimeoutMs defaults.requestTimeoutMs (60000)
healthCheckIntervalMs defaults.healthCheckIntervalMs (5000)
sampleRate defaults.sampleRate (16000)
maxRecordingDurationMs defaults.maxRecordingDurationMs (30000)
minRecordingDurationMs defaults.minRecordingDurationMs (500)

Tiers

Every provider should have a tier: value that reflects its physical and trust environment:

Tier What lives here
handheld Models running on the operator's own device
pack Compute carried by the operator, connected through a wired USB or Ethernet inference link.
mobile A companion compute device the squad carries
mounted A vehicle-mounted compute platform
command-post A back-line workstation reachable over the TAK mesh
cloud An internet-hosted provider

See Tiers and priority for details on how tiers drive lockdown modes, classification, and fallback.

API keys

Cloud providers with auth: true need an API key stored in the encrypted key store. Keys are never read from custos.yaml.

To set, change, or remove a key: open the Status panel from the NavBar, tap the provider's row, and use the Set Key / Change Key / Remove Key buttons in the provider detail dialog. The key is encrypted at rest and only decrypted at request time.

See also