smooai-config 4.2.2

Type-safe three-tier configuration management (public, secret, feature flags) with schema validation and a runtime client for the Smoo AI config platform.
Documentation

About SmooAI

SmooAI is an AI-powered platform for helping businesses multiply their customer, employee, and developer experience.

Learn more on smoo.ai

SmooAI Packages

Check out other SmooAI packages at smoo.ai/open-source

About smooai-config (Rust)

Type-safe configuration management for Rust services - Define configuration schemas with native Rust structs and schemars, validate for cross-language interoperability, and fetch values from the centralized Smoo AI config server with async reqwest and local caching.

Crates.io Version Crates.io Downloads Crates.io License

GitHub License GitHub Actions Workflow Status GitHub Repo stars

Rust Crate

A Rust port of @smooai/config that mirrors the feature set of the TypeScript and Python versions. The crate exposes a type-driven configuration API using schemars for JSON Schema generation, an async reqwest-based runtime client with local caching, and a local config manager that merges file and environment variable sources.

Why smooai-config?

Ever hardcoded configuration values across your Rust services or fought to keep configuration in sync between Rust backends and TypeScript frontends? Traditional config management gives you the values, but not the safety or cross-language consistency.

smooai-config provides:

  • Three configuration tiers - Separate public config, secrets, and feature flags with distinct schema types
  • Native Rust structs - Derive JsonSchema on your own types via schemars for automatic JSON Schema generation
  • define_config_typed API - Idiomatic generic function that converts Rust struct types to validated JSON Schema
  • Cross-language compatibility validation - Catches unsupported JSON Schema features at schema definition time
  • Async runtime client - Fetch configuration from the Smoo AI config server with tokio + reqwest and local caching
  • Environment variable fallback - Zero-config client setup via SMOOAI_CONFIG_* environment variables
  • from_env() constructor - Load all credentials from environment with a single call

Install

Add to your Cargo.toml:

[dependencies]
smooai-config = "0.1"

or using cargo:

cargo add smooai-config

All Language Packages

Language Package Install
TypeScript @smooai/config pnpm add @smooai/config
Python smooai-config pip install smooai-config
Rust smooai-config cargo add smooai-config
Go github.com/SmooAI/config/go/config go get github.com/SmooAI/config/go/config

Usage

Define Configuration Schemas with Native Rust Types

The preferred way to define configuration is with Rust structs that derive JsonSchema. Use EmptySchema for tiers that have no configuration values:

use smooai_config::schema::{define_config_typed, EmptySchema};
use schemars::JsonSchema;
use serde::{Serialize, Deserialize};

#[derive(Default, Serialize, Deserialize, JsonSchema)]
struct PublicConfig {
    api_url: String,
    max_retries: u32,
    enable_debug: bool,
}

#[derive(Default, Serialize, Deserialize, JsonSchema)]
struct SecretConfig {
    database_url: String,
    api_key: String,
}

#[derive(Default, Serialize, Deserialize, JsonSchema)]
struct FeatureFlags {
    enable_new_ui: bool,
    beta_features: bool,
}

// Generates JSON Schema from your Rust types and validates cross-language compatibility
let config = define_config_typed::<PublicConfig, SecretConfig, FeatureFlags>();

println!("{}", serde_json::to_string_pretty(&config.json_schema).unwrap());

Define Configuration Schemas from Raw JSON Schema

Alternatively, pass raw JSON Schema values directly:

use smooai_config::schema::define_config;

let public_schema = serde_json::json!({
    "type": "object",
    "properties": {
        "api_url": {"type": "string"},
        "max_retries": {"type": "integer"}
    }
});

let config = define_config(
    Some(public_schema),
    None, // no secret tier
    None, // no feature flags
);

Runtime Client - Fetch Values from Server

The ConfigClient is async and uses reqwest under the hood. Fetched values are cached locally until invalidate_cache is called or a TTL expires:

use smooai_config::ConfigClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Option 1: Use environment variables (zero-config)
    // Reads SMOOAI_CONFIG_API_URL, SMOOAI_CONFIG_API_KEY, SMOOAI_CONFIG_ORG_ID
    let mut client = ConfigClient::from_env();

    // Option 2: Explicit configuration
    let mut client = ConfigClient::new(
        "https://config.smooai.dev",
        "your-api-key",
        "your-org-id",
    );

    // Option 3: Explicit with default environment
    let mut client = ConfigClient::with_environment(
        "https://config.smooai.dev",
        "your-api-key",
        "your-org-id",
        "production",
    );

    // Fetch a single value (None uses default environment)
    let api_url = client.get_value("API_URL", None).await?;

    // Fetch with environment override
    let staging_url = client.get_value("API_URL", Some("staging")).await?;

    // Fetch all values
    let all_values = client.get_all_values(None).await?;

    Ok(())
}

Caching

Cache TTL can be configured with set_cache_ttl. By default the cache never expires (manual invalidation only):

use smooai_config::ConfigClient;
use std::time::Duration;

let mut client = ConfigClient::new(
    "https://config.smooai.dev",
    "your-api-key",
    "your-org-id",
);

// Set a 5-minute TTL
client.set_cache_ttl(Some(Duration::from_secs(300)));

// Fetched from server and cached
let value = client.get_value("API_URL", None).await?;

// Served from cache
let value = client.get_value("API_URL", None).await?;

// Invalidate all cached values
client.invalidate_cache();

// Invalidate cached values for one environment
client.invalidate_cache_for_environment("production");

Local Configuration Manager

For local development or offline environments, LocalConfigManager loads configuration from .smooai-config/ files and environment variables:

use smooai_config::LocalConfigManager;

let manager = LocalConfigManager::new(None, None, None)?;

// Fetch values from local file config + env vars
let api_url = manager.get_public_config("API_URL")?;
let db_url = manager.get_secret_config("DATABASE_URL")?;
let new_ui = manager.get_feature_flag("ENABLE_NEW_UI")?;

Environment Variables

All clients read from the same set of environment variables:

Variable Description Required
SMOOAI_CONFIG_API_URL Base URL of the config API Yes
SMOOAI_CONFIG_API_KEY Bearer token for authentication Yes
SMOOAI_CONFIG_ORG_ID Organization ID Yes
SMOOAI_CONFIG_ENV Default environment name (defaults to "development") No

Set these in your environment and the client will use them automatically:

export SMOOAI_CONFIG_API_URL="https://config.smooai.dev"
export SMOOAI_CONFIG_API_KEY="your-api-key"
export SMOOAI_CONFIG_ORG_ID="your-org-id"
export SMOOAI_CONFIG_ENV="production"

Configuration Tiers

Tier Purpose Examples
Public Client-visible settings API URLs, feature toggles, UI config
Secret Server-side only Database URLs, API keys, JWT secrets
Feature Flags Runtime toggles A/B tests, gradual rollouts, beta access

Built With

  • Rust 2021 Edition - Memory safety and performance
  • schemars - JSON Schema generation from Rust types
  • serde / serde_json - JSON serialization
  • reqwest - Async HTTP client
  • tokio - Async runtime

Development

Running tests

cargo test

Building

cargo build --release

Linting and Formatting

cargo clippy
cargo fmt

Related Packages

Contact

Brent Rager

Smoo Github: https://github.com/SmooAI

License

MIT © SmooAI