Back to Nanobot

Provider Cookbook

docs/provider-cookbook.md

0.2.215.2 KB
Original Source

Provider Cookbook

This page is for cases where you already know what you want to connect and need a pasteable setup. Each recipe shows what to set, what to run, and what a failure usually means.

If this is your first install and terminal commands are new to you, start with start-without-technical-background.md. If you want the field-by-field explanation, read providers.md and then configuration.md#providers.

Most examples below are snippets to merge into ~/.nanobot/config.json. Keep any existing sections you still need, and replace placeholder keys such as ${OPENROUTER_API_KEY} with environment-variable references or real values only on your own machine.

Recipes are examples, not rankings. Pick the recipe that matches the credential, endpoint, and model ID you already intend to use.

Choose a Recipe

Match the recipe to the credential or endpoint you already have:

What you haveRecipeMust match
A gateway key and model IDs that include a model family path, such as provider/model-nameOpenRouter GatewayAPI key, provider config key, preset provider, and gateway model ID
An OpenAI platform API key and OpenAI model IDOpenAI DirectOPENAI_API_KEY, provider: "openai", and an OpenAI model available to that account
An Anthropic API key and Anthropic model IDAnthropic DirectANTHROPIC_API_KEY, provider: "anthropic", and a non-gateway model ID
An OpenAI-compatible /v1 endpoint that is not a named nanobot providerCustom OpenAI-Compatible ProviderapiBase, optional API key, and the model ID served by that endpoint
Ollama already running locallyOllama Local ModelOllama apiBase, pulled model name, and local server availability
vLLM, LM Studio, or another local OpenAI-compatible servervLLM or LM StudioLocal /v1 base URL, any required key, and served model name
A primary model plus one or more backupsFallback PresetsNamed presets in modelPresets, referenced from agents.defaults.fallbackModels
A working agent and a Langfuse projectLangfuse TracingLangfuse env vars in the same process environment that starts nanobot

How to Use a Recipe

  1. Install nanobot and run nanobot onboard once so ~/.nanobot/config.json exists. Use nanobot onboard --wizard if you prefer prompts over hand-editing JSON.
  2. Put secrets in environment variables when possible.
  3. Merge the recipe snippet into ~/.nanobot/config.json.
  4. Run nanobot status.
  5. Run nanobot agent -m "Hello!".
  6. If the CLI works, then connect WebUI, gateway, or chat apps.

The active model should normally come from agents.defaults.modelPreset, and that name should point to an entry in modelPresets. Direct agents.defaults.provider and agents.defaults.model still work for older configs, but presets are easier to switch and easier to reuse as fallbacks.

Secret Setup

Environment variables keep API keys out of the config file.

Use the variable name shown by the recipe you picked. The commands below use OPENROUTER_API_KEY only as an example; an OpenAI direct recipe uses OPENAI_API_KEY, an Anthropic direct recipe uses ANTHROPIC_API_KEY, and a custom endpoint can use any variable name you reference in config.json.

macOS / Linux

bash
export OPENROUTER_API_KEY="sk-or-v1-..."
nanobot agent -m "Hello!"

Windows PowerShell

powershell
$env:OPENROUTER_API_KEY = "sk-or-v1-..."
nanobot agent -m "Hello!"

Environment variables set this way apply only to the current terminal. For long-running services such as systemd, Docker, LaunchAgent, or a remote shell, set the variables in that service environment before starting nanobot.

Recipe: OpenRouter Gateway

This recipe applies when one API key routes many hosted model families.

json
{
  "providers": {
    "openrouter": {
      "apiKey": "${OPENROUTER_API_KEY}"
    }
  },
  "modelPresets": {
    "primary": {
      "label": "Primary",
      "provider": "openrouter",
      "model": "anthropic/claude-sonnet-4.5",
      "maxTokens": 4096,
      "contextWindowTokens": 65536,
      "temperature": 0.1
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "primary"
    }
  }
}

Verify:

bash
nanobot status
nanobot agent -m "Hello!"

If this fails with 401 or unauthorized, check that OPENROUTER_API_KEY is visible in the same terminal or service that starts nanobot. If it fails with model not found, choose a model ID that OpenRouter lists for your account.

Recipe: OpenAI Direct

This recipe applies when you have an OpenAI API key and want to call OpenAI directly instead of through a gateway.

json
{
  "providers": {
    "openai": {
      "apiKey": "${OPENAI_API_KEY}"
    }
  },
  "modelPresets": {
    "primary": {
      "label": "OpenAI",
      "provider": "openai",
      "model": "gpt-5",
      "maxTokens": 4096,
      "contextWindowTokens": 128000,
      "temperature": 0.1
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "primary"
    }
  }
}

