Settings
forge-settings is the introspection layer for provider configuration. It
answers three questions consistently across every provider:
- What environment variables / config fields does this provider need?
- Which of those are currently set?
- What's missing before this provider can start?
The contract
pub trait ProviderSettings: Send + Sync {
fn provider_id(&self) -> &str; // "anthropic", "openai", ...
fn required_fields(&self) -> Vec<FieldSpec>;
fn optional_fields(&self) -> Vec<FieldSpec>;
fn current_state(&self) -> SettingsState;
fn missing(&self) -> Vec<FieldSpec>;
}
pub struct FieldSpec {
pub name: String, // "ANTHROPIC_API_KEY"
pub kind: FieldKind, // Secret | Url | String | ...
pub source: FieldSource, // EnvVar | ConfigFile | Inline
pub description: String,
}
pub enum SettingsState {
Ready,
Partial { missing: Vec<String> },
Empty,
}
Inspecting a single provider
use forge::providers::AnthropicConfig;
use forge::settings::ProviderSettings;
let config = AnthropicConfig::no_credentials(); // skip env loading
let state = config.current_state();
match state {
SettingsState::Ready => println!("anthropic is fully configured"),
SettingsState::Partial { missing } => {
println!("anthropic missing: {:?}", missing);
}
SettingsState::Empty => println!("anthropic not configured"),
}
Inspecting every provider at once
use forge::settings::list_all_providers;
for descriptor in list_all_providers() {
println!(
"{:>14} state={:?} missing={:?}",
descriptor.provider_id,
descriptor.state,
descriptor.missing,
);
}
This is what powers the Forge website's /start page — it scans the user's
environment and tells them exactly which providers are live, which are
partially configured, and which haven't been touched.
Why this exists
Before forge-settings, "is this provider ready?" was a per-provider exercise
in reading constructor source. With it:
- The harness's settings panel can render a uniform UI for all providers
- CI can fail fast with a clear "OPENAI_API_KEY missing" instead of cryptic authentication errors at first use
- New providers get this introspection for free by implementing one trait
Adding a new provider
impl ProviderSettings for MyProviderConfig {
fn provider_id(&self) -> &str { "myprovider" }
fn required_fields(&self) -> Vec<FieldSpec> {
vec![
FieldSpec::env("MYPROVIDER_API_KEY", FieldKind::Secret,
"API key issued by myprovider.com"),
]
}
fn optional_fields(&self) -> Vec<FieldSpec> {
vec![
FieldSpec::env("MYPROVIDER_BASE_URL", FieldKind::Url,
"Override base URL (defaults to api.myprovider.com)"),
]
}
fn current_state(&self) -> SettingsState { /* check env */ }
fn missing(&self) -> Vec<FieldSpec> { /* delta */ }
}
Next
- Provider Capability Matrix — feature parity per provider
- Provider Contract — the shared runtime contract