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:
- Direct token.
Config.Token. - Env-var reference.
Config.Credentials.Envnames an env var; the value is read withos.Getenv. The secret stays out of any config file. - Keychain reference.
Config.Credentials.Keychainis a"service/account"pair resolved through the host-injectedConfig.Credentials.Lookupfunc. With no lookup wired, this step is skipped. - Literal.
Config.Credentials.Key, an inline value (legacy; least preferred). - 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 providerapiconfig 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.
ValidateBaseURLrejectshttp://unlessAllowInsecureBaseURLis set, which is intended forhttptest.Servertargets 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
claudeCLI installed and onPATH. - Authenticated once (
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.
Related¶
- Architecture & the seams: how
chat.Newdispatches to a provider. - Providers: the full capability matrix and per-provider notes.
- Provider-endpoint & credential security: BaseURL validation and credential handling.