Verify:

bash
OPENAI_API_KEY="sk-..." nanobot agent -m "Hello!"

If your shell cannot use inline environment variables, set OPENAI_API_KEY first and then run nanobot agent -m "Hello!". If the provider rejects apiType, remove apiType unless you are using a documented OpenAI-specific mode.

Recipe: Anthropic Direct

This recipe applies when your key comes from Anthropic and your model name is an Anthropic model ID, not an OpenRouter model path.

json
{
  "providers": {
    "anthropic": {
      "apiKey": "${ANTHROPIC_API_KEY}"
    }
  },
  "modelPresets": {
    "primary": {
      "label": "Anthropic",
      "provider": "anthropic",
      "model": "claude-sonnet-4-5",
      "maxTokens": 4096,
      "contextWindowTokens": 200000,
      "temperature": 0.1
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "primary"
    }
  }
}

Verify:

bash
ANTHROPIC_API_KEY="sk-ant-..." nanobot agent -m "Hello!"

If you copied a model name such as anthropic/claude-sonnet-4.5, that is a gateway-style model path and belongs under provider: "openrouter", not provider: "anthropic".

If you use an Anthropic-compatible proxy, keep the preset provider as anthropic and set providers.anthropic.apiBase:

json
{
  "providers": {
    "anthropic": {
      "apiKey": "${ANTHROPIC_API_KEY}",
      "apiBase": "https://anthropic-proxy.example.com"
    }
  },
  "modelPresets": {
    "primary": {
      "label": "Anthropic proxy",
      "provider": "anthropic",
      "model": "claude-sonnet-4-5",
      "maxTokens": 4096,
      "contextWindowTokens": 200000,
      "temperature": 0.1
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "primary"
    }
  }
}

Do not configure Anthropic-compatible endpoints as arbitrary custom provider names; named custom providers use the OpenAI-compatible request format.

Recipe: Custom OpenAI-Compatible Provider

This recipe applies to an OpenAI-compatible service that is not a named nanobot provider.

json
{
  "providers": {
    "custom": {
      "apiKey": "${CUSTOM_API_KEY}",
      "apiBase": "https://api.example.com/v1"
    }
  },
  "modelPresets": {
    "primary": {
      "label": "Custom",
      "provider": "custom",
      "model": "provider-model-name",
      "maxTokens": 4096,
      "contextWindowTokens": 65536,
      "temperature": 0.1
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "primary"
    }
  }
}

Verify the endpoint before blaming nanobot:

bash
curl -sS https://api.example.com/v1/models
nanobot agent -m "Hello!"

apiBase is the HTTP base URL, not the model name. Include the version path when the service expects it, such as /v1. If the service requires a non-empty key but does not validate it, use a placeholder such as "apiKey": "EMPTY".

For multiple custom endpoints, do not overload the single custom block. Name each endpoint under providers and reference that same name from the preset:

json
{
  "providers": {
    "workProxy": {
      "apiKey": "${WORK_PROXY_API_KEY}",
      "apiBase": "https://proxy.example.com/v1"
    },
    "lab-local": {
      "apiBase": "http://127.0.0.1:8000/v1"
    }
  },
  "modelPresets": {
    "work": {
      "label": "Work proxy",
      "provider": "workProxy",
      "model": "gpt-4o-mini",
      "maxTokens": 4096,
      "contextWindowTokens": 65536,
      "temperature": 0.1
    },
    "lab": {
      "label": "Lab local",
      "provider": "lab-local",
      "model": "served-model-name",
      "maxTokens": 4096,
      "contextWindowTokens": 65536,
      "temperature": 0.1
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "work"
    }
  }
}

These custom names behave like direct OpenAI-compatible providers: apiBase is required, apiKey is optional when the endpoint allows anonymous or placeholder credentials, and apiType should be left unset. They do not support Anthropic-compatible endpoints; use the anthropic provider with apiBase for that case.

Recipe: Ollama Local Model

This recipe applies when Ollama is already installed and the model has been pulled locally.

bash
ollama serve
ollama pull llama3.2
json
{
  "providers": {
    "ollama": {
      "apiBase": "http://localhost:11434/v1"
    }
  },
  "modelPresets": {
    "local": {
      "label": "Local",
      "provider": "ollama",
      "model": "llama3.2",
      "maxTokens": 2048,
      "contextWindowTokens": 32768,
      "temperature": 0.2
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "local"
    }
  }
}

Verify:

bash
curl -sS http://localhost:11434/v1/models
nanobot agent -m "Hello!"

If you see connection refused, Ollama is not running or apiBase points to the wrong port. If the response is very slow, try a smaller local model or lower contextWindowTokens.

Recipe: vLLM or LM Studio

