Skip to content

title: Choose & configure a provider description: The chat.Config fields, how each provider is activated and credentialed, and the two that need extra setup: openai-compatible and claude-local. tags: [how-to, configuration, providers, credentials]


Choose & configure a provider

This guide covers the chat.Config fields, how each provider is activated and credentialed, and the two providers that need extra setup: openai-compatible (a required BaseURL and Model) and claude-local (a local CLI binary).

The fields that choose a provider

chat.Config carries provider behaviour and is passed inside chat.Settings to chat.New. Only Provider is effectively required, and even that defaults; everything else has a working zero value.

Five fields decide which provider you get and how it authenticates:

Field Type Description
Provider Provider The provider constant. Defaults to ProviderClaude when unset and AI_PROVIDER is not set.
Model string Model name. Falls back to a per-provider default when empty. Required for ProviderOpenAICompatible.
Token string API key. Optional when resolvable from config references or a well-known env var.
Credentials CredentialConfig Credential references (env-var name, keychain ref, literal) supplied by the host. Token wins when both are set.
BaseURL string API endpoint override. Required for ProviderOpenAICompatible. Validated by ValidateBaseURL.

Every other field (sampling, effort, caching, timeouts, the tool loop, the test seams) is in Configuration fields, with what each one defaults to and what happens when the value cannot be applied. Signatures are on pkg.go.dev.

Activate a provider by blank import

Each API provider lives in its own module. Blank-import it once (typically in main) to register it with the core; then reference it by its Provider constant.

Provider constant String Blank import Credential env var
chat.ProviderClaude claude _ "gitlab.com/phpboyscout/go/chat-anthropic" ANTHROPIC_API_KEY (chatanthropic.EnvClaudeKey)
chat.ProviderOpenAI openai _ "gitlab.com/phpboyscout/go/chat-openai" OPENAI_API_KEY (chatopenai.EnvOpenAIKey)
chat.ProviderOpenAICompatible openai-compatible _ "gitlab.com/phpboyscout/go/chat-openai" backend-dependent (Token)
chat.ProviderGemini gemini _ "gitlab.com/phpboyscout/go/chat-gemini" GEMINI_API_KEY (chatgemini.EnvGeminiKey)
chat.ProviderGeminiVertex gemini-vertex _ "gitlab.com/phpboyscout/go/chat-gemini" application default credentials, plus Project and Location
chat.ProviderClaudeLocal claude-local none (ships in the core none) the claude binary is pre-authenticated

The openai and openai-compatible providers are both registered by the single chat-openai import.

Resolve a credential

Every API provider resolves its key through one shared five-step cascade (chat.ResolveAPIKey). The first non-empty source wins; each step is trimmed so a half-configured value cannot mask a fully-configured one below it:

  1. Direct token. Config.Token.
  2. Env-var reference. Config.Credentials.Env names an env var; the value is read with os.Getenv. The secret stays out of any config file.
  3. Keychain reference. Config.Credentials.Keychain is a "service/account" pair resolved through the host-injected Config.Credentials.Lookup func. With no lookup wired, this step is skipped.
  4. Literal. Config.Credentials.Key, an inline value (legacy; least preferred).
  5. Well-known env var. ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY, the ecosystem fallback used by most SDKs and CI platforms.

The simplest path is to export the well-known env var and leave Token and Credentials empty:

import (
    "gitlab.com/phpboyscout/go/chat"
    _ "gitlab.com/phpboyscout/go/chat-anthropic"
)

// ANTHROPIC_API_KEY is set in the environment; nothing else needed.
client, err := chat.New(ctx, chat.Settings{
    Config: chat.Config{Provider: chat.ProviderClaude},
})

A host that keeps secrets in a config file or keychain populates Config.Credentials instead. See credential security.

Using go-tool-base? Its adapter maps the framework's ai.provider, AI_PROVIDER, and provider api config sections onto these fields for you; that adapter lives in go-tool-base, not this module.

OpenAI-compatible endpoints

ProviderOpenAICompatible targets any backend that speaks the OpenAI API: Ollama, Groq, Fireworks AI, Together AI, LM Studio, vLLM, and others. It is registered by the chat-openai import. Both BaseURL and Model are required (there is no default model, because names are backend-specific), and the BaseURL must pass endpoint validation.

import (
    "gitlab.com/phpboyscout/go/chat"
    _ "gitlab.com/phpboyscout/go/chat-openai"
)

// Ollama (local)
ollama, err := chat.New(ctx, chat.Settings{Config: chat.Config{
    Provider: chat.ProviderOpenAICompatible,
    BaseURL:  "http://localhost:11434/v1",
    Model:    "llama3.2",
    Token:    "ollama", // Ollama ignores the token; any non-empty value works

    // A localhost HTTP endpoint is non-HTTPS; permitted only in tests.
    AllowInsecureBaseURL: true,
}})

// Groq (cloud, HTTPS)
groq, err := chat.New(ctx, chat.Settings{Config: chat.Config{
    Provider: chat.ProviderOpenAICompatible,
    BaseURL:  "https://api.groq.com/openai/v1",
    Model:    "llama-3.3-70b-versatile",
    Token:    os.Getenv("GROQ_API_KEY"),
}})

Non-HTTPS endpoints. ValidateBaseURL rejects http:// unless AllowInsecureBaseURL is set, which is intended for httptest.Server targets only. For a plaintext local model, prefer an HTTPS proxy in production; the flag exists so tests can point at a local server, not as a way to disable TLS generally.

Token chunking falls back to the cl100k_base encoding for model names the tokenizer does not recognise, so Ollama and other non-OpenAI model names are handled gracefully.

Claude Local (the claude CLI)

ProviderClaudeLocal routes requests through a locally installed, pre-authenticated claude CLI binary instead of the Anthropic API. It is valuable in secure or air-gapped environments where outbound HTTPS to api.anthropic.com is blocked but the binary is permitted. It ships in the core, with no blank import and no API key required.

Requirements:

  • The claude CLI installed and on PATH.
  • Authenticated once (claude login).
npm install -g @anthropic-ai/claude-code
claude login
import "gitlab.com/phpboyscout/go/chat" // no provider import needed

client, err := chat.New(ctx, chat.Settings{Config: chat.Config{
    Provider:     chat.ProviderClaudeLocal,
    Model:        "claude-sonnet-4-6", // optional; uses claude's default if empty
    SystemPrompt: "You are a helpful assistant.",
}})

Multi-turn continuity is maintained via session IDs captured from the CLI's JSON output and passed back with --resume. Two limitations set claude-local apart: it does not support tool calling (SetTools returns an error; MCP-based tools are planned) and it does not stream. It also reports no reliable token usage. See Providers.