Documentation
¶
Overview ¶
Package config provides configuration management for the application.
Index ¶
- Constants
- Variables
- func CheckSecretDestinations(ctx context.Context, entity, id string, destinations []SecretDestination, ...) error
- func DefaultMediaPath() string
- func DefaultPIDFilePath() string
- func DeriveMCPServerSlug(name string) string
- func HasSecretReference(value string) bool
- func HasUnresolvedPlaceholder(value string) bool
- func IsLocalModelListSource(location string) bool
- func JoinBasePath(basePath, urlPath string) string
- func LoadFailoverPolicy(cfg *FailoverConfig) error
- func MCPServerEnabled(server MCPServerConfig) bool
- func NormalizeAllowedOrigin(origin string) (string, error)
- func NormalizeBasePath(value string) string
- func NormalizeBreakerScope(scope string) string
- func NormalizeHeaderName(value, fallback string) (string, error)
- func NormalizeMCPVirtualServer(virtual *MCPVirtualServerConfig) error
- func OnlySecretReferences(value string) bool
- func OriginHost(normalizedOrigin string) string
- func ParseBodySizeLimitBytes(s string) (int64, error)
- func ParseResilienceStatuses(entries, defaults []string) (map[int]bool, error)
- func ProviderModelIDs(models []RawProviderModel) []string
- func ProviderModelMetadataOverrides(models []RawProviderModel) map[string]*core.ModelMetadata
- func ResolveClientIPPolicy(cfg *ServerConfig) error
- func ResolveMediaConfig(cfg *MediaConfig) error
- func ResolveMetricsEndpoint(endpoint string) string
- func ResolveMetricsEndpointWithPprof(endpoint string, pprofEnabled bool) string
- func RestrictSecretReferences(ctx context.Context) context.Context
- func SecretFieldFromContext(ctx context.Context) (string, bool)
- func SemanticCacheActive(sem *SemanticCacheConfig) bool
- func SimpleCacheEnabled(s *SimpleCacheConfig) bool
- func ValidateBodySizeLimit(s string) error
- func ValidateCacheConfig(c *CacheConfig) error
- func ValidateMCPServerConfig(server *MCPServerConfig) error
- func ValidateMCPServerName(name string) error
- func ValidateMCPServerSlug(slug string) error
- func ValidateMCPVirtualServerName(name string) error
- func ValidateResilience(r ResilienceConfig) error
- func ValidateServerTLS(server ServerConfig) error
- func WithKeptSecrets(ctx context.Context, values ...string) context.Context
- type AdminConfig
- type BudgetLabelConfig
- type BudgetLimitConfig
- type BudgetProviderConfig
- type BudgetUserPathConfig
- type BudgetsConfig
- type CacheConfig
- type CircuitBreakerConfig
- type ClientIPPolicy
- type Config
- type ConfiguredProviderModelsMode
- type EmbedderConfig
- type FailoverConfig
- type FailoverErrorPhrase
- type FailoverMode
- type GuardrailRuleConfig
- type GuardrailsConfig
- type HTTPConfig
- type HTTPTLSConfig
- type ImageBodyScope
- type KeyWrapper
- type LLMBasedAlteringSettings
- type LoadResult
- func (r *LoadResult) DecodeExtension(name string, target any) (bool, error)
- func (r *LoadResult) KeyWrapper() KeyWrapper
- func (r *LoadResult) PreviousKeyWrappers() []KeyWrapper
- func (r *LoadResult) ResolveSecrets(ctx context.Context) error
- func (r *LoadResult) SetKeyWrapper(w KeyWrapper, previous ...KeyWrapper)
- type LocalCacheConfig
- type LogConfig
- type MCPConfig
- type MCPServerConfig
- type MCPVirtualServerConfig
- type MediaConfig
- type MediaStorageConfig
- type MetricsConfig
- type ModelCacheConfig
- type ModelFilter
- type ModelListConfig
- type ModelsConfig
- type MongoDBStorageConfig
- type OpenTelemetryConfig
- type PGVectorConfig
- type PineconeConfig
- type PluginFileConfig
- type PluginsConfig
- type PostgreSQLStorageConfig
- type PricingConfig
- type QdrantConfig
- type RateLimitModelConfig
- type RateLimitProviderConfig
- type RateLimitRuleConfig
- type RateLimitUserPathConfig
- type RateLimitsConfig
- type RawCircuitBreakerConfig
- type RawProviderConfig
- type RawProviderModel
- type RawResilienceConfig
- type RawRetryConfig
- type RedisModelConfig
- type RedisResponseConfig
- type ResilienceConfig
- type ResolvedEntity
- type ResponseCacheConfig
- type RetryConfig
- type SQLiteStorageConfig
- type SecretDestination
- type SecretError
- type SecretKey
- type SecretNotifier
- type SecretRecheck
- type SecretResolver
- type SecretResolverFunc
- type SecretWriter
- type Secrets
- func (s *Secrets) Changes() <-chan struct{}
- func (s *Secrets) EntityOwnsAny(entity string, fields []string) bool
- func (s *Secrets) ForgetEntity(entity string)
- func (s *Secrets) HasReference(value string) bool
- func (s *Secrets) NotifyChanged()
- func (s *Secrets) Recheck(ctx context.Context) (*SecretRecheck, error)
- func (s *Secrets) Register(scheme string, r SecretResolver) error
- func (s *Secrets) ReleaseSecrets(ctx context.Context, previous, current []string) error
- func (s *Secrets) Resolve(ctx context.Context, value string) (string, error)
- func (s *Secrets) ResolveEntity(ctx context.Context, entity string, fields map[string]string) (*ResolvedEntity, error)
- func (s *Secrets) ResolveFields(ctx context.Context, path string, target any) error
- func (s *Secrets) SetNotifier(n *SecretNotifier)
- func (s *Secrets) SetWriter(w SecretWriter)
- func (s *Secrets) StoreSecret(ctx context.Context, key SecretKey, value string, held []string) (string, error)
- type SemanticCacheConfig
- type ServerConfig
- type SessionConfig
- type SessionHeaderConfig
- type SimpleCacheConfig
- type StorageConfig
- type SystemPromptSettings
- type TaggingConfig
- type TaggingHeaderConfig
- type UsageConfig
- type UserConfig
- type VectorStoreConfig
- type VersionCheckConfig
- type VirtualModelConfig
- type VirtualModelTargetConfig
- type WeaviateConfig
- type WorkflowsConfig
- type WorkloadIdentityConfig
Constants ¶
const ( MCPTransportHTTP = "http" MCPTransportSSE = "sse" MCPTransportStdio = "stdio" )
MCP transport names accepted in MCPServerConfig.Transport.
const ( MCPToolDiscoveryOff = "off" MCPToolDiscoverySearch = "search" )
MCP tool discovery modes accepted in MCPConfig.ToolDiscovery.
const ( MediaStorageFilesystem = "filesystem" MediaStorageMemory = "memory" )
const ( DefaultBodySizeLimit int64 = 10 * 1024 * 1024 // 10MB MinBodySizeLimit int64 = 1 * 1024 // 1KB MaxBodySizeLimit int64 = 100 * 1024 * 1024 // 100MB )
Body size limit constants
const ClientIPHeaderForwardedFor = "X-Forwarded-For"
ClientIPHeaderForwardedFor is the default header GoModel reads the client address from. It carries a chain of hops rather than a single address, so it is the only header resolved by walking the chain.
const DefaultMCPToolTimeout = 30 * time.Second
DefaultMCPToolTimeout bounds a single upstream tools/call when the server declares no timeout of its own.
const DefaultStreamStallTimeoutSeconds = 60
DefaultStreamStallTimeoutSeconds is the default ServerConfig.StreamStallTimeout. It matches the send timeout most reverse proxies apply between two successive writes to a client.
const DefaultTaggingDelimiter = ","
DefaultTaggingDelimiter separates multiple labels inside one header value.
const DefaultVersionCheckURL = versioncheck.DefaultURL
DefaultVersionCheckURL is the public release manifest served by the GoModel website. "/core.txt" or "/pro.txt" is appended per distribution.
const LegacyPIDFilePath = "data/gomodel.pid"
LegacyPIDFilePath is the pid file location used next to a project-local ./data directory, matching where the SQLite database lands in the same setup.
const TrustAnyOrigin = "*"
TrustAnyOrigin is the mcp.allowed_origins entry that trusts every browser origin. It exists for deployments that enforce their own origin checks in front of the gateway, and disables the gateway's DNS-rebinding defense.
Variables ¶
var DefaultFailoverRetryErrors = []string{
"model not found",
"model does not exist",
"model unsupported",
"model unavailable",
"model not available",
"model deprecated",
"model retired",
"model disabled",
"upstream failed",
"upstream error",
"upstream unavailable",
"upstream timed out",
"upstream timeout",
"404 unsupported",
"404 unavailable",
"404 not available",
"404 deprecated",
"404 retired",
"404 disabled",
}
DefaultFailoverRetryErrors is the failover.retry_on_errors default. The phrases cover a model that is gone or refused whatever status the provider chose, an aggregator provider relaying a failure of its own upstream behind a 4xx, and retired-model 404s that avoid the word "model". Plain endpoint 404s and validation errors match none of them.
var DefaultFailoverRetryStatuses = []string{"429", "5xx"}
DefaultFailoverRetryStatuses is the failover.retry_on_statuses default: rate limits and every server-side failure.
var ErrSecretDestinationRestricted = errors.New("only the master key can change where an entity sends a secret it already holds; supply the secret again to repoint it")
ErrSecretDestinationRestricted reports a save, in a context from RestrictSecretReferences, that changes where an entity sends a secret the caller did not supply: one it holds as a reference, or one kept from the stored row behind a redaction mask.
var ErrSecretNotHeld = errors.New("refers to a stored secret this entity no longer holds; reload it and save again")
ErrSecretNotHeld reports a writer-owned reference saved to an entity whose stored row does not hold it. It was read from a row that has since been replaced or deleted, or it belongs to another entity: either way its secret may already be deleted, or be deleted with that other entity.
var ErrSecretReferenceRestricted = errors.New("only the master key can add or change a secret reference")
ErrSecretReferenceRestricted reports a secret reference saved, in a context from RestrictSecretReferences, to an entity that does not already hold it.
var ErrUnknownSecretScheme = errors.New("unknown secret scheme")
ErrUnknownSecretScheme reports a reference whose scheme no resolver is registered for.
Functions ¶
func CheckSecretDestinations ¶ added in v0.1.101
func CheckSecretDestinations(ctx context.Context, entity, id string, destinations []SecretDestination, values []string) error
CheckSecretDestinations returns, in a context from RestrictSecretReferences, a *SecretError wrapping ErrSecretDestinationRestricted naming the first destination that changes while the entity keeps a secret the caller cannot read: values, the entity's secret values as saved, hold a secret reference or a value the context marks as kept (WithKeptSecrets). Repointing such an entity at another host sends it the secret, which reads the reference, or the masked literal, as plainly as fetching it would. A secret the caller typed in is its own, so a save that supplies every secret afresh may repoint. Callers pass no destinations for a new entity: StoreSecret already refuses its references, and it has no stored secrets to keep.
func DefaultMediaPath ¶ added in v0.1.96
func DefaultMediaPath() string
DefaultMediaPath is where media files go when no path is configured.
func DefaultPIDFilePath ¶ added in v0.1.68
func DefaultPIDFilePath() string
DefaultPIDFilePath returns the pid file path used when none is configured: LegacyPIDFilePath when a ./data directory already exists (Docker images and existing deployments), otherwise the OS-conventional per-user data directory — the same resolution the database uses, so both land together.
func DeriveMCPServerSlug ¶
DeriveMCPServerSlug creates a conservative default slug from a display name. Callers may let users edit it before creation; once persisted it is a stable identity and should not change when the display name changes.
func HasSecretReference ¶ added in v0.1.100
HasSecretReference reports whether value contains at least one secret reference, using the same scan as Resolve. An escaped $${...} is not a reference.
func HasUnresolvedPlaceholder ¶ added in v0.1.100
HasUnresolvedPlaceholder reports whether value contains a ${...} that is neither a secret reference nor an escaped $${: typically a legacy ${VAR} that environment expansion left in place because VAR is unset. Only meaningful before Resolve; a resolved value is data and is not scanned.
func IsLocalModelListSource ¶ added in v0.1.88
IsLocalModelListSource reports whether a model list location names a file on the local filesystem ("file://..." or a bare path) rather than an HTTP URL. It mirrors what the catalog fetcher accepts.
func JoinBasePath ¶
JoinBasePath prefixes urlPath with the normalized public mount path.
func LoadFailoverPolicy ¶ added in v0.1.84
func LoadFailoverPolicy(cfg *FailoverConfig) error
LoadFailoverPolicy validates the retry policy fields of cfg and fills the parsed RetryStatuses and RetryErrors, applying the defaults for empty lists.
func MCPServerEnabled ¶
func MCPServerEnabled(server MCPServerConfig) bool
MCPServerEnabled reports the effective enabled state (default true).
func NormalizeAllowedOrigin ¶ added in v0.1.80
NormalizeAllowedOrigin canonicalizes one origin for comparison against an Origin header: scheme and host lowercased, port preserved. Origins are compared exactly, so anything that is not a bare "scheme://host[:port]" is rejected rather than silently widened.
func NormalizeBasePath ¶
NormalizeBasePath canonicalizes the public mount path for the HTTP server. Empty, whitespace-only, and "/" all resolve to root.
func NormalizeBreakerScope ¶ added in v0.1.88
NormalizeBreakerScope resolves the empty scope to the provider default.
func NormalizeHeaderName ¶
NormalizeHeaderName canonicalizes an HTTP header field name. Empty values fall back to fallback.
func NormalizeMCPVirtualServer ¶ added in v0.1.104
func NormalizeMCPVirtualServer(virtual *MCPVirtualServerConfig) error
NormalizeMCPVirtualServer validates one admin-supplied definition and normalizes it in place: description, members, and tool_discovery. Admin input is literal, so nothing is left for secret resolution. The admin API checks nesting and member existence itself.
func OnlySecretReferences ¶ added in v0.1.101
OnlySecretReferences reports whether value is made of secret references alone, one or more, with no literal text around or between them. The admin API shows such a value as stored; a value that mixes literal text with a reference may carry a literal secret and is masked like one.
func OriginHost ¶ added in v0.1.80
OriginHost returns the "host[:port]" of an origin already canonicalized by NormalizeAllowedOrigin, which is the form a Host header carries.
func ParseBodySizeLimitBytes ¶
ParseBodySizeLimitBytes parses a configured body size limit into bytes. Accepts formats like: "10M", "10MB", "1024K", "1024KB", "104857600". Returns an error if the format is invalid or value is outside bounds (1KB - 100MB).
func ParseResilienceStatuses ¶ added in v0.1.88
ParseResilienceStatuses expands exact HTTP codes and classes. Nil uses the supplied defaults; an explicit empty list disables status-based matches.
func ProviderModelIDs ¶
func ProviderModelIDs(models []RawProviderModel) []string
ProviderModelIDs returns the ID of each model entry, preserving order and dropping entries with empty IDs.
func ProviderModelMetadataOverrides ¶
func ProviderModelMetadataOverrides(models []RawProviderModel) map[string]*core.ModelMetadata
ProviderModelMetadataOverrides returns id -> metadata for entries with non-nil Metadata. Returns nil if no entries declare metadata.
func ResolveClientIPPolicy ¶ added in v0.1.95
func ResolveClientIPPolicy(cfg *ServerConfig) error
ResolveClientIPPolicy validates the server's client-address settings and compiles them into ServerConfig.ClientIP, rewriting TrustedProxies as the networks it resolved so logs and config dumps show what is actually trusted.
func ResolveMediaConfig ¶ added in v0.1.96
func ResolveMediaConfig(cfg *MediaConfig) error
ResolveMediaConfig fills defaults and validates the media storage block.
func ResolveMetricsEndpoint ¶ added in v0.1.74
ResolveMetricsEndpoint returns the normalized, safe endpoint used by the HTTP server. Extensions should use the same value when excluding Prometheus scrapes from request instrumentation.
func ResolveMetricsEndpointWithPprof ¶ added in v0.1.74
ResolveMetricsEndpointWithPprof also prevents the metrics route from shadowing an enabled pprof route.
func RestrictSecretReferences ¶ added in v0.1.101
RestrictSecretReferences returns a context in which StoreSecret accepts only the secret references the stored entity already holds. Authentication applies it to every credential other than the master key, when one is configured: a reference resolves on the gateway host, so whoever can add one can read any environment variable or file the gateway can, the master key included.
func SecretFieldFromContext ¶ added in v0.1.101
SecretFieldFromContext returns the field a SecretResolver is resolving for, as passed to ResolveSecret: a configuration path such as "server.master_key", "extensions.vaults.token", or "providers.openai.api_keys[1]". A provider API key set by an environment variable is named by the variable ("OPENAI_API_KEY_2"); other provider values an environment variable set are named by the provider field. Field labels are not secret, so resolvers may log them for audit. The boolean is false for an anonymous Resolve.
func SemanticCacheActive ¶
func SemanticCacheActive(sem *SemanticCacheConfig) bool
SemanticCacheActive reports whether the semantic response cache should be validated and constructed. The semantic block must be present (YAML or SEMANTIC_CACHE_ENABLED=true); omitted enabled means true.
func SimpleCacheEnabled ¶
func SimpleCacheEnabled(s *SimpleCacheConfig) bool
SimpleCacheEnabled reports whether the exact-match response cache layer is allowed to run for a non-nil simple config. Omitted enabled means true.
func ValidateBodySizeLimit ¶
ValidateBodySizeLimit validates a body size limit string. Accepts formats like: "10M", "10MB", "1024K", "1024KB", "104857600" Returns an error if the format is invalid or value is outside bounds (1KB - 100MB).
func ValidateCacheConfig ¶
func ValidateCacheConfig(c *CacheConfig) error
ValidateCacheConfig validates the cache configuration in c. For the model cache, at least one backend (Local or Redis) must be configured; having neither is an error. Both may be set: Redis is preferred and Local is the fallback if Redis is unreachable at startup. When Redis is selected, its URL must be non-empty. Returns a descriptive error if any constraint is violated, or nil if the configuration is valid.
func ValidateMCPServerConfig ¶
func ValidateMCPServerConfig(server *MCPServerConfig) error
ValidateMCPServerConfig validates one server definition and applies defaults in place. It is shared by config loading and the admin API.
func ValidateMCPServerName ¶
ValidateMCPServerName accepts a human-facing Unicode display name. Machine constraints belong to the separate immutable slug.
func ValidateMCPServerSlug ¶
ValidateMCPServerSlug validates the stable ASCII identity used in routes, scope headers, and aggregated tool/prompt names.
func ValidateMCPVirtualServerName ¶ added in v0.1.104
ValidateMCPVirtualServerName applies the server slug rules: the name is a /mcp/{name} URL segment and prefixes nothing, but sharing the rules keeps one alphabet for that path segment. Shared by config loading and the admin API.
func ValidateResilience ¶ added in v0.1.88
func ValidateResilience(r ResilienceConfig) error
ValidateResilience checks policies for both file loading and programmatic providers.
func ValidateServerTLS ¶ added in v0.2.0
func ValidateServerTLS(server ServerConfig) error
ValidateServerTLS reports a half-configured certificate pair, and a client CA without one. The files themselves are read when the server starts.
func WithKeptSecrets ¶ added in v0.2.0
WithKeptSecrets returns a context recording that values, secret values of the entity being saved, were not supplied by the caller but resolved from the stored row, which is how an admin API resolves the redaction mask the dashboard echoes back. CheckSecretDestinations treats them like references: the caller cannot read them, so it may not repoint the entity that sends them.
Types ¶
type AdminConfig ¶
type AdminConfig struct {
// EndpointsEnabled controls whether the admin REST API is active
// Default: true
EndpointsEnabled bool `yaml:"endpoints_enabled" env:"ADMIN_ENDPOINTS_ENABLED"`
// UIEnabled controls whether the admin dashboard UI is active
// Requires EndpointsEnabled — if endpoints are disabled and UI is enabled,
// a warning is logged and UI is forced to false.
// Default: true
UIEnabled bool `yaml:"ui_enabled" env:"ADMIN_UI_ENABLED"`
// LiveLogsEnabled controls whether the dashboard opens a realtime log stream.
// Default: true
LiveLogsEnabled bool `yaml:"live_logs_enabled" env:"DASHBOARD_LIVE_LOGS_ENABLED"`
// LiveLogsBufferSize is the in-memory replay window for dashboard live log events.
// Default: 10000
LiveLogsBufferSize int `yaml:"live_logs_buffer_size" env:"DASHBOARD_LIVE_LOGS_BUFFER_SIZE"`
// LiveLogsReplayLimit caps events replayed to one reconnecting dashboard client.
// Default: 1000
LiveLogsReplayLimit int `yaml:"live_logs_replay_limit" env:"DASHBOARD_LIVE_LOGS_REPLAY_LIMIT"`
// LiveLogsHeartbeatSeconds keeps idle stream connections and proxies active.
// Default: 15
LiveLogsHeartbeatSeconds int `yaml:"live_logs_heartbeat_seconds" env:"DASHBOARD_LIVE_LOGS_HEARTBEAT_SECONDS"`
}
AdminConfig holds configuration for the admin API and dashboard UI.
type BudgetLabelConfig ¶ added in v0.1.60
type BudgetLabelConfig struct {
Label string `yaml:"label"`
Limits []BudgetLimitConfig `yaml:"limits"`
}
BudgetLabelConfig declares one or more budget limits for a request label.
type BudgetLimitConfig ¶
type BudgetLimitConfig struct {
// Period accepts hourly, daily, weekly, or monthly. The resolved period is
// persisted as PeriodSeconds in the database.
Period string `yaml:"period" json:"period"`
// PeriodSeconds can be set directly instead of Period. Standard values are
// 3600, 86400, 604800, and 2592000.
PeriodSeconds int64 `yaml:"period_seconds" json:"period_seconds"`
// Amount is the maximum allowed tracked spend for the period.
Amount float64 `yaml:"amount" json:"amount"`
// CostBasis selects the spend the amount limits: provider (default) for
// upstream provider cost, or billed for provider cost plus markup. billed
// requires pricing.markups_enabled and a GoModel Pro license with the
// billing entitlement.
CostBasis string `yaml:"cost_basis" json:"cost_basis,omitempty"`
// PerChild is accepted only in the JSON-array environment-variable form.
// YAML keeps this setting on the enclosing user-path entry.
PerChild bool `yaml:"-" json:"per_child,omitempty"`
}
BudgetLimitConfig declares one spend limit for a reset period. The json tags support the JSON-array form of SET_BUDGET_* env values.
type BudgetProviderConfig ¶ added in v0.1.104
type BudgetProviderConfig struct {
Name string `yaml:"name"`
Limits []BudgetLimitConfig `yaml:"limits"`
}
BudgetProviderConfig declares one or more budget limits for a provider.
type BudgetUserPathConfig ¶
type BudgetUserPathConfig struct {
Path string `yaml:"path"`
PerChild bool `yaml:"per_child"`
Limits []BudgetLimitConfig `yaml:"limits"`
}
BudgetUserPathConfig declares one or more budget limits for a user path.
type BudgetsConfig ¶
type BudgetsConfig struct {
// Enabled controls whether budget checks are active.
// Default: true. Requires usage tracking because spend limits are evaluated
// from usage cost records.
Enabled bool `yaml:"enabled" env:"BUDGETS_ENABLED"`
// UserPaths declares budget limits by tracked user path.
UserPaths []BudgetUserPathConfig `yaml:"user_paths"`
// Labels declares budget limits by request label. A request carrying
// several labels is charged against every matching label budget.
//
// Labels have no env-var form: they are matched verbatim and may contain
// characters and casing that env var names cannot express. Declare them
// here or through the admin API.
Labels []BudgetLabelConfig `yaml:"labels"`
// Providers declares budget limits by configured provider name. A
// provider budget caps all spend routed to that provider instance;
// failover skips a provider whose budget is exhausted.
Providers []BudgetProviderConfig `yaml:"providers"`
// ProviderBilledCacheHits controls whether a provider budget on billed
// cost counts the billed response-cache hits of that provider's models.
// Default: true. Set false to limit only what was billed for requests the
// provider served. Provider-cost budgets never count cache hits.
ProviderBilledCacheHits bool `yaml:"provider_billed_cache_hits" env:"BUDGETS_PROVIDER_BILLED_CACHE_HITS"`
}
BudgetsConfig holds spend limits by user path, request label, and provider.
type CacheConfig ¶
type CacheConfig struct {
Model ModelCacheConfig `yaml:"model"`
Response ResponseCacheConfig `yaml:"response"`
}
CacheConfig holds model and response cache configuration.
type CircuitBreakerConfig ¶
type CircuitBreakerConfig struct {
// FailureOnStatuses uses defaults when nil; an empty list disables status triggers.
FailureOnStatuses []string `yaml:"failure_on_statuses" env:"CIRCUIT_BREAKER_FAILURE_ON_STATUSES"`
Scope string `yaml:"scope" env:"CIRCUIT_BREAKER_SCOPE"`
// Enabled switches the circuit breaker on or off. When false, requests are
// never short-circuited regardless of the thresholds below.
// Default: true
Enabled bool `yaml:"enabled" env:"CIRCUIT_BREAKER_ENABLED"`
FailureThreshold int `yaml:"failure_threshold" env:"CIRCUIT_BREAKER_FAILURE_THRESHOLD"`
SuccessThreshold int `yaml:"success_threshold" env:"CIRCUIT_BREAKER_SUCCESS_THRESHOLD"`
Timeout time.Duration `yaml:"timeout" env:"CIRCUIT_BREAKER_TIMEOUT"`
// SlowCallThreshold counts a call that was answered, but slower than this,
// as a breaker failure, so sustained latency opens the circuit like
// sustained errors do. Zero disables the latency trigger.
// Default: 0
SlowCallThreshold time.Duration `yaml:"slow_call_threshold" env:"CIRCUIT_BREAKER_SLOW_CALL_THRESHOLD"`
}
CircuitBreakerConfig holds resolved circuit breaker settings. This is the canonical type shared between config and llmclient.
func DefaultCircuitBreakerConfig ¶
func DefaultCircuitBreakerConfig() CircuitBreakerConfig
DefaultCircuitBreakerConfig returns the default circuit breaker settings.
type ClientIPPolicy ¶ added in v0.1.95
type ClientIPPolicy struct {
// Prefixes are the networks whose requests may carry a client address.
Prefixes []netip.Prefix
// Header carries the client address. Empty when no proxy is trusted.
Header string
// Hops is the number of proxies between the client and the gateway. Zero
// selects chain-scanning by Prefixes instead of a fixed depth.
Hops int
// contains filtered or unexported fields
}
ClientIPPolicy is the resolved form of the server's client-address settings: which peers may speak about the client, which header they speak through, and how to read it. The zero value trusts nothing, which makes every request report the address of the socket that reached the gateway.
func (ClientIPPolicy) Enabled ¶ added in v0.1.95
func (p ClientIPPolicy) Enabled() bool
Enabled reports whether any peer is trusted to speak about the client.
func (ClientIPPolicy) Resolve ¶ added in v0.1.95
func (p ClientIPPolicy) Resolve(req *http.Request) string
Resolve returns the address to attribute a request to. Forwarding headers are read only when the request arrived from a trusted network; anything the policy cannot vouch for falls back to the address of the socket peer, which no client can forge.
type Config ¶
type Config struct {
Server ServerConfig `yaml:"server"`
Models ModelsConfig `yaml:"models"`
Cache CacheConfig `yaml:"cache"`
Storage StorageConfig `yaml:"storage"`
Logging LogConfig `yaml:"logging"`
Media MediaConfig `yaml:"media"`
Usage UsageConfig `yaml:"usage"`
Pricing PricingConfig `yaml:"pricing"`
Budgets BudgetsConfig `yaml:"budgets"`
RateLimits RateLimitsConfig `yaml:"rate_limits"`
Metrics MetricsConfig `yaml:"metrics"`
OpenTelemetry OpenTelemetryConfig `yaml:"opentelemetry"`
HTTP HTTPConfig `yaml:"http"`
Admin AdminConfig `yaml:"admin"`
Guardrails GuardrailsConfig `yaml:"guardrails"`
Failover FailoverConfig `yaml:"failover"`
Workflows WorkflowsConfig `yaml:"workflows"`
Resilience ResilienceConfig `yaml:"resilience"`
Tagging TaggingConfig `yaml:"tagging"`
Session SessionConfig `yaml:"session"`
MCP MCPConfig `yaml:"mcp"`
// Plugins controls which plugin shared objects (.so) are loaded at startup.
Plugins PluginsConfig `yaml:"plugins"`
// VersionCheck controls the daily update check against the public
// release manifest. See VersionCheckConfig for what it sends.
VersionCheck VersionCheckConfig `yaml:"version_check"`
// Offline is the one switch for air-gapped installs. It turns off every
// outbound call the gateway makes on its own: the update check and the
// remote model catalog download. Calls to configured providers and to
// anything else the operator declared (OTLP, MCP upstreams, vector
// stores) are untouched. A catalog served from a local file keeps working.
// Default: false
Offline bool `yaml:"offline" env:"GOMODEL_OFFLINE"`
// Extensions holds configuration owned by custom distributions. Core keeps
// the values opaque; an extension decodes its named section with
// LoadResult.DecodeExtension.
Extensions map[string]yaml.Node `yaml:"extensions,omitempty"`
// VirtualModels declares redirects, load balancers, and access policies as
// infrastructure-as-code. They override admin-store rows of the same source.
VirtualModels []VirtualModelConfig `yaml:"virtual_models"`
// Users declares per-user-path model access policies as
// infrastructure-as-code. They shadow admin-store rows of the same path.
Users []UserConfig `yaml:"users"`
}
Config holds the application configuration.
type ConfiguredProviderModelsMode ¶
type ConfiguredProviderModelsMode string
ConfiguredProviderModelsMode controls how explicitly configured provider model lists are applied to the discovered model inventory.
const ( // ConfiguredProviderModelsModeFallback uses configured models only when the // upstream /models call fails or returns nothing. ConfiguredProviderModelsModeFallback ConfiguredProviderModelsMode = "fallback" // ConfiguredProviderModelsModeAllowlist exposes only the configured models // and skips the upstream /models call. ConfiguredProviderModelsModeAllowlist ConfiguredProviderModelsMode = "allowlist" // ConfiguredProviderModelsModeMerge unions the upstream inventory with the // configured models, so models a provider serves but does not list stay // routable without hiding the discovered ones. ConfiguredProviderModelsModeMerge ConfiguredProviderModelsMode = "merge" )
func NormalizeConfiguredProviderModelsMode ¶
func NormalizeConfiguredProviderModelsMode(mode ConfiguredProviderModelsMode) ConfiguredProviderModelsMode
NormalizeConfiguredProviderModelsMode canonicalizes a configured provider models mode.
func ResolveConfiguredProviderModelsMode ¶
func ResolveConfiguredProviderModelsMode(mode ConfiguredProviderModelsMode) ConfiguredProviderModelsMode
ResolveConfiguredProviderModelsMode canonicalizes mode and applies the process default.
func (ConfiguredProviderModelsMode) Valid ¶
func (m ConfiguredProviderModelsMode) Valid() bool
Valid reports whether mode is one of the supported configured-provider-models modes.
type EmbedderConfig ¶
EmbedderConfig selects how embeddings are generated. Provider must match a key in the top-level providers map when semantic caching is active; that provider's api_key and base_url are reused for POST /v1/embeddings. There is no default provider.
type FailoverConfig ¶
type FailoverConfig struct {
// Enabled controls failover globally. It defaults to true; configured rules
// and workflow policy decide whether any request has failover candidates.
Enabled bool `yaml:"enabled" env:"FAILOVER_ENABLED"`
// MaxAttempts caps how many failover targets one request may try after
// its primary attempt fails. Zero (the default) sweeps every remaining
// target in order.
MaxAttempts int `yaml:"max_attempts" env:"FAILOVER_MAX_ATTEMPTS"`
// RetryOnStatuses lists the upstream HTTP statuses that trigger failover:
// exact codes (408) or whole classes (5xx). Setting it replaces the
// default DefaultFailoverRetryStatuses; an empty list keeps the default.
RetryOnStatuses []string `yaml:"retry_on_statuses" env:"FAILOVER_RETRY_ON_STATUSES"`
// RetryOnErrors lists phrases that trigger failover regardless of status:
// an error qualifies when every word of a phrase appears in its code or
// message. A numeric word (404, 4xx) matches the HTTP status instead of
// the text. Setting it replaces the default DefaultFailoverRetryErrors; an
// empty list keeps the default.
RetryOnErrors []string `yaml:"retry_on_errors" env:"FAILOVER_RETRY_ON_ERRORS"`
// DefaultMode is a deprecated compatibility field. It is accepted from old
// config files and FAILOVER_MODE, but runtime failover is manual-only.
DefaultMode FailoverMode `yaml:"default_mode" env:"FAILOVER_MODE"`
// ManualRulesPath points to a JSON file that maps source model selectors to
// ordered failover model selector lists. Empty disables manual rules.
ManualRulesPath string `yaml:"manual_rules_path" env:"FAILOVER_MANUAL_RULES_PATH"`
// Rules defines manual failover rules inline in config.yaml.
Rules map[string][]string `yaml:"rules"`
// RulesJSON defines manual failover rules inline from env.
RulesJSON string `yaml:"rules_json" env:"FAILOVER_RULES_JSON"`
// DisabledModels disables failover for matching source selectors.
DisabledModels []string `yaml:"disabled_models" env:"FAILOVER_DISABLED_MODELS"`
// DisabledModelsJSON disables failover for matching source selectors from
// env. It accepts either a JSON string array or object with boolean values.
DisabledModelsJSON string `yaml:"disabled_models_json" env:"FAILOVER_DISABLED_MODELS_JSON"`
// Overrides is a removed compatibility field. Per-model failover modes are gone;
// operators migrate to DisabledModels. It is still parsed — and ignored, with a
// warning — so an old config file keeps booting under strict YAML validation.
Overrides map[string]any `yaml:"overrides"`
// Manual holds the parsed manual failover lists loaded from ManualRulesPath.
Manual map[string][]string `yaml:"-"`
// Disabled holds normalized per-model failover disables.
Disabled map[string]bool `yaml:"-"`
// RetryStatuses is the parsed RetryOnStatuses (or its default): the set of
// HTTP statuses that trigger failover.
RetryStatuses map[int]bool `yaml:"-"`
// RetryErrors is the parsed RetryOnErrors (or its default): one lower-cased
// word list per phrase.
RetryErrors []FailoverErrorPhrase `yaml:"-"`
}
FailoverConfig holds translated-route model failover policy.
type FailoverErrorPhrase ¶ added in v0.1.84
type FailoverErrorPhrase struct {
// Words are the lower-cased text fragments the error must contain.
Words []string
// Statuses are HTTP statuses the error must carry; empty means any.
Statuses map[int]bool
}
FailoverErrorPhrase is one parsed retry_on_errors entry. Every Word must appear in the error text and every status constraint must hold.
type FailoverMode ¶
type FailoverMode string
const ( FailoverModeOff FailoverMode = "off" FailoverModeManual FailoverMode = "manual" FailoverModeAuto FailoverMode = "auto" )
func ResolveFailoverDefaultMode ¶
func ResolveFailoverDefaultMode(mode FailoverMode) FailoverMode
ResolveFailoverDefaultMode canonicalizes the global failover default mode and applies the process default when unset.
func (FailoverMode) Valid ¶
func (m FailoverMode) Valid() bool
Valid reports whether mode is one of the supported failover modes.
type GuardrailRuleConfig ¶
type GuardrailRuleConfig struct {
// Name is a unique identifier for this guardrail instance (used in logs and errors)
Name string `yaml:"name"`
// Type selects the plugin the instance is built from: a built-in such as
// "system_prompt", "llm_based_altering", "string_replace", "tag_replace",
// "header_edit", "llm_judge", "presidio", or the manifest name of a loaded plugin.
Type string `yaml:"type"`
// UserPath scopes internal auxiliary guardrail requests for workflow
// selection and audit logging. When empty, the caller user path is used.
UserPath string `yaml:"user_path"`
// Order controls execution ordering relative to other guardrails.
// Guardrails with the same order run in parallel; different orders run sequentially.
// Default: 0
Order int `yaml:"order"`
// Phase selects where the default workflow runs this instance:
// "prompt" (before the provider call), "response" (on the complete
// response), or "stream" (per streamed event).
// Default: "prompt"
Phase string `yaml:"phase"`
// Config is the plugin's own configuration, validated against the
// plugin's config schema (see GET /admin/guardrails/types). The typed
// system_prompt and llm_based_altering blocks below are folded into it.
//
// LoadResult.ResolveSecrets leaves its secret references in place: the
// rule is seeded into the guardrail store with them, secret fields are
// resolved when the guardrail is built, and other fields when the rule is
// seeded. A resolved secret is therefore never written to the database.
Config map[string]any `yaml:"config" secrets:"deferred"`
// FailMode selects what happens when the instance errors or times out:
// "closed" rejects the request with HTTP 500, "open" continues without it.
// Default: empty (closed for prompt/response/stream phases)
FailMode string `yaml:"fail_mode"`
// TimeoutMS bounds every hook call of the instance in milliseconds.
// Default: 0 (no per-instance timeout)
TimeoutMS int `yaml:"timeout_ms"`
// SystemPrompt holds settings when Type is "system_prompt"
SystemPrompt SystemPromptSettings `yaml:"system_prompt"`
// LLMBasedAltering holds settings when Type is "llm_based_altering"
LLMBasedAltering LLMBasedAlteringSettings `yaml:"llm_based_altering"`
}
GuardrailRuleConfig defines a single guardrail instance.
type GuardrailsConfig ¶
type GuardrailsConfig struct {
// Enabled controls whether guardrails are active
// Default: false
Enabled bool `yaml:"enabled" env:"GUARDRAILS_ENABLED"`
// EnableForBatchProcessing controls whether guardrails are applied to inline
// batch items for /v1/batches requests.
// Default: false
EnableForBatchProcessing bool `yaml:"enable_for_batch_processing" env:"ENABLE_GUARDRAILS_FOR_BATCH_PROCESSING"`
// Rules is a list of guardrail instances. Each entry defines one guardrail
// with its own name, type, order, and type-specific settings. Multiple
// instances of the same type are allowed (e.g. two system_prompt guardrails
// with different content).
Rules []GuardrailRuleConfig `yaml:"rules"`
}
GuardrailsConfig holds configuration for the request guardrails pipeline.
type HTTPConfig ¶
type HTTPConfig struct {
// Timeout is the overall HTTP request timeout in seconds (default: 600)
Timeout int `yaml:"timeout" env:"HTTP_TIMEOUT"`
// ResponseHeaderTimeout is the time to wait for response headers in seconds (default: 600)
ResponseHeaderTimeout int `yaml:"response_header_timeout" env:"HTTP_RESPONSE_HEADER_TIMEOUT"`
// StreamIdleTimeout is the longest silence, in seconds, a streaming
// response may keep once its first bytes arrived before GoModel gives up
// on it (default: 300). 0 disables it. The HTTP_STREAM_IDLE_TIMEOUT env var
// is read by internal/httpclient instead of the generic env overlay, so it
// accepts Go durations such as "2m" as well as seconds.
StreamIdleTimeout int `yaml:"stream_idle_timeout"`
// TLS configures client-side trust for the gateway's outbound HTTPS
// clients; see HTTPTLSConfig for what it covers.
TLS HTTPTLSConfig `yaml:"tls"`
}
HTTPConfig holds HTTP client configuration for upstream API requests. App startup installs these values into internal/httpclient before providers are constructed; the HTTP_TIMEOUT and HTTP_RESPONSE_HEADER_TIMEOUT env vars take precedence over the YAML values.
type HTTPTLSConfig ¶ added in v0.2.0
type HTTPTLSConfig struct {
// CAFile is a PEM bundle of additional root certificates, appended to the
// system store. Set it for a private CA behind a TLS-intercepting proxy or
// in front of local model servers.
CAFile string `yaml:"ca_file" env:"HTTP_TLS_CA_FILE"`
// ClientCertFile and ClientKeyFile present a client certificate (mTLS) to
// upstreams that request one. Both must be set together.
ClientCertFile string `yaml:"client_cert_file" env:"HTTP_TLS_CLIENT_CERT_FILE"`
ClientKeyFile string `yaml:"client_key_file" env:"HTTP_TLS_CLIENT_KEY_FILE"`
// InsecureSkipVerify disables certificate verification for those outbound
// clients. Lab use only; the gateway logs a warning at startup.
InsecureSkipVerify bool `yaml:"insecure_skip_verify" env:"HTTP_TLS_INSECURE_SKIP_VERIFY"`
}
HTTPTLSConfig configures client TLS trust for outbound connections: providers, the model catalog, the update check, MCP upstreams, vector stores, and embedding endpoints. The OTLP exporters and the PostgreSQL, MongoDB, and Redis drivers keep their own TLS settings. All fields are optional; the zero value trusts the operating system certificate store.
type ImageBodyScope ¶ added in v0.1.81
type ImageBodyScope string
ImageBodyScope selects which image bytes the audit log embeds when LogImageBodies is enabled.
const ( ImageBodyScopeAll ImageBodyScope = "all" ImageBodyScopeInput ImageBodyScope = "input" ImageBodyScopeOutput ImageBodyScope = "output" )
func ResolveImageBodyScope ¶ added in v0.1.81
func ResolveImageBodyScope(value ImageBodyScope) ImageBodyScope
ResolveImageBodyScope normalizes a configured scope, defaulting to all.
func (ImageBodyScope) Inputs ¶ added in v0.1.81
func (s ImageBodyScope) Inputs() bool
Inputs reports whether uploaded images (edit sources and masks) are stored.
func (ImageBodyScope) Outputs ¶ added in v0.1.81
func (s ImageBodyScope) Outputs() bool
Outputs reports whether generated images are stored.
func (ImageBodyScope) Valid ¶ added in v0.1.81
func (s ImageBodyScope) Valid() bool
Valid reports whether the scope is one of the supported values.
type KeyWrapper ¶ added in v0.1.100
type KeyWrapper interface {
ID() string
WrapKey(ctx context.Context, dek []byte) ([]byte, error)
UnwrapKey(ctx context.Context, wrapped []byte) ([]byte, error)
}
KeyWrapper wraps the data keys that encrypt dashboard-managed secrets at rest. GoModel generates one random 256-bit data key per database and stores it only in wrapped form; by default the key-encryption key is derived from GOMODEL_ENCRYPTION_KEY. An extension sets a KeyWrapper with LoadResult.SetKeyWrapper to wrap data keys with a KMS instead.
ID names the wrapper and is stored with every key it wraps; only a wrapper with the same id is asked to unwrap that key. It must stay stable across restarts. At startup a data key stored under another id is unwrapped with a previous wrapper passed to SetKeyWrapper, or with GOMODEL_ENCRYPTION_KEY (or GOMODEL_ENCRYPTION_KEY_PREVIOUS) when it was wrapped locally, and then re-wrapped with this wrapper.
Implementations must never log or return the data key in an error.
type LLMBasedAlteringSettings ¶
type LLMBasedAlteringSettings struct {
// Model is the model selector used for the auxiliary rewrite call.
// This can be a concrete model name, provider-qualified selector, or alias.
Model string `yaml:"model"`
// Provider is an optional routing hint for Model.
Provider string `yaml:"provider"`
// Prompt is the system prompt used to rewrite targeted messages.
// When empty, the built-in LiteLLM-derived anonymization prompt is used.
Prompt string `yaml:"prompt"`
// Roles selects which message roles are rewritten.
// Default: ["user"]
Roles []string `yaml:"roles"`
// SkipContentPrefix skips rewriting for messages whose trimmed text begins with this prefix.
SkipContentPrefix string `yaml:"skip_content_prefix"`
// MaxTokens limits the auxiliary rewrite completion.
// Default: 4096
MaxTokens int `yaml:"max_tokens"`
}
LLMBasedAlteringSettings holds the type-specific settings for an llm_based_altering guardrail.
type LoadResult ¶
type LoadResult struct {
Config *Config
RawProviders map[string]RawProviderConfig
// Secrets resolves ${scheme:reference} secret references for this
// generation. Load leaves references in place; a distribution may Register
// more schemes in its configuration hook before ResolveSecrets runs.
Secrets *Secrets
// contains filtered or unexported fields
}
LoadResult is returned by Load and bundles the application config with the raw provider map parsed from YAML. Provider env vars and resolution are handled by the providers package.
func Load ¶
func Load() (*LoadResult, error)
Load reads configuration from file and environment using a three-layer pipeline:
defaults (code) → config.yaml (optional overlay) → env vars (always win)
The returned LoadResult contains the resolved application Config and the raw provider map parsed from YAML. Provider env var discovery, credential filtering, and resilience merging are handled by the providers package.
func (*LoadResult) DecodeExtension ¶ added in v0.1.71
func (r *LoadResult) DecodeExtension(name string, target any) (bool, error)
DecodeExtension strictly decodes one named extensions: section into target. It returns false when the section is absent. Core deliberately does not know any extension's schema, while each extension still gets unknown-key safety. Secret references in the section are resolved with the schemes registered on Secrets at the time of the call.
func (*LoadResult) KeyWrapper ¶ added in v0.1.100
func (r *LoadResult) KeyWrapper() KeyWrapper
KeyWrapper returns the wrapper set with SetKeyWrapper, or nil.
func (*LoadResult) PreviousKeyWrappers ¶ added in v0.1.100
func (r *LoadResult) PreviousKeyWrappers() []KeyWrapper
PreviousKeyWrappers returns the previous wrappers passed to SetKeyWrapper.
func (*LoadResult) ResolveSecrets ¶ added in v0.1.100
func (r *LoadResult) ResolveSecrets(ctx context.Context) error
ResolveSecrets resolves every secret reference in Config, failing on the first one that cannot be resolved, then re-checks the settings whose load-time validation had to accept a reference. Extensions are skipped: DecodeExtension resolves a section when it is decoded. RawProviders are skipped too: providers.Init resolves them after the provider environment variables are merged, so a value an environment variable replaces is never looked up.
It runs once per generation, after the distribution's configuration hook has registered its schemes. Later calls return the first call's result, so a resolved value is never scanned again, not even after a failure left the configuration partly resolved.
func (*LoadResult) SetKeyWrapper ¶ added in v0.1.100
func (r *LoadResult) SetKeyWrapper(w KeyWrapper, previous ...KeyWrapper)
SetKeyWrapper replaces the key-encryption key derived from GOMODEL_ENCRYPTION_KEY with w for this configuration generation. Call it from run.Options.SetupConfig, before the application opens storage. A reload keeps the wrappers of the previous generation unless run.Options.ReloadConfig sets others.
previous lists wrappers w replaces, for example after moving to another KMS key: data keys they wrapped are re-wrapped with w at startup, after which they can be dropped.
type LocalCacheConfig ¶
type LocalCacheConfig struct {
CacheDir string `yaml:"cache_dir" env:"GOMODEL_CACHE_DIR"`
}
LocalCacheConfig holds local file cache configuration.
type LogConfig ¶
type LogConfig struct {
// Enabled controls whether audit logging is active
// Default: false
Enabled bool `yaml:"enabled" env:"LOGGING_ENABLED"`
// LogBodies enables logging of full request/response bodies
// WARNING: May contain sensitive data (PII, API keys in prompts)
// Default: true
LogBodies bool `yaml:"log_bodies" env:"LOGGING_LOG_BODIES"`
// LogAudioBodies refines LogBodies for audio endpoints: when both are
// enabled, the /v1/audio/speech JSON input and binary audio output are
// stored (audio as base64 for playback) and /v1/audio/transcriptions upload
// metadata is recorded. Requires LogBodies (the master body-logging switch);
// when LogBodies is on but this is off, audio responses are recorded as a
// lightweight placeholder instead of the full bytes.
// WARNING: stores full audio in the audit log; grows storage quickly.
// Default: false
LogAudioBodies bool `yaml:"log_audio_bodies" env:"LOGGING_LOG_AUDIO_BODIES"`
// LogImageBodies refines LogBodies for the image endpoints
// (/v1/images/generations, /v1/images/edits): when both are enabled the
// image bytes (uploaded sources and masks, generated outputs) are stored as
// base64 so the dashboard can display them. Requires LogBodies; when
// LogBodies is on but this is off, image bodies keep their metadata
// (prompt, parameters, sizes, usage) and URLs but drop the pixels.
// WARNING: stores full images in the audit log; grows storage quickly.
// Default: false
LogImageBodies bool `yaml:"log_image_bodies" env:"LOGGING_LOG_IMAGE_BODIES"`
// LogImageBodiesScope narrows LogImageBodies to one direction: "all"
// stores uploaded inputs and generated outputs, "input" only the uploads
// (edit sources and masks), "output" only the generated images. Ignored
// while LogImageBodies is off.
// Default: all
LogImageBodiesScope ImageBodyScope `yaml:"log_image_bodies_scope" env:"LOGGING_LOG_IMAGE_BODIES_SCOPE"`
// LogRevisionBodies refines LogBodies for the request-revision chain:
// when both are enabled, every request rewriter that changed the body
// (for example GoModel Pro token compression) and every prompt guardrail
// that edited the prompt store the request as they left it alongside the
// original in the audit entry. Requires LogBodies.
// Disabling it keeps the revision metadata (rewriter name, sizes, tokens
// saved, change detail) but drops the rewritten body copy — roughly
// halving audit storage per compressed request.
// Default: true
LogRevisionBodies bool `yaml:"log_revision_bodies" env:"LOGGING_LOG_REVISION_BODIES"`
// LogGuardrailSteps records every prompt guardrail that edited the
// request as its own revision in the audit entry, carrying the request
// as that step left it, so a chain of edits reads step by step. Each
// step leaves a copy of the prompt behind; building and encoding the
// requests from those copies runs off the request path. Disabling it
// records the
// chain's edits as one revision (the request as forwarded) and skips
// the per-step snapshots.
// Default: true
LogGuardrailSteps bool `yaml:"log_guardrail_steps" env:"LOGGING_LOG_GUARDRAIL_STEPS"`
// LogHeaders enables logging of request/response headers
// Sensitive headers (Authorization, Cookie, etc.) are auto-redacted
// Default: true
LogHeaders bool `yaml:"log_headers" env:"LOGGING_LOG_HEADERS"`
// BufferSize is the number of log entries to buffer before flushing
// Default: 1000
BufferSize int `yaml:"buffer_size" env:"LOGGING_BUFFER_SIZE"`
// FlushInterval is how often to flush buffered logs (in seconds)
// Default: 5
FlushInterval int `yaml:"flush_interval" env:"LOGGING_FLUSH_INTERVAL"`
// RetentionDays is how long to keep logs (0 = forever)
// Default: 30
RetentionDays int `yaml:"retention_days" env:"LOGGING_RETENTION_DAYS"`
// OnlyModelInteractions limits audit logging to AI model endpoints only
// When true, only /v1/chat/completions, /v1/responses, /v1/embeddings, /v1/files, and /v1/batches are logged
// Endpoints like /health, /metrics, /admin, /v1/models are skipped
// Default: true
OnlyModelInteractions bool `yaml:"only_model_interactions" env:"LOGGING_ONLY_MODEL_INTERACTIONS"`
}
LogConfig holds audit logging configuration
type MCPConfig ¶
type MCPConfig struct {
// Enabled gates the /mcp routes. Default: true (a no-op without servers).
Enabled bool `yaml:"enabled" env:"MCP_ENABLED"`
// AllowedOrigins lists the browser origins ("scheme://host[:port]") that
// may reach /mcp. Empty — the default — trusts none, which is right for
// the MCP clients this endpoint serves, since none of them are web pages.
// It is what stops a DNS-rebound page from driving the gateway; only add
// an origin you actually serve an MCP web client from. TrustAnyOrigin
// ("*") turns the check off and is logged as a warning at startup.
AllowedOrigins []string `yaml:"allowed_origins" env:"MCP_ALLOWED_ORIGINS"`
// ToolDiscovery selects how sessions see tools by default. "off" (the
// default) lists every visible tool. "search" lists only search_tools and
// call_tool, so large catalogs stop costing context on every model turn.
// Clients override it per session with the X-MCP-Tool-Discovery header.
ToolDiscovery string `yaml:"tool_discovery" env:"MCP_TOOL_DISCOVERY"`
// Servers maps stable server slugs to upstream definitions. Slugs become
// tool namespaces and URL segments, so they are restricted to [a-z0-9_-].
Servers map[string]MCPServerConfig `yaml:"servers"`
// ProviderServers names configured providers whose hosted MCP servers
// (for example Z.ai web search) the gateway exposes as servers slugged
// "{provider}-{server}", authenticated with that provider's API key.
// Empty — the default — exposes none: each provider's tools cost money
// on its key, so operators opt in per provider.
ProviderServers []string `yaml:"provider_servers" env:"MCP_PROVIDER_SERVERS"`
// VirtualServers maps names to curated subsets of Servers, each served at
// /mcp/{name}. Names share that path with server slugs, so they must not
// match one.
VirtualServers map[string]MCPVirtualServerConfig `yaml:"virtual_servers"`
}
MCPConfig declares the MCP gateway: upstream MCP servers aggregated behind the authenticated /mcp endpoint. Declarative entries override admin-store rows with the same name and are read-only in the dashboard.
type MCPServerConfig ¶
type MCPServerConfig struct {
// URL is the upstream MCP endpoint for http/sse transports.
URL string `yaml:"url,omitempty" json:"url,omitempty"`
// Transport selects the upstream transport: "http" (streamable HTTP,
// default), "sse" (legacy HTTP+SSE), or "stdio" (spawned subprocess).
Transport string `yaml:"transport,omitempty" json:"transport,omitempty"`
// Headers are sent verbatim on every upstream request (http/sse). Values
// support ${ENV} expansion via the standard config pipeline. This is the
// credential boundary: client bearer tokens are never forwarded upstream.
Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
// Command, Args, and Env launch a stdio server as a subprocess. Stdio
// servers are deliberately declarative-only: the admin API and dashboard
// reject them, because registering subprocesses at runtime is a remote
// code execution vector.
Command string `yaml:"command,omitempty" json:"command,omitempty"`
Args []string `yaml:"args,omitempty" json:"args,omitempty"`
Env map[string]string `yaml:"env,omitempty" json:"env,omitempty"`
// Description is an optional human-readable note.
Description string `yaml:"description,omitempty" json:"description,omitempty"`
// Enabled toggles the entry. It defaults to true when omitted.
Enabled *bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
// AllowedTools restricts the tools exposed from this server (original,
// un-prefixed names). Empty means all tools.
AllowedTools []string `yaml:"allowed_tools,omitempty" json:"allowed_tools,omitempty"`
// DisallowedTools hides specific tools; applied after AllowedTools.
DisallowedTools []string `yaml:"disallowed_tools,omitempty" json:"disallowed_tools,omitempty"`
// UserPaths scopes server visibility to specific request user paths
// (subtree match, same semantics as virtual models). Empty means all.
UserPaths []string `yaml:"user_paths,omitempty" json:"user_paths,omitempty"`
// DisallowedUserPaths hides the server from these user-path subtrees,
// even inside an allowed UserPaths subtree. Empty excludes nobody.
DisallowedUserPaths []string `yaml:"disallowed_user_paths,omitempty" json:"disallowed_user_paths,omitempty"`
// ToolTimeout bounds a single tools/call against this server.
// Default: 30s.
ToolTimeout time.Duration `yaml:"tool_timeout,omitempty" json:"tool_timeout,omitempty"`
}
MCPServerConfig declares one upstream MCP server.
type MCPVirtualServerConfig ¶ added in v0.1.100
type MCPVirtualServerConfig struct {
// Description is an optional human-readable note.
Description string `yaml:"description,omitempty" json:"description,omitempty"`
// Servers lists the member server slugs. Required.
Servers []string `yaml:"servers" json:"servers"`
// ToolDiscovery overrides mcp.tool_discovery for sessions on this virtual
// server: "off" or "search". Empty inherits the gateway default.
ToolDiscovery string `yaml:"tool_discovery,omitempty" json:"tool_discovery,omitempty"`
}
MCPVirtualServerConfig declares a virtual MCP server: a named subset of the upstream servers served at /mcp/{name}, so a client configured with a URL alone can reach a curated mix. It filters, never grants: each member keeps its own user-path scope and tool filters.
type MediaConfig ¶ added in v0.1.96
type MediaConfig struct {
Storage MediaStorageConfig `yaml:"storage"`
}
MediaConfig says where the gateway keeps media files: audio and images captured for the audit log today, generated videos and images later. Media metadata always lives in the shared storage backend; only the bytes go here. See docs/adr/0013-media-storage.md.
type MediaStorageConfig ¶ added in v0.1.96
type MediaStorageConfig struct {
// Type is the blob backend: "filesystem" (default) writes files under
// Path; "memory" keeps them in the process and loses them on restart.
Type string `yaml:"type" env:"MEDIA_STORAGE_TYPE"`
// Path is the directory the filesystem backend writes to. Default:
// ./data/media when a ./data directory exists, otherwise the OS per-user
// data directory (e.g. ~/.local/share/gomodel/media). Mount a volume,
// EFS, or an S3 FUSE mount there to keep media off the local disk.
Path string `yaml:"path" env:"MEDIA_STORAGE_PATH"`
}
MediaStorageConfig selects the blob backend.
type MetricsConfig ¶
type MetricsConfig struct {
// Enabled controls whether Prometheus metrics are collected and exposed
// Default: false
Enabled bool `yaml:"enabled" env:"METRICS_ENABLED"`
// Endpoint is the HTTP path where metrics are exposed
// Default: "/metrics"
Endpoint string `yaml:"endpoint" env:"METRICS_ENDPOINT"`
}
MetricsConfig holds observability configuration for Prometheus metrics
type ModelCacheConfig ¶
type ModelCacheConfig struct {
RefreshInterval int `yaml:"refresh_interval" env:"CACHE_REFRESH_INTERVAL"`
// RecheckInterval is how often (seconds) providers whose latest refresh
// failed are re-checked, so outage recovery is detected without waiting
// for the next full refresh. Zero or negative disables the fast recheck.
RecheckInterval int `yaml:"recheck_interval" env:"PROVIDER_RECHECK_INTERVAL"`
ModelList ModelListConfig `yaml:"model_list"`
Local *LocalCacheConfig `yaml:"local"`
Redis *RedisModelConfig `yaml:"redis"`
}
ModelCacheConfig holds cache configuration for model registry. At least one of Local or Redis must be non-nil. When both are set, Redis is preferred and Local is the fallback if Redis is unreachable.
type ModelFilter ¶ added in v0.1.82
type ModelFilter struct {
// Include keeps only models matching at least one pattern. Empty keeps all.
Include []string `yaml:"include"`
// Exclude drops models matching any pattern. It is applied after Include.
Exclude []string `yaml:"exclude"`
// MaxPricePerMtok caps a model's highest per-million-token rate — the
// larger of its input and output rate. A model with no known pricing is
// dropped while the cap is set: a price cap that lets unpriced models
// through is not a cap. Nil disables price filtering.
MaxPricePerMtok *float64 `yaml:"max_price_per_mtok"`
}
ModelFilter narrows a provider's discovered model inventory. It is declared under providers.<name>.model_filter and applied after metadata enrichment, so price rules see both registry pricing and whatever the provider reported.
providers:
openrouter:
model_filter:
include: ["*:free"] # keep only matching models
exclude: ["*-preview"] # then drop matching models
max_price_per_mtok: 0 # drop models priced above the cap
Patterns are globs matched case-insensitively against the raw provider model ID: `*` matches any run of characters (including `/`, unlike shell globs, so `*:free` matches `deepseek/deepseek-r1:free`) and `?` matches exactly one.
func (ModelFilter) Empty ¶ added in v0.1.82
func (f ModelFilter) Empty() bool
Empty reports whether the filter would keep every model.
func (ModelFilter) Normalize ¶ added in v0.1.82
func (f ModelFilter) Normalize() ModelFilter
Normalize trims patterns and drops empty ones.
func (ModelFilter) Validate ¶ added in v0.1.82
func (f ModelFilter) Validate(field string) error
Validate rejects a price cap that cannot express a real limit. NaN silently rejects every model, +Inf silently disables the cap, and a negative cap can never be met — each turns a cost control into something other than what was written, so they fail startup rather than mislead.
type ModelListConfig ¶
type ModelListConfig struct {
// URL is the HTTP(S) URL to fetch models.json from (empty = disabled)
URL string `yaml:"url" env:"MODEL_LIST_URL"`
}
ModelListConfig holds configuration for fetching the external model metadata registry.
type ModelsConfig ¶
type ModelsConfig struct {
// EnabledByDefault controls whether provider models are available
// when no persisted user-path access override exists.
// Default: true.
EnabledByDefault bool `yaml:"enabled_by_default" env:"MODELS_ENABLED_BY_DEFAULT"`
// KeepOnlyAliasesAtModelsEndpoint controls whether GET /v1/models hides
// provider models and returns only alias-projected model entries.
// Default: false.
KeepOnlyAliasesAtModelsEndpoint bool `yaml:"keep_only_aliases_at_models_endpoint" env:"KEEP_ONLY_ALIASES_AT_MODELS_ENDPOINT"`
// VLLMDiscoveryCompat makes GET /v1/models advertise every model the way a
// vLLM runtime does, so a client whose model discovery only understands
// vLLM picks the gateway's models up instead of requiring a hand-written
// list: owned_by becomes "vllm" and each entry carries max_model_len, from
// the provider's own report, else the model's context window, else 0 when
// the limit is unknown. The field is always present because those clients
// decode the listing against a schema that requires it: omitting it for one
// model fails the response and hides every other model behind it. It is a
// lie about the owner, so it stays opt-in and only for deployments whose
// consumers need it.
// Default: false.
VLLMDiscoveryCompat bool `yaml:"vllm_discovery_compat" env:"MODELS_VLLM_DISCOVERY_COMPAT"`
// UnqualifiedModelIDsAtModelsEndpoint controls whether GET /v1/models
// returns bare model IDs (gpt-5) instead of provider-qualified ones
// (openai/gpt-5). When two providers expose the same model ID, only the
// entry for the provider an unqualified request routes to is listed.
// Default: false.
UnqualifiedModelIDsAtModelsEndpoint bool `yaml:"unqualified_model_ids_at_models_endpoint" env:"UNQUALIFIED_MODEL_IDS_AT_MODELS_ENDPOINT"`
// ConfiguredProviderModelsMode controls how providers.<name>.models and
// provider *_MODELS env vars affect the provider model inventory.
// Supported values: "fallback", "allowlist", "merge". Default: "fallback".
ConfiguredProviderModelsMode ConfiguredProviderModelsMode `yaml:"configured_provider_models_mode" env:"CONFIGURED_PROVIDER_MODELS_MODE"`
}
ModelsConfig holds global model access defaults.
type MongoDBStorageConfig ¶
type MongoDBStorageConfig struct {
// URL is the connection string; a database named in its path is honored
// (e.g., mongodb://localhost:27017/gomodel)
URL string `yaml:"url" env:"MONGODB_URL"`
// Database overrides the database named in the URL (default: gomodel)
Database string `yaml:"database" env:"MONGODB_DATABASE"`
}
MongoDBStorageConfig holds MongoDB-specific storage configuration
type OpenTelemetryConfig ¶ added in v0.1.84
type OpenTelemetryConfig struct {
// Enabled turns on OpenTelemetry export for inbound HTTP requests and
// outbound provider calls.
// Default: false
Enabled bool `yaml:"enabled" env:"OTEL_ENABLED"`
// ServiceName is the service.name resource attribute (OTEL_SERVICE_NAME).
// Default: "gomodel"
ServiceName string `yaml:"service_name"`
// ResourceAttributes adds resource attributes such as
// deployment.environment (OTEL_RESOURCE_ATTRIBUTES).
ResourceAttributes map[string]string `yaml:"resource_attributes"`
// Endpoint is the OTLP collector endpoint (OTEL_EXPORTER_OTLP_ENDPOINT).
// Default: "http://localhost:4318" for http/protobuf, "localhost:4317" for grpc
Endpoint string `yaml:"endpoint"`
// Protocol is "http/protobuf" or "grpc" (OTEL_EXPORTER_OTLP_PROTOCOL).
// Default: "http/protobuf"
Protocol string `yaml:"protocol"`
// Headers are sent with every export request, for example an
// authorization header for a hosted backend (OTEL_EXPORTER_OTLP_HEADERS).
Headers map[string]string `yaml:"headers"`
// TracesExporter is "otlp" or "none" (OTEL_TRACES_EXPORTER).
// Default: "otlp"
TracesExporter string `yaml:"traces_exporter"`
// MetricsExporter is "otlp" or "none" (OTEL_METRICS_EXPORTER).
// Default: "otlp"
MetricsExporter string `yaml:"metrics_exporter"`
// Sampler selects the trace sampler (OTEL_TRACES_SAMPLER), for example
// "parentbased_traceidratio" with SamplerArg "0.1".
// Default: "parentbased_always_on"
Sampler string `yaml:"sampler"`
// SamplerArg is the sampler argument (OTEL_TRACES_SAMPLER_ARG).
SamplerArg string `yaml:"sampler_arg"`
// Propagators is the comma-separated context propagator list
// (OTEL_PROPAGATORS): tracecontext, baggage, b3, b3multi, jaeger,
// ottrace, or none.
// Default: "tracecontext,baggage"
Propagators string `yaml:"propagators"`
// CaptureMessageContent records prompts and completions on GenAI spans
// (OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT). Content then
// leaves the gateway with every exported trace.
// Default: false
CaptureMessageContent bool `yaml:"capture_message_content"`
}
OpenTelemetryConfig configures OTLP trace and metric export.
Only Enabled is a GoModel setting. The other fields mirror the standard OTEL_* environment variables that the OpenTelemetry SDK reads by itself, so a YAML-first deployment does not have to reach for the environment for the common settings. An OTEL_* variable that is already set in the environment wins over the YAML value, like every other GoModel setting; anything not listed here (per-signal endpoints, timeouts, compression, batch sizes, …) is available through its OTEL_* variable.
func (OpenTelemetryConfig) Environment ¶ added in v0.1.84
func (c OpenTelemetryConfig) Environment() map[string]string
Environment returns the OTEL_* variables that the configured fields stand for. Unset fields are omitted so the SDK applies its own defaults.
type PGVectorConfig ¶
type PGVectorConfig struct {
URL string `yaml:"url"`
Table string `yaml:"table"`
Dimension int `yaml:"dimension"`
}
PGVectorConfig holds connection configuration for the pgvector vector store.
type PineconeConfig ¶
type PineconeConfig struct {
Host string `yaml:"host"`
APIKey string `yaml:"api_key"`
Namespace string `yaml:"namespace"`
Dimension int `yaml:"dimension"`
}
PineconeConfig holds connection configuration for Pinecone (data-plane HTTP API).
type PluginFileConfig ¶ added in v0.1.90
type PluginFileConfig struct {
// File is the .so path: absolute, or relative to one of SearchPaths.
File string `yaml:"file"`
// SHA256 is an optional hex digest of the file. When set, a mismatch
// fails startup.
SHA256 string `yaml:"sha256"`
}
PluginFileConfig identifies one shared object to load.
type PluginsConfig ¶ added in v0.1.90
type PluginsConfig struct {
// Enabled turns the plugin system on: the built-in and loaded plugin
// types, the guardrails built from them, the routing-strategy plugins
// virtual models can select, and the /admin/plugins and /admin/guardrails
// endpoints. Guardrails need plugins, so GUARDRAILS_ENABLED=true enables
// it implicitly.
// Default: false
Enabled bool `yaml:"enabled" env:"PLUGINS_ENABLED"`
// SearchPaths lists directories searched for relative plugin files.
// A relative file must resolve inside one of these directories; the first
// match wins. Absolute file paths are used as-is.
// Default: empty (no .so loading)
SearchPaths []string `yaml:"search_paths" env:"PLUGINS_SEARCH_PATHS"`
// Load lists the shared objects to open at startup. Each file exports a
// GoModelPlugin symbol (see the pluginapi package). A file that cannot be
// resolved, verified, or opened is a startup error.
// Env: PLUGINS_LOAD is a comma-separated list of file names, each
// optionally "file=sha256hex" to pin the digest, and REPLACES this list
// when set (env > config), like every other env-configurable value. It
// exists so an install can load plugins without a config.yaml.
Load []PluginFileConfig `yaml:"load"`
}
PluginsConfig controls the plugin system and the loading of plugin shared objects (.so files).
A shared object is trusted code: loading one is equivalent to changing the binary. Keep search_paths root-owned and pin files with sha256 in production. Loading requires a cgo-enabled build of GoModel on Linux, macOS, or FreeBSD (the gomodel:<version>-plugins image); the default static binary reports a clear error for any configured plugin file.
type PostgreSQLStorageConfig ¶
type PostgreSQLStorageConfig struct {
// URL is the connection string (e.g., postgres://user:pass@localhost/dbname)
URL string `yaml:"url" env:"POSTGRES_URL"`
// MaxConns is the maximum connection pool size (default: 10)
MaxConns int `yaml:"max_conns" env:"POSTGRES_MAX_CONNS"`
}
PostgreSQLStorageConfig holds PostgreSQL-specific storage configuration
type PricingConfig ¶ added in v0.1.108
type PricingConfig struct {
// MarkupsEnabled turns on markups and billed cost: usage rows record a
// billed cost and the dashboard shows it. While off, Markups and
// BillCacheHits are ignored and no billed cost is recorded.
// Default: false
MarkupsEnabled bool `yaml:"markups_enabled" env:"PRICING_MARKUPS_ENABLED"`
// Markups maps a model selector to a percentage added on top of the
// provider cost: "/" (all models), "openai/" (one provider instance),
// "gpt-5" (a model on any provider) or "openai/gpt-5". The most specific
// selector wins; markups never stack. 20 bills $1.20 for $1.00 of cost.
// Markups are declared in config.yaml only.
// Default: none (billed cost equals provider cost).
Markups map[string]float64 `yaml:"markups"`
// UserPathMarkups gives a customer (a user-path subtree) its own markups,
// keyed by user path and then by the same selectors as Markups. The
// deepest configured path covering the request's user path that has a
// matching selector wins; otherwise shallower paths, then Markups, apply.
// Requires GoModel Pro (the customer_markups capability).
// Markups are declared in config.yaml only.
// Default: none.
UserPathMarkups map[string]map[string]float64 `yaml:"user_path_markups"`
// BillCacheHits controls whether responses served from the gateway
// response cache are billed at what the same call would cost when the hit
// is served, plus markup. False bills them at zero. Provider prompt caching
// is unaffected: its cached-token cost is always billed.
// Default: true
BillCacheHits bool `yaml:"bill_cache_hits" env:"PRICING_BILL_CACHE_HITS"`
}
PricingConfig holds how tracked provider cost is turned into the amount billed to the caller. It never changes the provider cost itself, so budgets and cost reports keep measuring upstream spend.
type QdrantConfig ¶
type QdrantConfig struct {
URL string `yaml:"url"`
Collection string `yaml:"collection"`
APIKey string `yaml:"api_key"`
}
QdrantConfig holds connection configuration for the Qdrant vector store.
type RateLimitModelConfig ¶
type RateLimitModelConfig struct {
Model string `yaml:"model"`
Limits []RateLimitRuleConfig `yaml:"limits"`
}
RateLimitModelConfig declares one or more rate limit rules for a model.
type RateLimitProviderConfig ¶
type RateLimitProviderConfig struct {
Name string `yaml:"name"`
Limits []RateLimitRuleConfig `yaml:"limits"`
}
RateLimitProviderConfig declares one or more rate limit rules for a provider.
type RateLimitRuleConfig ¶
type RateLimitRuleConfig struct {
// Period accepts minute, hour, day, or concurrent. The resolved period is
// persisted as PeriodSeconds in the database.
Period string `yaml:"period" json:"period"`
// PeriodSeconds can be set directly instead of Period for custom windows.
// 0 means the concurrent (in-flight) limit.
PeriodSeconds *int64 `yaml:"period_seconds" json:"period_seconds"`
// MaxRequests caps requests per period, or in-flight requests for the
// concurrent period.
MaxRequests *int64 `yaml:"max_requests" json:"max_requests"`
// MaxTokens caps total tokens per period. Not valid for the concurrent
// period. Requires usage tracking to be enforced.
MaxTokens *int64 `yaml:"max_tokens" json:"max_tokens"`
// PerChild is accepted only in the JSON-array environment-variable form.
// YAML keeps this setting on the enclosing user-path entry.
PerChild bool `yaml:"-" json:"per_child,omitempty"`
}
RateLimitRuleConfig declares the limits for one period. The json tags support the JSON-array form of SET_RATE_LIMIT_* env values.
type RateLimitUserPathConfig ¶
type RateLimitUserPathConfig struct {
Path string `yaml:"path"`
PerChild bool `yaml:"per_child"`
Limits []RateLimitRuleConfig `yaml:"limits"`
}
RateLimitUserPathConfig declares one or more rate limit rules for a user path.
type RateLimitsConfig ¶
type RateLimitsConfig struct {
// Enabled controls whether rate limit checks are active.
// Default: true. With no rules configured the check is a no-op.
Enabled bool `yaml:"enabled" env:"RATE_LIMITS_ENABLED"`
// FlushInterval is how often live request/token windows are written to
// storage, in seconds. Default 1. 0 disables the periodic loop; Start
// still loads and Close of an active generation still writes once.
FlushInterval int `yaml:"flush_interval" env:"RATE_LIMITS_FLUSH_INTERVAL"`
// UserPaths declares rate limit rules by tracked user path.
UserPaths []RateLimitUserPathConfig `yaml:"user_paths"`
// Providers declares rate limit rules by configured provider name.
// Provider rules cap all traffic routed to that provider instance; load
// balancing and failover skip a saturated provider while capacity exists
// elsewhere.
Providers []RateLimitProviderConfig `yaml:"providers"`
// Models declares rate limit rules by model. A provider-qualified subject
// ("openai/gpt-4o") caps one provider's model; a bare id ("gpt-4o") caps
// the model across every provider.
Models []RateLimitModelConfig `yaml:"models"`
}
RateLimitsConfig holds request, token, and concurrency limits scoped to user paths (consumers), providers, and models.
type RawCircuitBreakerConfig ¶
type RawCircuitBreakerConfig struct {
FailureOnStatuses []string `yaml:"failure_on_statuses"`
Scope *string `yaml:"scope"`
Enabled *bool `yaml:"enabled"`
FailureThreshold *int `yaml:"failure_threshold"`
SuccessThreshold *int `yaml:"success_threshold"`
Timeout *time.Duration `yaml:"timeout"`
SlowCallThreshold *time.Duration `yaml:"slow_call_threshold"`
}
RawCircuitBreakerConfig holds optional per-provider circuit breaker overrides from YAML. Nil fields inherit from the global CircuitBreakerConfig.
type RawProviderConfig ¶
type RawProviderConfig struct {
Type string `yaml:"type"`
APIKey string `yaml:"api_key"`
// APIKeys lists additional API keys for this provider. When more than one
// key is resolved (counting APIKey), identified sessions stay on one key by
// default while sessionless requests rotate round robin. Set it via
// `api_keys:` or the `<PROVIDER>_API_KEY_<n>` env vars.
APIKeys []string `yaml:"api_keys"`
// SessionStickyKeys defaults to true. Set false to restore round-robin key
// selection for every request, including requests carrying a session ID.
SessionStickyKeys *bool `yaml:"session_sticky_keys"`
BaseURL string `yaml:"base_url"`
APIVersion string `yaml:"api_version"`
Backend string `yaml:"backend"`
AuthType string `yaml:"auth_type"`
APIMode string `yaml:"api_mode"`
VertexProject string `yaml:"vertex_project"`
VertexLocation string `yaml:"vertex_location"`
ServiceAccountFile string `yaml:"service_account_file"`
ServiceAccountJSON string `yaml:"service_account_json"`
ServiceAccountJSONBase64 string `yaml:"service_account_json_base64"`
GCPScope string `yaml:"gcp_scope"`
// ProxyURL sends this provider's upstream traffic through an HTTP, HTTPS,
// or SOCKS5 proxy ("http://proxy:3128", "socks5://user:pass@host:1080").
// Empty keeps the process-wide HTTP_PROXY / HTTPS_PROXY / NO_PROXY
// behaviour. Set it via `proxy_url:` or `<PROVIDER>_PROXY_URL`.
ProxyURL string `yaml:"proxy_url"`
// InferenceObjective is the trusted llm-d InferenceObjective name injected
// into outbound requests. It is ignored by provider types other than llmd.
InferenceObjective string `yaml:"inference_objective"`
// FairnessFromUserPath controls whether the llmd provider derives its
// fairness ID from GoModel's effective (authenticated) user path. It
// defaults to true; nil preserves that default.
FairnessFromUserPath *bool `yaml:"fairness_from_user_path"`
Models []RawProviderModel `yaml:"models"`
// ModelFilter narrows the provider's model inventory to the models that
// match its patterns and price cap. It applies to the final inventory, so
// it also narrows models added by `models` in merge or allowlist mode.
ModelFilter ModelFilter `yaml:"model_filter"`
Resilience *RawResilienceConfig `yaml:"resilience"`
// WorkloadIdentity authenticates with a short-lived token exchanged for
// the workload's platform identity token instead of a static API key.
// Supported by the openai and anthropic types. An API key, when also set,
// wins, matching the official SDKs.
WorkloadIdentity WorkloadIdentityConfig `yaml:"workload_identity"`
}
RawProviderConfig is the YAML-sourced provider configuration before env var overrides, credential filtering, or resilience merging. Exported so the providers package can resolve it into a fully-configured ProviderConfig.
type RawProviderModel ¶
type RawProviderModel struct {
ID string `yaml:"id"`
Metadata *core.ModelMetadata `yaml:"metadata,omitempty"`
}
RawProviderModel is a single entry under providers.<name>.models. It supports two YAML shapes so operators can opt into rich metadata without churning simple configs:
models:
- some-model-id # bare string
- id: local-model # mapping with optional metadata
metadata:
context_window: 131072
capabilities:
tools: true
Metadata is merged onto whatever the remote model registry supplies, with config-declared fields taking precedence. This lets local providers (Ollama, custom OpenAI-compatible endpoints) advertise their context windows, pricing, and capabilities via /v1/models even when the remote registry has no entry.
func (*RawProviderModel) UnmarshalYAML ¶
func (m *RawProviderModel) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML accepts either a bare string (model ID) or a mapping with id and metadata.
type RawResilienceConfig ¶
type RawResilienceConfig struct {
Retry *RawRetryConfig `yaml:"retry"`
CircuitBreaker *RawCircuitBreakerConfig `yaml:"circuit_breaker"`
}
RawResilienceConfig holds optional per-provider resilience overrides from YAML. Nil fields inherit from the global ResilienceConfig.
type RawRetryConfig ¶
type RawRetryConfig struct {
RetryOnStatuses []string `yaml:"retry_on_statuses"`
MaxRetries *int `yaml:"max_retries"`
InitialBackoff *time.Duration `yaml:"initial_backoff"`
MaxBackoff *time.Duration `yaml:"max_backoff"`
BackoffFactor *float64 `yaml:"backoff_factor"`
JitterFactor *float64 `yaml:"jitter_factor"`
}
RawRetryConfig holds optional per-provider retry overrides from YAML. Nil fields inherit from the global RetryConfig.
type RedisModelConfig ¶
type RedisModelConfig struct {
URL string `yaml:"url" env:"REDIS_URL"`
Key string `yaml:"key" env:"REDIS_KEY_MODELS"`
TTL int `yaml:"ttl" env:"REDIS_TTL_MODELS"`
}
RedisModelConfig holds Redis connection configuration for the model registry cache.
type RedisResponseConfig ¶
type RedisResponseConfig struct {
URL string `yaml:"url"`
Key string `yaml:"key"`
TTL int `yaml:"ttl"`
}
RedisResponseConfig holds Redis connection configuration for the response cache. Uses separate env vars from RedisModelConfig for key and TTL to allow independent configuration. The URL is shared via REDIS_URL to simplify single-Redis deployments; use YAML config if different Redis instances are needed for model and response caches. Env vars are applied in Load via applyResponseSimpleEnv, only when cache.response.simple is present (see RESPONSE_CACHE_SIMPLE_ENABLED for env-only opt-in without YAML).
type ResilienceConfig ¶
type ResilienceConfig struct {
Retry RetryConfig `yaml:"retry"`
CircuitBreaker CircuitBreakerConfig `yaml:"circuit_breaker"`
}
ResilienceConfig holds resolved resilience settings (retry and circuit breaker).
type ResolvedEntity ¶ added in v0.1.101
type ResolvedEntity struct {
// contains filtered or unexported fields
}
ResolvedEntity holds the resolved secret fields of one dashboard-managed entity (a provider credential, an MCP server, a guardrail), as returned by ResolveEntity. Nothing is recorded for rotation until Record is called.
func (*ResolvedEntity) Record ¶ added in v0.1.101
func (r *ResolvedEntity) Record()
Record makes these fields the ones rotation compares against for the entity, replacing whatever it recorded before: a field that no longer holds a reference stops being watched. Safe on a nil receiver.
func (*ResolvedEntity) Value ¶ added in v0.1.101
func (r *ResolvedEntity) Value(field string) string
Value returns the resolved value of field, or "" when it was not resolved.
type ResponseCacheConfig ¶
type ResponseCacheConfig struct {
Simple *SimpleCacheConfig `yaml:"simple"`
Semantic *SemanticCacheConfig `yaml:"semantic"`
}
ResponseCacheConfig holds configuration for response cache middleware.
type RetryConfig ¶
type RetryConfig struct {
// RetryOnStatuses uses defaults when nil; an empty list disables status triggers.
RetryOnStatuses []string `yaml:"retry_on_statuses" env:"RETRY_ON_STATUSES"`
MaxRetries int `yaml:"max_retries" env:"RETRY_MAX_RETRIES"`
InitialBackoff time.Duration `yaml:"initial_backoff" env:"RETRY_INITIAL_BACKOFF"`
MaxBackoff time.Duration `yaml:"max_backoff" env:"RETRY_MAX_BACKOFF"`
BackoffFactor float64 `yaml:"backoff_factor" env:"RETRY_BACKOFF_FACTOR"`
JitterFactor float64 `yaml:"jitter_factor" env:"RETRY_JITTER_FACTOR"`
}
RetryConfig holds resolved retry settings for an LLM client. This is the canonical type shared between config and llmclient.
func DefaultRetryConfig ¶
func DefaultRetryConfig() RetryConfig
DefaultRetryConfig returns the default retry settings.
type SQLiteStorageConfig ¶
type SQLiteStorageConfig struct {
// Path is the database file path. Default: ./data/gomodel.db when a
// ./data directory exists, otherwise the OS per-user data directory
// (e.g. ~/.local/share/gomodel/gomodel.db).
Path string `yaml:"path" env:"SQLITE_PATH"`
}
SQLiteStorageConfig holds SQLite-specific storage configuration
type SecretDestination ¶ added in v0.1.101
type SecretDestination struct {
// Field is the field within the entity, for example "url" or "base_url".
Field string
Stored, Saved string
}
SecretDestination is a field of an admin-saved entity that decides where the entity sends its secrets, such as an upstream URL, with its stored and saved values.
type SecretError ¶ added in v0.1.100
type SecretError struct {
// Field is the configuration path or environment variable holding the
// reference, for example "providers.openai.api_key". It may be empty.
Field string
// Scheme is the reference's scheme when GoModel knows it: a built-in
// scheme, one an extension registered, or one it has a hint for. It is
// empty for any other scheme, whose name is text taken from the value,
// which may be a literal secret that only looks like a reference.
Scheme string
Err error
}
SecretError reports a secret reference that could not be resolved. It names where the reference was found and its scheme, never the value.
func (*SecretError) Error ¶ added in v0.1.100
func (e *SecretError) Error() string
func (*SecretError) Unwrap ¶ added in v0.1.100
func (e *SecretError) Unwrap() error
type SecretKey ¶ added in v0.1.101
type SecretKey struct {
// Entity is the kind of entity: "provider_credentials", "mcp_servers",
// or "guardrail_definitions".
Entity string
// ID is the entity's name.
ID string
// Field is the field within the entity, for example "api_keys[0]",
// "headers.Authorization", or "config.api_key".
Field string
}
SecretKey names one secret field of a dashboard-managed entity, for a SecretWriter to derive where it stores the value. None of it is secret.
type SecretNotifier ¶ added in v0.1.101
type SecretNotifier struct {
// contains filtered or unexported fields
}
SecretNotifier carries change notifications from every generation's Secrets to whichever generation is serving. Notifications coalesce: any number of them before the serving generation receives is one pending check.
The process creates one and hands it to each generation's Secrets with SetNotifier, so an extension that keeps notifying the Secrets it last saw still reaches the serving generation when a reload of a newer one was abandoned. A Secrets without a notifier has a private one.
func NewSecretNotifier ¶ added in v0.1.101
func NewSecretNotifier() *SecretNotifier
NewSecretNotifier returns a notifier with no check pending.
func (*SecretNotifier) C ¶ added in v0.1.101
func (n *SecretNotifier) C() <-chan struct{}
C returns the channel a pending check is delivered on. Only the serving generation should receive from it.
func (*SecretNotifier) Notify ¶ added in v0.1.101
func (n *SecretNotifier) Notify()
Notify records a pending check without blocking.
type SecretRecheck ¶ added in v0.1.101
type SecretRecheck struct {
// contains filtered or unexported fields
}
SecretRecheck is the outcome of re-resolving every recorded reference. It holds the new values of the fields that changed only until it is dropped.
func (*SecretRecheck) Commit ¶ added in v0.1.101
func (r *SecretRecheck) Commit()
Commit records the new values as the ones in use, so the next Recheck compares against them. Call it once the change has been applied; a change that was not applied stays pending and is reported again.
func (*SecretRecheck) Fields ¶ added in v0.1.101
func (r *SecretRecheck) Fields() []string
Fields returns the paths of the fields whose resolved value changed, sorted.
func (*SecretRecheck) Select ¶ added in v0.1.101
func (r *SecretRecheck) Select(keep func(field string) bool) *SecretRecheck
Select returns the part of the recheck whose fields keep reports true. Committing it commits only those fields.
type SecretResolver ¶ added in v0.1.100
type SecretResolver interface {
ResolveSecret(ctx context.Context, reference string) (string, error)
}
SecretResolver resolves the reference part of ${scheme:reference}. Implementations must be safe for concurrent use and must never include the resolved value in an error. ResolveSecret must return once ctx is done: each call gets a deadline, and one that ignores it holds up whatever is resolving, such as startup, a reload, or a dashboard save.
type SecretResolverFunc ¶ added in v0.1.100
SecretResolverFunc adapts a function to SecretResolver.
func (SecretResolverFunc) ResolveSecret ¶ added in v0.1.100
ResolveSecret calls f(ctx, reference).
type SecretWriter ¶ added in v0.1.101
type SecretWriter interface {
// WriteSecret stores value as a new secret and returns the
// ${scheme:reference} that resolves to it. It must not change what an
// existing reference resolves to: a save can still fail after the write,
// and the stored entity then keeps using its old reference. Return a
// distinct reference per write, for example one pinned to the version
// written. Core never deletes a reference the stored entity still holds.
WriteSecret(ctx context.Context, key SecretKey, value string) (reference string, err error)
// DeleteSecret removes a secret WriteSecret created.
DeleteSecret(ctx context.Context, reference string) error
// OwnsReference reports whether reference is one WriteSecret created,
// so core never deletes a secret an operator referenced by hand.
OwnsReference(reference string) bool
}
SecretWriter stores secrets entered through the admin API in an external secret manager, so only a reference to them is persisted. An extension registers one with Secrets.SetWriter; core ships none.
Implementations must be safe for concurrent use and must never include a secret value in an error.
type Secrets ¶ added in v0.1.100
type Secrets struct {
// contains filtered or unexported fields
}
Secrets resolves ${scheme:reference} secret references for one configuration generation. The env and file schemes are built in; extensions add more with Register. A nil *Secrets resolves the built-in schemes only. Safe for concurrent use.
func NewSecrets ¶ added in v0.1.100
func NewSecrets() *Secrets
NewSecrets returns a Secrets with only the built-in schemes registered.
func (*Secrets) Changes ¶ added in v0.1.101
func (s *Secrets) Changes() <-chan struct{}
Changes returns the channel NotifyChanged signals. Only the serving generation receives from it; a nil *Secrets returns a nil channel, which never fires.
func (*Secrets) EntityOwnsAny ¶ added in v0.1.101
EntityOwnsAny reports whether entity recorded any of fields for rotation (see Record). It matches exact field paths, so the entity "pii" never owns a field of "pii.team" although its paths share the prefix "guardrail_definitions.pii.".
func (*Secrets) ForgetEntity ¶ added in v0.1.101
ForgetEntity stops rotation from watching the fields entity recorded, for an entity that was deleted or is no longer installed.
func (*Secrets) HasReference ¶ added in v0.1.100
HasReference reports whether value contains at least one secret reference. An escaped $${...} is not a reference.
func (*Secrets) NotifyChanged ¶ added in v0.1.101
func (s *Secrets) NotifyChanged()
NotifyChanged tells core that a secret backend may hold new values. It never blocks, and calls that arrive before core gets round to checking are coalesced into one check. Core then re-resolves every recorded reference: when only provider API keys changed they are swapped in place, any other change reloads the configuration as SIGHUP would.
Extensions call it when their backend reports a new version. Each configuration generation has its own Secrets, but the gateway shares one SecretNotifier between them, so calling it on any generation's Secrets reaches the generation that is serving, including after a reload was rejected. The serving generation re-checks with its own Secrets, the one whose resolvers it was built with. Safe on a nil *Secrets.
func (*Secrets) Recheck ¶ added in v0.1.101
func (s *Secrets) Recheck(ctx context.Context) (*SecretRecheck, error)
Recheck re-resolves every recorded reference with the resolvers registered now and reports the fields whose value changed. It changes nothing: Commit does that once the caller has applied the change. Every resolution error is returned, joined, as *SecretError values naming field and scheme.
func (*Secrets) Register ¶ added in v0.1.100
func (s *Secrets) Register(scheme string, r SecretResolver) error
Register adds a resolver for scheme. The built-in env and file schemes are reserved, and a scheme can be registered once.
func (*Secrets) ReleaseSecrets ¶ added in v0.1.101
ReleaseSecrets deletes, through the registered writer, every reference in the values of previous that the writer owns and no value of current still contains: the secrets of a deleted entity, or of a field whose reference was replaced. A reference counts wherever it appears in a value, alone or inside longer text. Call it after the change is committed. Every failure is returned, joined; none of them undoes the change.
func (*Secrets) Resolve ¶ added in v0.1.100
Resolve replaces every secret reference in value with its resolved value and turns each $${ escape into a literal ${. Other text, including a legacy ${VAR} left by environment expansion, is kept as is. Resolved values are never scanned again.
func (*Secrets) ResolveEntity ¶ added in v0.1.101
func (s *Secrets) ResolveEntity(ctx context.Context, entity string, fields map[string]string) (*ResolvedEntity, error)
ResolveEntity resolves the secret fields of one dashboard-managed entity as a unit. entity identifies it ("provider_credentials.openai"); fields maps each field path ("provider_credentials.openai.api_keys[0]") to its stored value. Resolvers see the field path, as with ResolveFields.
The first field that fails returns its *SecretError, naming the field and scheme, and nothing is recorded. On success, call Record once the entity is installed so rotation tracks exactly the values it runs on.
func (*Secrets) ResolveFields ¶ added in v0.1.100
ResolveFields resolves the secret references in every string reachable from target, a pointer or a map: struct fields, slices, maps, and interface values such as map[string]any. yaml.Node values are skipped. Errors name the field by its YAML path below path, for example "providers.openai.api_key".
Values are resolved in place, but slices and maps reached through a settable value are replaced by resolved copies, so data shared with another value is not rewritten. Call it once per value: resolved values must not be scanned again.
func (*Secrets) SetNotifier ¶ added in v0.1.101
func (s *Secrets) SetNotifier(n *SecretNotifier)
SetNotifier routes NotifyChanged to n, which the process shares across generations. Call it before the generation starts watching Changes.
func (*Secrets) SetWriter ¶ added in v0.1.101
func (s *Secrets) SetWriter(w SecretWriter)
SetWriter registers the writer literal secrets saved through the admin API are stored with. Like Register, it applies to one configuration generation. A nil w removes the writer.
func (*Secrets) StoreSecret ¶ added in v0.1.101
func (s *Secrets) StoreSecret(ctx context.Context, key SecretKey, value string, held []string) (string, error)
StoreSecret returns what to persist for a secret field saved through the admin API. With a writer registered, a non-empty literal value is written through it and the reference it returns is persisted instead. The writer receives the value the field would resolve to without one: each $${ escape is already turned into ${, since a resolved value is never scanned again. A value that is empty or already holds a reference is returned unchanged, and so is every value when no writer is registered. The writer must return exactly one ${scheme:reference} and nothing else.
held lists the values of the entity as currently stored. A reference the writer owns, alone or inside a longer value, that no value of held contains is rejected with a *SecretError wrapping ErrSecretNotHeld, so a save never persists a reference whose secret was released.
In a context from RestrictSecretReferences, any reference no value of held contains is rejected with a *SecretError wrapping ErrSecretReferenceRestricted.
type SemanticCacheConfig ¶
type SemanticCacheConfig struct {
Enabled *bool `yaml:"enabled"`
SimilarityThreshold float64 `yaml:"similarity_threshold"`
TTL *int `yaml:"ttl"`
MaxConversationMessages *int `yaml:"max_conversation_messages"`
ExcludeSystemPrompt bool `yaml:"exclude_system_prompt"`
Embedder EmbedderConfig `yaml:"embedder"`
VectorStore VectorStoreConfig `yaml:"vector_store"`
}
SemanticCacheConfig holds configuration for the semantic (vector-similarity) response cache. When the semantic block is omitted from config.yaml, this layer stays off unless SEMANTIC_CACHE_ENABLED=true is set. Omitted enabled (nil) means true whenever the semantic block exists. Tuning env vars are applied in Load via applyResponseSemanticEnv when this block exists.
type ServerConfig ¶
type ServerConfig struct {
Port string `yaml:"port" env:"PORT"`
BasePath string `yaml:"base_path" env:"BASE_PATH"` // URL path prefix where the app is mounted (e.g., "/g")
MasterKey string `yaml:"master_key" env:"GOMODEL_MASTER_KEY"` // Optional: Master key for authentication
// MasterKeyDisabled turns off master key authentication. Default: false.
// Set it to leave managed keys and any configured authentication extension
// as the only credentials: the master key is forgotten at startup, and the
// gateway then requires a credential on every request instead of falling
// back to unauthenticated access or opening the admin API for bootstrap.
MasterKeyDisabled bool `yaml:"master_key_disabled" env:"MASTER_KEY_DISABLED"`
BodySizeLimit string `yaml:"body_size_limit" env:"BODY_SIZE_LIMIT"` // Max request body size (e.g., "10M", "1024K")
SwaggerEnabled bool `yaml:"swagger_enabled" env:"SWAGGER_ENABLED"` // Whether to expose the Swagger UI at /swagger/index.html
PprofEnabled bool `yaml:"pprof_enabled" env:"PPROF_ENABLED"` // Whether to expose debug profiling routes at /debug/pprof/*
// EnablePassthroughRoutes exposes provider-native passthrough endpoints under
// /p/{provider}/{endpoint}. Default: true.
EnablePassthroughRoutes bool `yaml:"enable_passthrough_routes" env:"ENABLE_PASSTHROUGH_ROUTES"`
// AllowPassthroughV1Alias allows /p/{provider}/v1/... style passthrough routes
// while keeping /p/{provider}/... as the canonical form. Default: true.
AllowPassthroughV1Alias bool `yaml:"allow_passthrough_v1_alias" env:"ALLOW_PASSTHROUGH_V1_ALIAS"`
// UserPathHeader is the inbound HTTP header used to read/write user paths.
// Default: X-GoModel-User-Path.
UserPathHeader string `yaml:"user_path_header" env:"USER_PATH_HEADER"`
// EnabledPassthroughProviders lists the provider types enabled on
// /p/{provider}/... passthrough routes. Default:
// ["openai", "anthropic", "openrouter", "kilo", "zai", "sglang", "vllm", "llamacpp", "llmd", "deepseek", "jev"].
EnabledPassthroughProviders []string `yaml:"enabled_passthrough_providers" env:"ENABLED_PASSTHROUGH_PROVIDERS"`
// RealtimeEnabled exposes the realtime (speech-to-speech) websocket endpoints
// at /v1/realtime and /v1/realtime/translations, their WebRTC signaling
// siblings, and the /p/{provider}/v1/realtime passthrough upgrade.
// Default: true. Only providers implementing realtime accept sessions.
RealtimeEnabled bool `yaml:"realtime_enabled" env:"REALTIME_ENABLED"`
// AuthVerifyEnabled exposes GET /v1/auth/verify, which reports whether the
// API key a request carries authenticates against this gateway. It sits
// outside /admin so it keeps working when the admin API is disabled.
// Default: false — turn it on only when a service in front of the gateway
// needs to validate keys without holding a copy of them.
AuthVerifyEnabled bool `yaml:"auth_verify_enabled" env:"AUTH_VERIFY_ENABLED"`
// PIDFile records the process id of the running gateway so `gomodel --reload`
// can find it. Default: DefaultPIDFilePath(). Set it per instance when
// several gateways share a host, or to "" in config.yaml to write no pid
// file at all, which also disables `--reload` (an empty PID_FILE reads as
// unset, like every other env var here, and keeps the default). Changing it
// needs a restart — it names the process that is already running — so a
// reload only warns about it.
PIDFile string `yaml:"pid_file" env:"PID_FILE"`
// StreamStallTimeout bounds, in seconds, how long a single response write
// on a model interaction route may wait for the client to accept bytes
// before the connection is dropped. It fires only when the client has
// stopped reading (its socket buffer is full), never while the gateway is
// waiting on the provider, so slow models are unaffected. Without it a
// client that stops reading a stream pins a goroutine and the upstream
// provider connection until the provider side times out.
// Default: 60 (DefaultStreamStallTimeoutSeconds). 0 disables the limit.
StreamStallTimeout int `yaml:"stream_stall_timeout" env:"STREAM_STALL_TIMEOUT"`
// TrustedProxies lists the networks your own proxies sit on, enabling
// header-based client addresses everywhere the gateway reports one (audit
// entries, rate limit keys, logs). Entries are CIDR networks, bare
// addresses (a single host), or the presets "loopback" and "private".
//
// When empty (default), the gateway records the address of the socket peer
// that connected to it and ignores every forwarding header. Nothing is
// trusted implicitly, not even loopback: list the hops between your
// clients and the gateway, or name the preset that covers them.
// Example: ["10.42.0.0/16", "loopback"].
// Default: empty (forwarding headers ignored)
TrustedProxies []string `yaml:"trusted_proxies" env:"SERVER_TRUSTED_PROXIES"`
// ClientIPHeader is the header a trusted proxy passes the client address
// in. X-Forwarded-For (the default) carries a chain and is resolved hop by
// hop; any other header (X-Real-IP, CF-Connecting-IP, True-Client-IP)
// carries one address and is taken verbatim, which is the correct reading
// behind an edge like Cloudflare that writes the client itself. Requires
// TrustedProxies. RFC 7239 Forwarded is not supported.
// Default: X-Forwarded-For
ClientIPHeader string `yaml:"client_ip_header" env:"SERVER_CLIENT_IP_HEADER"`
// TrustedHops is how many proxies sit between the client and the gateway,
// selecting the X-Forwarded-For entry at that depth instead of scanning the
// chain against TrustedProxies. Use it when your edge is at a fixed depth
// but rotates through addresses you cannot enumerate; the socket peer must
// still be in TrustedProxies. A chain shorter than this depth falls back to
// the socket peer. Requires TrustedProxies and the default header.
// Default: 0 (scan the chain against TrustedProxies)
TrustedHops int `yaml:"trusted_hops" env:"SERVER_TRUSTED_HOPS"`
// ClientIP is the compiled form of the three settings above, resolved once
// at load. It is not configured directly.
ClientIP ClientIPPolicy `yaml:"-"`
// TLSCertFile and TLSKeyFile serve the listener over HTTPS from a PEM
// certificate (intermediates after the leaf) and its private key. Both or
// neither; unset (default) serves plain HTTP. The files are re-read when
// they change on disk, so rotation (cert-manager, certbot) needs no
// restart or reload. Inbound only: outbound trust is http.tls.
// Default: empty (plain HTTP)
TLSCertFile string `yaml:"tls_cert_file" env:"SERVER_TLS_CERT_FILE"`
TLSKeyFile string `yaml:"tls_key_file" env:"SERVER_TLS_KEY_FILE"`
// TLSClientCAFile requires a client certificate signed by a CA in this PEM
// bundle on every request except /health and /health/ready, which probes
// reach without one (mTLS). The CA is checked during the TLS handshake, so
// a rotated CA applies from the next one; an open connection keeps the
// access it was granted. Requires TLSCertFile and TLSKeyFile; reloaded with
// them.
// Default: empty (no client certificate requested)
TLSClientCAFile string `yaml:"tls_client_ca_file" env:"SERVER_TLS_CLIENT_CA_FILE"`
}
ServerConfig holds HTTP server configuration
func (ServerConfig) Scheme ¶ added in v0.2.0
func (s ServerConfig) Scheme() string
Scheme is the URL scheme the listener serves: "https" or "http".
func (ServerConfig) TLSEnabled ¶ added in v0.2.0
func (s ServerConfig) TLSEnabled() bool
TLSEnabled reports whether the listener serves HTTPS.
type SessionConfig ¶ added in v0.1.63
type SessionConfig struct {
// Enabled turns session identification on. Default: true.
Enabled bool `yaml:"enabled" env:"SESSION_KEEPING_ENABLED"`
// AutoDetect derives a session id from the conversation prefix of chat and
// responses requests when no explicit signal is present. Default: true.
AutoDetect bool `yaml:"auto_detect" env:"SESSION_AUTO_DETECT"`
// BuiltinRules enables the built-in registry of session headers and body
// fields known coding tools send. Default: true.
BuiltinRules bool `yaml:"builtin_rules" env:"SESSION_BUILTIN_RULES"`
// Headers declares additional session id headers, merged over the built-in
// registry (an entry with a built-in header name overrides it).
Headers []SessionHeaderConfig `yaml:"headers,omitempty"`
}
SessionConfig controls session keeping: identifying which requests belong to one client session for sticky load balancing and audit-log grouping.
type SessionHeaderConfig ¶ added in v0.1.63
type SessionHeaderConfig struct {
// Header is the HTTP header name to read the session id from.
Header string `yaml:"header" json:"header"`
// Transform optionally post-processes the header value. Supported:
// "session-uuid" (extract a session UUID from Anthropic metadata-style
// values). Default: use the value as-is.
Transform string `yaml:"transform,omitempty" json:"transform,omitempty"`
}
SessionHeaderConfig declares one header to read session ids from.
type SimpleCacheConfig ¶
type SimpleCacheConfig struct {
Enabled *bool `yaml:"enabled"`
Redis *RedisResponseConfig `yaml:"redis"`
}
SimpleCacheConfig holds configuration for exact-match response caching. When the simple block is omitted from config.yaml, this layer stays off unless RESPONSE_CACHE_SIMPLE_ENABLED=true is set (e.g. Helm without a response-cache YAML fragment). Omitted enabled (nil) means true whenever the simple block exists.
type StorageConfig ¶
type StorageConfig struct {
// Type specifies the storage backend: "sqlite" (default), "postgresql", or "mongodb"
Type string `yaml:"type" env:"STORAGE_TYPE"`
// SQLite configuration
SQLite SQLiteStorageConfig `yaml:"sqlite"`
// PostgreSQL configuration
PostgreSQL PostgreSQLStorageConfig `yaml:"postgresql"`
// MongoDB configuration
MongoDB MongoDBStorageConfig `yaml:"mongodb"`
// EncryptionKey enables encryption at rest for dashboard-managed secrets
// (provider credentials, MCP headers, guardrail secrets). Any string is
// accepted; 32 random bytes in base64 (openssl rand -base64 32) is
// recommended. Losing it makes those secrets unrecoverable.
// Default: empty (secrets are stored in plaintext).
EncryptionKey string `yaml:"encryption_key" env:"GOMODEL_ENCRYPTION_KEY"`
// EncryptionKeyPrevious is the old EncryptionKey during a key rotation.
// It is only used at startup to re-wrap the data key with EncryptionKey.
EncryptionKeyPrevious string `yaml:"encryption_key_previous" env:"GOMODEL_ENCRYPTION_KEY_PREVIOUS"`
}
StorageConfig holds database storage configuration (used by audit logging, usage tracking, future IAM, etc.)
func (StorageConfig) BackendConfig ¶
func (c StorageConfig) BackendConfig() storage.Config
BackendConfig converts the application storage config into the internal storage config.
type SystemPromptSettings ¶
type SystemPromptSettings struct {
// Mode controls how the system prompt is applied: "inject", "override", or "decorator"
// - inject: adds a system message only if none exists
// - override: replaces all existing system messages
// - decorator: prepends to the first existing system message
// Default: "inject"
Mode string `yaml:"mode"`
// Content is the system prompt text to apply
Content string `yaml:"content"`
}
SystemPromptSettings holds the type-specific settings for a system_prompt guardrail.
type TaggingConfig ¶
type TaggingConfig struct {
Headers []TaggingHeaderConfig `yaml:"headers"`
// LiteLLMTagsEnabled turns the tags LiteLLM clients send (the
// x-litellm-tags header, a body "tags" field, and a list metadata.tags)
// into request labels and strips them before the request goes upstream.
// Clients choose these tags, so they can charge any label budget they
// name; turn this off when label budgets must hold per team.
// Default: true.
LiteLLMTagsEnabled bool `yaml:"litellm_tags_enabled" env:"LITELLM_TAGS_ENABLED"`
}
TaggingConfig declares request labelling based on HTTP headers. Headers listed here are read on every request; their values become request labels. Declarative entries override admin-store rows with the same header name and are read-only in the dashboard.
type TaggingHeaderConfig ¶
type TaggingHeaderConfig struct {
// Header is the HTTP header name to read labels from.
Header string `yaml:"header" json:"header"`
// Prefix is optionally trimmed from the front of each label. Trimming only
// affects the extracted label, never the forwarded header value.
Prefix string `yaml:"prefix,omitempty" json:"prefix,omitempty"`
// DoNotPass strips the header before forwarding the request upstream.
// Default: false (headers are passed through as-is).
DoNotPass bool `yaml:"do_not_pass,omitempty" json:"do_not_pass,omitempty"`
// Delimiter splits one header value into multiple labels. Default: ",".
Delimiter string `yaml:"delimiter,omitempty" json:"delimiter,omitempty"`
}
TaggingHeaderConfig declares one header to extract labels from.
type UsageConfig ¶
type UsageConfig struct {
// Enabled controls whether usage tracking is active
// Default: true
Enabled bool `yaml:"enabled" env:"USAGE_ENABLED"`
// EnforceReturningUsageData controls whether to ask streaming providers to return usage data when possible.
// When true, stream_options: {"include_usage": true} is added for provider paths that support it.
// Default: true
EnforceReturningUsageData bool `yaml:"enforce_returning_usage_data" env:"ENFORCE_RETURNING_USAGE_DATA"`
// PricingRecalculationEnabled controls whether the admin pricing recalculation action is available.
// Storage and pricing metadata support are still required; false always disables the feature.
// Default: true
PricingRecalculationEnabled bool `yaml:"pricing_recalculation_enabled" env:"USAGE_PRICING_RECALCULATION_ENABLED"`
// BufferSize is the number of usage entries to buffer before flushing
// Default: 1000
BufferSize int `yaml:"buffer_size" env:"USAGE_BUFFER_SIZE"`
// FlushInterval is how often to flush buffered usage entries (in seconds)
// Default: 5
FlushInterval int `yaml:"flush_interval" env:"USAGE_FLUSH_INTERVAL"`
// RetentionDays is how long to keep usage data (0 = forever)
// Default: 90
RetentionDays int `yaml:"retention_days" env:"USAGE_RETENTION_DAYS"`
}
UsageConfig holds token usage tracking configuration
type UserConfig ¶ added in v0.1.84
type UserConfig struct {
// Path is the user path (group or user) the policy applies to, e.g.
// "/acme/eng". Deeper paths inherit it.
Path string `yaml:"path" json:"path"`
// AllowedModels lists the model selectors requests under Path may use:
// exact "provider/model", provider-wide "provider/*", or model-wide
// "model". Empty means the node itself does not restrict models.
AllowedModels []string `yaml:"allowed_models,omitempty" json:"allowed_models,omitempty"`
// Description is an optional human-readable note.
Description string `yaml:"description,omitempty" json:"description,omitempty"`
}
UserConfig declares one user-path access policy in config.yaml or the USERS env var, so model access can be managed as infrastructure-as-code. A declared policy shadows the admin-store row of the same path and is read-only in the dashboard.
type VectorStoreConfig ¶
type VectorStoreConfig struct {
Type string `yaml:"type"`
Qdrant QdrantConfig `yaml:"qdrant"`
PGVector PGVectorConfig `yaml:"pgvector"`
Pinecone PineconeConfig `yaml:"pinecone"`
Weaviate WeaviateConfig `yaml:"weaviate"`
}
VectorStoreConfig selects the vector DB backend. Type must be set when semantic caching is enabled: qdrant, pgvector, pinecone, weaviate.
type VersionCheckConfig ¶ added in v0.1.83
type VersionCheckConfig struct {
// Enabled turns the daily update check on.
// Default: true
Enabled bool `yaml:"enabled" env:"GOMODEL_VERSION_CHECK_ENABLED"`
// URL is the base URL of the version manifest. The channel file
// ("core.txt" or "pro.txt") is appended to it.
// Default: https://gomodel.enterpilot.io/version
URL string `yaml:"url" env:"GOMODEL_VERSION_CHECK_URL"`
// IntervalHours is how often the background check runs. Each run is
// jittered so gateways started together do not query in lockstep.
// Default: 24
IntervalHours int `yaml:"interval_hours" env:"GOMODEL_VERSION_CHECK_INTERVAL_HOURS"`
// TimeoutSeconds bounds a single manifest request.
// Default: 5
TimeoutSeconds int `yaml:"timeout_seconds" env:"GOMODEL_VERSION_CHECK_TIMEOUT_SECONDS"`
// MaxDailyChecks caps how many manifest requests this gateway makes per
// day in total, so a hostile client cycling cookies cannot turn /version
// into an outbound request amplifier.
// Default: 500
MaxDailyChecks int `yaml:"max_daily_checks" env:"GOMODEL_VERSION_CHECK_MAX_DAILY"`
}
VersionCheckConfig controls the daily update check against the GoModel release manifest.
The check sends the running version, the distribution name, and an anonymous install identifier. It never sends API keys, provider credentials, model names, prompts, usage data, client addresses, or the hostname the gateway is served on. Set Enabled to false to stop all outbound traffic from this subsystem.
type VirtualModelConfig ¶
type VirtualModelConfig struct {
// Source is the addressable virtual model name (for a redirect/load balancer)
// or the access selector (for an access policy).
Source string `yaml:"source" json:"source"`
// Strategy selects load balancing across multiple targets: "round_robin"
// (default), "cost", "failover", "adaptive" (delegates to a registered
// routing extension and falls back to round_robin without one), or
// "plugin" (delegates to the routing-strategy plugin named by
// StrategyPlugin). Ignored for single-target aliases and access policies.
Strategy string `yaml:"strategy,omitempty" json:"strategy,omitempty"`
// StrategyPlugin names the routing-strategy plugin used when Strategy is
// "plugin"; required then, ignored otherwise. Target weights have no
// effect under a plugin strategy: the plugin picks the target.
StrategyPlugin string `yaml:"strategy_plugin,omitempty" json:"strategy_plugin,omitempty"`
// StrategyConfig is the plugin's per-virtual-model configuration. Its keys
// are the plugin's route-scoped fields (see GET /admin/plugins,
// route_fields) and are validated against them at startup.
StrategyConfig map[string]any `yaml:"strategy_config,omitempty" json:"strategy_config,omitempty"`
// SessionAffinity keeps requests of one detected client session on the
// target that served it before, while that target stays available. Defaults
// to true when omitted; set false to restore stateless balancing.
SessionAffinity *bool `yaml:"session_affinity,omitempty" json:"session_affinity,omitempty"`
// Failover retries a request that failed on the chosen target against the
// remaining targets, in declared order. Defaults to true when omitted; set
// false to serve the chosen target only. The failover strategy always
// fails over.
Failover *bool `yaml:"failover,omitempty" json:"failover,omitempty"`
// Target is shorthand for a single-target alias, e.g. "openai/gpt-4o". Use
// Targets instead to load balance across several models.
Target string `yaml:"target,omitempty" json:"target,omitempty"`
// Targets are the redirect destinations. One target is a plain alias; several
// are load balanced across by Strategy.
Targets []VirtualModelTargetConfig `yaml:"targets,omitempty" json:"targets,omitempty"`
// UserPaths scopes the entry to specific request user paths. Empty means all.
UserPaths []string `yaml:"user_paths,omitempty" json:"user_paths,omitempty"`
// Description is an optional human-readable note.
Description string `yaml:"description,omitempty" json:"description,omitempty"`
// Slowdown is an optional extra-time factor. For example, 0.5 adds 50% of
// measured inference time. Zero explicitly disables inherited slowdown;
// nil leaves the setting unspecified.
Slowdown *float64 `yaml:"slowdown,omitempty" json:"slowdown,omitempty"`
// ReasoningEffort forces the reasoning effort sent upstream for requests
// through this redirect or to this model ("none", "minimal", "low",
// "medium", "high", "xhigh", or "max"), replacing the client's value.
// Empty leaves the client's value untouched.
ReasoningEffort string `yaml:"reasoning_effort,omitempty" json:"reasoning_effort,omitempty"`
// Enabled toggles the entry. It defaults to true when omitted.
Enabled *bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
}
VirtualModelConfig declares one virtual model in config.yaml or the VIRTUAL_MODELS env var, so operators can manage redirects, load balancers, and access policies as infrastructure-as-code. Declarative virtual models override admin-store rows of the same source and are read-only in the dashboard.
type VirtualModelTargetConfig ¶
type VirtualModelTargetConfig struct {
Provider string `yaml:"provider,omitempty" json:"provider,omitempty"`
Model string `yaml:"model" json:"model"`
Weight float64 `yaml:"weight,omitempty" json:"weight,omitempty"`
}
VirtualModelTargetConfig is one load-balancing destination. Model may be a bare id (with Provider set) or a "provider/model" selector. Weight biases the round_robin strategy and defaults to 1.
type WeaviateConfig ¶
type WeaviateConfig struct {
URL string `yaml:"url"`
Class string `yaml:"class"`
APIKey string `yaml:"api_key"`
}
WeaviateConfig holds connection configuration for Weaviate.
type WorkflowsConfig ¶
type WorkflowsConfig struct {
// RefreshInterval controls how often the in-memory workflow snapshot
// is refreshed from storage. Default: 1m.
RefreshInterval time.Duration `yaml:"refresh_interval" env:"WORKFLOW_REFRESH_INTERVAL"`
}
WorkflowsConfig holds runtime refresh behavior for persisted workflows.
type WorkloadIdentityConfig ¶ added in v0.1.108
type WorkloadIdentityConfig struct {
// IdentityTokenFile is re-read on every exchange, so projected tokens
// that rotate on disk stay current. It wins over IdentityToken.
IdentityTokenFile string `yaml:"identity_token_file"`
IdentityToken string `yaml:"identity_token"`
// TokenEndpoint overrides the provider's default exchange endpoint.
TokenEndpoint string `yaml:"token_endpoint"`
ServiceAccountID string `yaml:"service_account_id"`
// IdentityProviderID is the OpenAI workload identity provider (openai).
IdentityProviderID string `yaml:"identity_provider_id"`
// FederationRuleID, OrganizationID and WorkspaceID select the Anthropic
// federation rule, organization and workspace (anthropic).
FederationRuleID string `yaml:"federation_rule_id"`
OrganizationID string `yaml:"organization_id"`
WorkspaceID string `yaml:"workspace_id"`
}
WorkloadIdentityConfig configures workload identity federation: the gateway reads an identity token issued by its platform (Kubernetes, AWS, GCP, Azure, GitHub Actions, SPIFFE) and exchanges it for a short-lived provider access token. Which fields are required depends on the provider type.
func (WorkloadIdentityConfig) Configured ¶ added in v0.1.108
func (w WorkloadIdentityConfig) Configured() bool
Configured reports whether any workload identity field is set.
Source Files
¶
- admin.go
- budget.go
- cache.go
- clientip.go
- config.go
- encryption.go
- env.go
- env_references.go
- failover.go
- failover_policy.go
- guardrails.go
- http.go
- logging.go
- mcp.go
- mcp_virtual.go
- media.go
- merge.go
- metrics.go
- model_filter.go
- models.go
- opentelemetry.go
- plugins.go
- pricing.go
- provider_models.go
- providers.go
- ratelimit.go
- resilience.go
- resilience_policy.go
- secrets.go
- secrets_builtin.go
- secrets_destination.go
- secrets_entity.go
- secrets_rotation.go
- secrets_walk.go
- secrets_writer.go
- server.go
- session.go
- storage.go
- tagging.go
- usage.go
- user_path_env.go
- users.go
- versioncheck.go
- virtualmodels.go
- workflows.go