Documentation
¶
Overview ¶
Package eino contains the Eino-backed chat model wrapper used by all AI agents in versus-incident. It is the ONLY package in the codebase that imports concrete model SDKs — every concrete AI agent (detect, analyze, ...) goes through these helpers so a future framework swap only touches this package.
There is no `framework` knob in the config (Eino is the framework). The MODEL backend, however, IS selectable: `agent.ai.provider` chooses among the providers registered in provider.go (openai by default). The provider registry is the single chokepoint for concrete model imports.
Index ¶
- Constants
- func IsKeylessProvider(name string) bool
- func IsSupportedEmbedderProvider(name string) bool
- func IsSupportedProvider(name string) bool
- func NewChatModel(ctx context.Context, cfg config.AgentAIConfig, opts Options) (model.BaseChatModel, error)
- func NewEmbedder(ctx context.Context, cfg config.AgentAIConfig, opts Options) (core.Embedder, error)
- func NewTool(value core.Tool, timeout time.Duration, maxOutputBytes int) (tool.InvokableTool, error)
- func NewToolCallingChatModel(ctx context.Context, cfg config.AgentAIConfig, opts Options) (model.ToolCallingChatModel, error)
- func SupportedProviders() []string
- type ConfigError
- type Holder
- func NewChatModelHolder(base config.AgentAIConfig, opts Options, rt RuntimeAI) *Holder[model.BaseChatModel]
- func NewEmbedderHolder(base config.AgentAIConfig, opts Options, rt RuntimeAI) *Holder[core.Embedder]
- func NewModelHolder[T any](base config.AgentAIConfig, opts Options, rt RuntimeAI, ...) *Holder[T]
- func NewToolCallingChatModelHolder(base config.AgentAIConfig, opts Options, rt RuntimeAI) *Holder[model.ToolCallingChatModel]
- type Options
- type ProviderError
- type RuntimeAI
Constants ¶
const DefaultProvider = "openai"
DefaultProvider is the model backend used when AgentAIConfig.Provider is empty. It is the OSS default and preserves the historical OpenAI behaviour byte-for-byte (JSON-mode, MaxCompletionTokens, runtime-key transport, the test-only Options.BaseURL seam).
Variables ¶
This section is empty.
Functions ¶
func IsKeylessProvider ¶ added in v1.4.26
IsKeylessProvider reports whether a registered chat provider intentionally sends no provider credential. Consumers use this registry-derived policy when deciding whether a provider transition requires a replacement key.
func IsSupportedEmbedderProvider ¶ added in v1.4.26
IsSupportedEmbedderProvider reports whether the normalized provider has a registered embedding implementation.
func IsSupportedProvider ¶ added in v1.4.4
IsSupportedProvider reports whether name (case-insensitive, with the empty string normalised to DefaultProvider) is a registered chat provider. It is the boundary validator the enterprise control API gates writes on.
func NewChatModel ¶
func NewChatModel(ctx context.Context, cfg config.AgentAIConfig, opts Options) (model.BaseChatModel, error)
NewChatModel builds an Eino ChatModel configured for JSON-mode structured output. cfg must already be the *resolved* per-task config (see AgentAIConfig.Resolve) — this helper does not look at the per-task sub-blocks.
The concrete model backend is selected by cfg.Provider via the provider registry (provider.go); an empty provider defaults to openai and an unsupported one fails fast. Model must be set; APIKey may be empty (the provider client errors at call time, not construction time, which is fine for tests).
func NewEmbedder ¶ added in v1.4.4
func NewEmbedder(ctx context.Context, cfg config.AgentAIConfig, opts Options) (core.Embedder, error)
NewEmbedder builds a core.Embedder for the configured provider. cfg.Provider selects the backend (empty defaults to openai); an unsupported provider fails fast with a clear error. cfg.Model must be set (the embedding model id, e.g. "text-embedding-3-small"); APIKey may be empty (a local/unauthenticated server accepts it, a remote one errors at call time — convenient for tests).
The openai path is OpenAI-compatible, so pointing opts.BaseURL at a local server (Ollama / vLLM / LocalAI) keeps embeddings in the operator's VPC; the dedicated ollama provider does the same against a native Ollama daemon.
func NewTool ¶ added in v1.4.25
func NewTool(value core.Tool, timeout time.Duration, maxOutputBytes int) (tool.InvokableTool, error)
NewTool adapts a core.Tool to Eino's invokable tool contract.
func NewToolCallingChatModel ¶
func NewToolCallingChatModel(ctx context.Context, cfg config.AgentAIConfig, opts Options) (model.ToolCallingChatModel, error)
NewToolCallingChatModel mirrors NewChatModel but returns the tool-calling variant. The analyze agent needs WithTools to register its read-only tool catalog; detect uses the base helper above.
IMPORTANT: this helper deliberately does NOT force JSON-mode. With tools bound, the model alternates between tool_calls (JSON, never content) and a final assistant message; forcing JSON-mode causes providers to reject the tool-call turns.
func SupportedProviders ¶ added in v1.4.4
func SupportedProviders() []string
SupportedProviders is the exported, sorted list of registered chat providers. It lets a consumer (e.g. the enterprise runtime AI-settings API) validate an operator-supplied provider on WRITE against the SAME registry the model builders use, so an unknown value is rejected at the boundary rather than relying solely on the Holder's runtime fail-closed.
Types ¶
type ConfigError ¶ added in v1.4.26
type ConfigError struct {
// contains filtered or unexported fields
}
ConfigError is a trusted local validation error produced before a provider SDK is called. Its message contains only bounded configuration identifiers and fixed guidance, so boot diagnostics may log it directly.
func (*ConfigError) Error ¶ added in v1.4.26
func (err *ConfigError) Error() string
type Holder ¶ added in v1.4.4
type Holder[T any] struct { // contains filtered or unexported fields }
Holder lazily builds and caches a model artifact of type T (a chat model, a tool-calling chat model, an embedder, or a higher-level agent that wraps one), rebuilding only when the effective signature changes. It is concurrency-safe: agent ticks and an operator's runtime change can race, so every Get is mutex-guarded.
func NewChatModelHolder ¶ added in v1.4.4
func NewChatModelHolder(base config.AgentAIConfig, opts Options, rt RuntimeAI) *Holder[model.BaseChatModel]
NewChatModelHolder is the shared entrypoint for the tool-free, JSON-mode chat path (detect, slo-advisor). It rebuilds the model on a provider / model / state change and returns model.BaseChatModel.
func NewEmbedderHolder ¶ added in v1.4.4
func NewEmbedderHolder(base config.AgentAIConfig, opts Options, rt RuntimeAI) *Holder[core.Embedder]
NewEmbedderHolder mirrors the chat holders for the embedding path. Runtime provider overrides are validated against the (smaller) embedding registry, so a runtime switch to a chat-only provider (deepseek, claude, qwen) fails closed to the configured embedding provider.
func NewModelHolder ¶ added in v1.4.4
func NewModelHolder[T any](base config.AgentAIConfig, opts Options, rt RuntimeAI, build func(ctx context.Context, cfg config.AgentAIConfig, opts Options) (T, error)) *Holder[T]
NewModelHolder builds a Holder for an arbitrary artifact whose backend is a CHAT provider (runtime provider overrides are validated against the chat registry). build receives a copy of base with Provider already resolved to the effective provider for the current signature; callers route their construction (e.g. NewToolCallingChatModel + a ReAct agent) through it.
func NewToolCallingChatModelHolder ¶ added in v1.4.4
func NewToolCallingChatModelHolder(base config.AgentAIConfig, opts Options, rt RuntimeAI) *Holder[model.ToolCallingChatModel]
NewToolCallingChatModelHolder is the shared entrypoint for the tool-calling analyze path. It returns model.ToolCallingChatModel; the caller binds tools.
func (*Holder[T]) Current ¶ added in v1.4.4
func (h *Holder[T]) Current() T
Current returns the most recently built artifact without consulting the runtime signature (no rebuild). It returns the zero value when nothing has been built yet. Used by structural guards that need the concrete built model, never on the hot path.
func (*Holder[T]) Get ¶ added in v1.4.4
Get returns the model for the current effective signature, rebuilding it only when the signature has changed since the last build. A build error is returned to the caller and the previously-cached model (if any) is left untouched, so a transient failure never poisons a healthy holder.
type Options ¶
type Options struct {
HTTPClient *http.Client
BaseURL string
Timeout time.Duration
// RuntimeKeyFunc is an OPTIONAL per-request provider credential override.
// Provider builders apply it using their native authentication scheme.
// ok=false leaves the SDK's configured key untouched; ok=true with an
// empty key explicitly clears credentials for that request.
RuntimeKeyFunc func(ctx context.Context) (key string, ok bool)
}
BaseURL is overridable for tests. Production code passes "" to use the provider default endpoint. It is intentionally not a config field: admin endpoints never expose this; only the chatmodel test sets it to point at an httptest server.
type ProviderError ¶ added in v1.4.26
ProviderError is the safe, public representation of a model-provider failure. It deliberately does not retain or unwrap the raw provider cause.
func SafeProviderError ¶ added in v1.4.26
func SafeProviderError(provider, model string, cause error) *ProviderError
SafeProviderError classifies a raw provider failure in memory and returns a bounded error containing only safe identifiers and a fixed diagnostic.
func (*ProviderError) Error ¶ added in v1.4.26
func (err *ProviderError) Error() string
type RuntimeAI ¶ added in v1.4.4
type RuntimeAI struct {
// Provider returns a runtime provider override for ctx. ok=false ⇒ no
// opinion (use the configured provider). An unknown/unsupported value
// FAILS CLOSED: the Holder keeps the configured provider and logs once
// per distinct bad value — it never crashes and never silently falls
// back to openai.
Provider func(ctx context.Context) (provider string, ok bool)
// Enabled folds the runtime enable state into the signature so a toggle
// rebuilds. ok=false ⇒ not folded. Optional.
Enabled func(ctx context.Context) (enabled bool, ok bool)
// KeySet folds whether a runtime key override is currently present into
// the signature so a set⟷clear transition rebuilds. ok=false ⇒ not
// folded. The key VALUE is never part of the signature (it hot-reloads
// through the transport). Optional.
KeySet func(ctx context.Context) (set bool, ok bool)
// Revision folds an opaque runtime configuration revision into the
// signature. Tool catalogs use a hash of durable per-agent settings so all
// replicas rebuild their bound graph on the next turn after a change.
Revision func(ctx context.Context) (revision string, ok bool)
}
RuntimeAI is the optional set of runtime override signals folded into a Holder's rebuild signature. Every func MAY be nil; a zero RuntimeAI is the community default (no overrides ⇒ the configured provider, built once, never rebuilt).
Provider composes with the existing per-request key override: the key VALUE still hot-reloads through the provider-native transport WITHOUT a rebuild (it is NOT part of the signature); only the provider, the model id, and the enable/key-presence STATE force a rebuild.