Home → Providers

Providers & models

Six providers behind one streaming interface. You keep your keys, you pick the model, and nothing is proxied through anyone else.

ProviderKeyNotes
OpenAIOPENAI_API_KEYIncludes the /v1/responses transport — see below
AnthropicANTHROPIC_API_KEYExplicit cache_control for ~90% input savings
OpenRouterOPENROUTER_API_KEYRoutes any model; sticky session routing keeps the cache warm
Google GeminiGEMINI_API_KEYVia the OpenAI-compatible endpoint
Z.AI (GLM)ZAI_API_KEYImplicit caching; Coding Plan endpoint supported
OllamanoneLocal, free, private

The model name decides the provider, overriding any configured default. aico -m glm-4.6 goes to Z.AI even if your default is OpenRouter — so switching model never means also remembering to switch provider.

Where to put your key

aico provider add writes to ~/.aico/settings.json, which works from any directory. That is the one to use.

A .env file also works, but dotenv reads it from the current working directory. A key in your project's .env will not be found when you run aico anywhere else. This is the single most common setup surprise.

Configuring one

~/.aico/settings.json is the global file; .aico/settings.json in a project merges over it, so a repo can pin its own model without touching your defaults.

{
  "model": "gpt-5.6-terra",
  "providers": {
    "openai": {
      "reasoningEffort": "high",     // none | low | medium | high | xhigh | max
      "maxOutputTokens": 32000     // reasoning shares this budget with output
    },
    "anthropic": {
      "thinking": "adaptive",
      "maxTokens": 32000
    }
  }
}

gpt-5.6 needs the Responses API

The gpt-5.6 family (luna, terra, sol) cannot be driven agentically through Chat Completions at all. It rejects max_tokens, and refuses function tools whenever any reasoning effort is set:

Function tools with reasoning_effort are not supported … use /v1/responses
or set reasoning_effort to 'none'.

Setting none "works" but disables the reasoning you are paying for. aico detects these models and speaks /v1/responses instead, where tools and reasoning coexist. Nothing to configure. Older gpt-5.x models stay on Chat Completions, which is correct for them.

Prompt caching

This is where the event log earns its keep. Because the prompt prefix only ever grows, the cacheable part of a request is stable across turns — so caching actually hits instead of being invalidated by a reshuffled history.

Measured across real coding sessions: 79–91% of input tokens served from cache. /cost reports it per session.

Switch it off with "promptCaching": { "enabled": false } if you are debugging something and want every request built fresh.

Switching mid-session

/model                    # list what is configured
/model claude-opus-5      # switch, keeping the session
/cost                     # what it has spent so far

The session survives the switch, because the transcript is a log rather than a provider-shaped payload. The new model gets the same history, rendered the way it expects.

Spending limits

Checked before every model call, so a breach stops the turn rather than reporting it afterwards. Sub-agent spend counts toward the parent's ceiling.

{
  "safetyLimits": {
    "maxCostPerSession": 5.00,
    "maxTokensPerSession": 2000000
  }
}

Both are off unless set — no default can be guessed honestly.