Nexus

Forge Extension

Run Nexus as a forge.Extension with auto-discovery and DI.

Setup

import (
    "github.com/xraph/forge"
    nexusext "github.com/xraph/nexus/extension"
)

app := forge.New(
    forge.WithExtension(nexusext.New(
        nexusext.WithProvider(openai.New(key)),
    )),
)
app.Start(ctx)

Auto-Discovery

When running in a Forge application, the Nexus extension automatically discovers other Forge extensions via vessel DI:

  • Chronicle — Wires audit_hook with Chronicle recorder
  • Shield — Wires Shield as a guardrail adapter
  • Relay — Wires relay_hook with Relay sender
  • Authsome — Wires Authsome as auth provider
  • Metrics — Wires observability with gu.MetricFactory

YAML configuration

When running inside Forge, Nexus automatically loads configuration from the application's YAML config file. The extension looks for settings under two keys (in order):

  1. extensions.nexus (namespaced, recommended)
  2. nexus (legacy shorthand)
forge.yaml
extensions:
  nexus:
    base_path: "/ai"
    default_timeout: "30s"
    default_max_retries: 2
    global_rate_limit: 1000
    log_level: "info"
    enable_usage: true
    enable_cache: false
    grove_database: ""
    disable_routes: false
    disable_migrate: false

Configuration reference

FieldYAML keyTypeDefaultDescription
BasePathbase_pathstring"/ai"URL prefix for gateway routes
DefaultTimeoutdefault_timeoutduration30sDefault timeout for provider requests
DefaultMaxRetriesdefault_max_retriesint2Default retries per request
GlobalRateLimitglobal_rate_limitint0Global rate limit in RPM (0 = unlimited)
LogLevellog_levelstring"info"Gateway log level
EnableUsageenable_usagebooltrueEnable usage tracking
EnableCacheenable_cacheboolfalseEnable response caching
GroveDatabasegrove_databasestring""Name of grove.DB to resolve from DI
DisableRoutesdisable_routesboolfalseDisable automatic route registration
DisableMigratedisable_migrateboolfalseDisable automatic store migration

Merge behavior

File-based and programmatic configuration are merged with these rules:

CategoryPrecedence
Boolean flags (disable_routes, disable_migrate, enable_cache)Programmatic true wins
String fields (base_path, log_level, grove_database)YAML takes precedence; programmatic fills gaps
Duration/int fields (default_timeout, default_max_retries, global_rate_limit)YAML takes precedence; programmatic fills gaps
Pointer fields (enable_usage)YAML takes precedence; programmatic fills gaps

Any remaining zero-valued fields are filled from DefaultConfig().

Requiring file config

If your deployment relies on the config file being present, use WithRequireConfig:

app := forge.New(
    forge.WithExtension(nexusext.New(
        nexusext.WithRequireConfig(true),
    )),
)

When RequireConfig is true and no config is found under either key, Register returns an error.

Extension options

OptionPurpose
WithProvider(p)Register an LLM provider
WithDatabase(s)Set the persistence store directly
WithGatewayOption(opt)Pass a raw nexus.Option to the gateway
WithBasePath(path)Set the HTTP base path (default: /ai)
WithConfig(cfg)Set extension configuration directly
WithDisableRoutes()Disable automatic route registration
WithDisableMigrate()Disable automatic store migration
WithRequireConfig(bool)Require config to be present in YAML files
WithGroveDatabase(name)Resolve a grove.DB from DI by name

Grove database integration

When your Forge app uses the Grove extension to manage database connections, Nexus can automatically resolve a grove.DB from the DI container and construct the correct store backend based on the driver type.

Using the default grove database

If the Grove extension registers a single database (or a default in multi-DB mode), use WithGroveDatabase with an empty name:

ext := nexusext.New(
    nexusext.WithGroveDatabase(""),
    nexusext.WithProvider(openai.New(key)),
)

Using a named grove database

In multi-database setups, reference a specific database by name:

ext := nexusext.New(
    nexusext.WithGroveDatabase("nexus"),
    nexusext.WithProvider(openai.New(key)),
)

This resolves the grove.DB named "nexus" from the DI container and auto-constructs the matching store. The driver type is detected automatically -- you do not need to import individual store packages.

Via YAML

Grove database can also be configured via the YAML config file:

extensions:
  nexus:
    grove_database: "nexus"

When grove_database is set in YAML, the extension enables grove resolution automatically.

Store resolution order

The extension resolves its store in this order:

  1. Explicit store -- if WithDatabase(s) was called, it is used directly and grove is ignored.
  2. Grove database -- if WithGroveDatabase(name) was called, the named or default grove.DB is resolved from DI.
  3. In-memory fallback -- if neither is configured, an in-memory store is used.

DI Registration

The extension registers the Gateway in the vessel container:

// Other extensions can resolve it
gw, err := vessel.Resolve[*nexus.Gateway](container)

On this page