---
title: Configuration
description: Options and defaults for the Sentinel engine and Forge extension.
---

## Engine configuration

`sentinel.Config` holds global defaults that apply to all evaluations unless overridden at the suite level:

```go
type Config struct {
    DefaultModel    string        // LLM model (default: "smart")
    Temperature     float64       // LLM sampling temperature (default: 0)
    PassThreshold   float64       // minimum score to pass (default: 0.7)
    Concurrency     int           // max concurrent case evaluations (default: 4)
    ShutdownTimeout time.Duration // graceful shutdown timeout (default: 30s)
}
```

### Defaults

```go
sentinel.DefaultConfig() // returns:
// Config{
//     DefaultModel:    "smart",
//     Temperature:     0,
//     PassThreshold:   0.7,
//     Concurrency:     4,
//     ShutdownTimeout: 30 * time.Second,
// }
```

The special model names `"smart"` and `"fast"` are resolved by the target adapter to the appropriate model for the provider.

### Overriding defaults

Pass a custom config via engine options:

```go
eng, err := engine.New(
    engine.WithConfig(sentinel.Config{
        DefaultModel:  "gpt-4o",
        PassThreshold: 0.8,
        Concurrency:   8,
    }),
    engine.WithStore(pgStore),
)
```

## Engine options

| Option | Description |
|--------|-------------|
| `engine.WithStore(s)` | Sets the composite store (required) |
| `engine.WithConfig(cfg)` | Sets the engine configuration |
| `engine.WithExtension(ext)` | Registers a plugin extension |
| `engine.WithLogger(l)` | Sets the structured logger |

## Suite-level overrides

Each `suite.Suite` can override engine-level defaults:

```go
s := &suite.Suite{
    Model:       "claude-3-opus",  // overrides DefaultModel
    Temperature: 0.3,              // overrides Temperature
}
```

If a suite field is zero-valued, the engine default applies.

## Forge extension options

The `extension.New` function accepts its own set of options:

```go
ext := extension.New(
    extension.WithStore(pgStore),
    extension.WithExtension(metricsPlugin),
    extension.WithDisableRoutes(),
    extension.WithDisableMigrate(),
    extension.WithBasePath("/sentinel"),
    extension.WithGroveDatabase(""),
)
```

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `WithStore(s)` | `store.Store` | -- | Composite store (auto-resolved from grove if not set). |
| `WithExtension(x)` | `plugin.Extension` | -- | Lifecycle hook plugin (repeatable). |
| `WithEngineOption(opt)` | `engine.Option` | -- | Pass engine option directly. |
| `WithConfig(cfg)` | `Config` | defaults | Full config struct. |
| `WithDisableRoutes()` | -- | `false` | Skip HTTP route registration. |
| `WithDisableMigrate()` | -- | `false` | Skip migrations on Start. |
| `WithBasePath(path)` | `string` | `""` | URL prefix for all sentinel routes. |
| `WithGroveDatabase(name)` | `string` | `""` | Named grove.DB to resolve from DI. |
| `WithRequireConfig(b)` | `bool` | `false` | Require config in YAML files. |

## File-based configuration (YAML)

When running as a Forge extension, Sentinel automatically loads configuration from YAML config files. The extension looks for config under the following keys (in order):

1. `extensions.sentinel` -- standard Forge extension config namespace
2. `sentinel` -- top-level shorthand

### Example

```yaml
# forge.yaml
extensions:
  sentinel:
    disable_routes: false
    disable_migrate: false
    base_path: "/sentinel"
    default_model: "smart"
    temperature: 0
    pass_threshold: 0.7
    concurrency: 4
    shutdown_timeout: "30s"
    grove_database: ""
```

### Config fields

| YAML Key | Type | Default | Description |
|----------|------|---------|-------------|
| `disable_routes` | `bool` | `false` | Skip HTTP route registration |
| `disable_migrate` | `bool` | `false` | Skip migrations on Start |
| `base_path` | `string` | `""` | URL prefix for all routes |
| `default_model` | `string` | `"smart"` | LLM model identifier |
| `temperature` | `float64` | `0` | LLM sampling temperature |
| `pass_threshold` | `float64` | `0.7` | Minimum score to pass |
| `concurrency` | `int` | `4` | Parallel evaluation workers |
| `shutdown_timeout` | `duration` | `"30s"` | Max graceful shutdown wait |
| `grove_database` | `string` | `""` | Named grove.DB from DI |

### Merge behaviour

File-based configuration is merged with programmatic options. Programmatic boolean flags (`DisableRoutes`, `DisableMigrate`) always win when set to `true`. For other fields, YAML values take precedence, then programmatic values, then defaults.