This recipe applies when a local server exposes an OpenAI-compatible /v1 API.

json
{
  "providers": {
    "vllm": {
      "apiBase": "http://127.0.0.1:8000/v1",
      "apiKey": "EMPTY"
    }
  },
  "modelPresets": {
    "local": {
      "label": "Local",
      "provider": "vllm",
      "model": "served-model-name",
      "maxTokens": 4096,
      "contextWindowTokens": 65536,
      "temperature": 0.2
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "local"
    }
  }
}

For LM Studio, use its local base URL and provider name:

json
{
  "providers": {
    "lmStudio": {
      "apiBase": "http://localhost:1234/v1"
    }
  },
  "modelPresets": {
    "local": {
      "label": "LM Studio",
      "provider": "lm_studio",
      "model": "local-model",
      "maxTokens": 2048,
      "contextWindowTokens": 32768
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "local"
    }
  }
}

The config key can be lmStudio or lm_studio, but the preset provider should use the registry name lm_studio.

Recipe: Fallback Presets

This recipe applies when one provider sometimes rate-limits, one model is expensive, or you want a local backup.

json
{
  "modelPresets": {
    "fast": {
      "label": "Fast",
      "provider": "openrouter",
      "model": "anthropic/claude-sonnet-4.5",
      "maxTokens": 4096,
      "contextWindowTokens": 65536,
      "temperature": 0.1
    },
    "deep": {
      "label": "Deep",
      "provider": "anthropic",
      "model": "claude-sonnet-4-5",
      "maxTokens": 4096,
      "contextWindowTokens": 200000,
      "temperature": 0.1
    },
    "local": {
      "label": "Local",
      "provider": "ollama",
      "model": "llama3.2",
      "maxTokens": 2048,
      "contextWindowTokens": 32768,
      "temperature": 0.2
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "fast",
      "fallbackModels": ["deep", "local"]
    }
  }
}

fallbackModels belongs under agents.defaults. String entries are preset names, not raw model names. nanobot tries the active preset first, then the fallback presets in order.

Keep fallback candidates realistic. If the local fallback has a smaller context window, nanobot must build context that fits the smallest window in the active chain.

Recipe: Langfuse Tracing

This recipe applies after the agent works and you want observability for OpenAI-compatible provider calls.

Install the optional package in the same Python environment that runs nanobot:

bash
python -m pip install langfuse

Set the environment variables before starting nanobot:

bash
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_BASE_URL="https://cloud.langfuse.com"
nanobot agent -m "Hello!"

PowerShell:

powershell
$env:LANGFUSE_SECRET_KEY = "sk-lf-..."
$env:LANGFUSE_PUBLIC_KEY = "pk-lf-..."
$env:LANGFUSE_BASE_URL = "https://cloud.langfuse.com"
nanobot agent -m "Hello!"

Langfuse is not a model provider in config.json. It is configured through environment variables and traces supported OpenAI-compatible provider calls. Native providers that do not use that client path may not produce Langfuse OpenAI-wrapper traces.

Recipe: Switch Models at Runtime

Use this after you have more than one preset and are chatting through a supported channel.

json
{
  "modelPresets": {
    "fast": {
      "label": "Fast",
      "provider": "openrouter",
      "model": "anthropic/claude-sonnet-4.5",
      "maxTokens": 4096,
      "contextWindowTokens": 65536
    },
    "local": {
      "label": "Local",
      "provider": "ollama",
      "model": "llama3.2",
      "maxTokens": 2048,
      "contextWindowTokens": 32768
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "fast"
    }
  }
}

In chat:

text
/model
/model local
/model fast

/model switching is runtime-only. It does not rewrite config.json, and an in-progress turn keeps using the model it started with.

Quick Failure Map

SymptomUsually meansFirst check
401, unauthorized, or invalid API keyThe key is missing, wrong, expired, or under the wrong providerPrint or re-set the environment variable in the same terminal or service
model not foundThe model ID does not belong to the selected provider or gatewayCompare modelPresets.<name>.provider and modelPresets.<name>.model
connection refusedLocal server is not running or apiBase has the wrong port/pathRun curl <apiBase>/models
provider not foundProvider name is misspelled or uses the config key instead of registry nameUse names such as openrouter, openai, anthropic, ollama, vllm, lm_studio
Langfuse shows no tracesEnv vars are missing, langfuse is not installed in the active Python environment, or the provider path is nativeRun python -m pip show langfuse and restart nanobot from the same environment

Next References

NeedRead
Field meanings and provider resolutionproviders.md
Full schema and provider tableconfiguration.md#providers
Langfuse detailsconfiguration.md#langfuse-observability
First-run diagnosistroubleshooting.md