Skip to content

windlass.core.config

config

Configuration and settings.

Windlass reads configuration from four places, later sources winning:

  1. Built-in defaults.
  2. A config file (windlass.toml / .json / .yaml), when present.
  3. Environment variables — both WINDLASS_* and the conventional provider variables (OPENAI_API_KEY, ANTHROPIC_API_KEY, ...).
  4. Explicit keyword arguments passed to a builder.

Nothing is required to get started: with no configuration at all the dependency-free fake LLM, hash embeddings and memory vector store give you a working pipeline for tests and demos.

Example

from windlass import configure, settings _ = configure(default_llm="fake", request_timeout=30.0) settings().default_llm 'fake'

RetryConfig

Bases: BaseSettings

Retry policy applied to every provider call.

Attributes:

Name Type Description
attempts int

Total tries including the first. 1 disables retrying.

initial_delay float

Seconds before the first retry.

max_delay float

Ceiling for the exponential backoff.

multiplier float

Backoff growth factor.

jitter float

Random fraction (0-1) added to each delay to avoid thundering herds when many workers retry at once.

Example

RetryConfig(attempts=5).max_delay 30.0

CacheConfig

Bases: BaseSettings

Response caching policy.

Attributes:

Name Type Description
enabled bool

Master switch. Off by default — caching a non-deterministic model is a decision, not a default.

backend Literal['memory', 'disk']

memory (LRU, per process) or disk (needs the cache extra).

ttl float | None

Seconds an entry stays fresh. None means forever.

max_size int

Entry ceiling for the in-memory backend.

directory Path

Where the disk backend stores its data.

WindlassSettings

Bases: BaseSettings

Process-wide defaults and credentials.

Every field can be set with an environment variable. Provider keys accept both the Windlass-prefixed name and the vendor's conventional name, so an existing OPENAI_API_KEY in your shell just works.

Attributes:

Name Type Description
default_llm str

Provider used when a builder does not name one.

default_model str

Model id used when a builder does not name one.

default_embedding str

Embedding provider used by RAG builders.

default_vectordb str

Vector store used by RAG builders.

default_chunker str

Chunking strategy used by RAG builders.

default_retriever str

Retrieval strategy used by RAG builders.

temperature float

Default sampling temperature.

max_tokens int | None

Default completion ceiling; None defers to the provider.

request_timeout float

Per-request timeout in seconds.

max_concurrency int

Ceiling on in-flight provider calls for batch work.

batch_size int

Default batch size for embedding and indexing.

openai_api_key SecretStr | None

Credential for OpenAI-compatible endpoints.

openai_base_url str | None

Override for proxies and Azure-style gateways.

anthropic_api_key SecretStr | None

Credential for Anthropic.

google_api_key SecretStr | None

Credential for Gemini.

groq_api_key SecretStr | None

Credential for Groq.

huggingface_api_key SecretStr | None

Token for the HuggingFace Inference API.

ollama_base_url str

Where the local Ollama daemon listens.

pinecone_api_key SecretStr | None

Credential for Pinecone.

langsmith_api_key SecretStr | None

Credential for LangSmith tracing.

langfuse_public_key SecretStr | None

Public key for Langfuse.

langfuse_secret_key SecretStr | None

Secret key for Langfuse.

langfuse_host str

Langfuse endpoint.

telemetry bool

Whether Windlass may emit anonymous usage counters. Off by default; Windlass ships no telemetry backend, the flag exists so downstream distributions can honour it.

strict_plugins bool

Fail loudly when a third-party plugin cannot load.

retry RetryConfig

Retry policy.

cache CacheConfig

Cache policy.

Example

s = WindlassSettings(default_llm="anthropic", temperature=0.0) s.default_llm, s.temperature ('anthropic', 0.0)

secret

secret(field: str) -> str | None

Return a credential's plaintext value, or None when unset.

Parameters:

Name Type Description Default
field str

Attribute name, e.g. "openai_api_key".

required

Returns:

Type Description
str | None

The secret value, or None.

Raises:

Type Description
ConfigurationError

If field is not a known setting.

Source code in src\windlass\core\config.py
def secret(self, field: str) -> str | None:
    """Return a credential's plaintext value, or ``None`` when unset.

    Args:
        field: Attribute name, e.g. ``"openai_api_key"``.

    Returns:
        The secret value, or ``None``.

    Raises:
        ConfigurationError: If ``field`` is not a known setting.
    """
    if not hasattr(self, field):
        raise ConfigurationError(f"Unknown setting {field!r}.")
    value = getattr(self, field)
    if value is None:
        return None
    return value.get_secret_value() if isinstance(value, SecretStr) else str(value)

require_secret

require_secret(field: str, *, provider: str, env_var: str) -> str

Return a credential or raise a clear authentication error.

Parameters:

Name Type Description Default
field str

Attribute name holding the credential.

required
provider str

Provider name for the error message.

required
env_var str

The environment variable a user would normally set.

required

Returns:

Type Description
str

The secret value.

Raises:

Type Description
AuthenticationError

When the credential is missing.

Source code in src\windlass\core\config.py
def require_secret(self, field: str, *, provider: str, env_var: str) -> str:
    """Return a credential or raise a clear authentication error.

    Args:
        field: Attribute name holding the credential.
        provider: Provider name for the error message.
        env_var: The environment variable a user would normally set.

    Returns:
        The secret value.

    Raises:
        AuthenticationError: When the credential is missing.
    """
    value = self.secret(field)
    if not value:
        from windlass.core.exceptions import AuthenticationError

        raise AuthenticationError(
            f"No API key configured for the {provider} provider.",
            provider=provider,
            hint=(
                f"Set {env_var} in your environment, add it to a .env file, or pass\n"
                f"    Windlass.agent().llm('{provider}', api_key='...')"
            ),
        )
    return value

masked

masked() -> dict[str, Any]

Return settings as a dict with every secret replaced by '***'.

Safe to log or print. Used by windlass config.

Source code in src\windlass\core\config.py
def masked(self) -> dict[str, Any]:
    """Return settings as a dict with every secret replaced by ``'***'``.

    Safe to log or print. Used by ``windlass config``.
    """
    data = self.model_dump(mode="json")
    for key, value in list(data.items()):
        if isinstance(getattr(self, key, None), SecretStr):
            data[key] = "***" if value else None
    return data

settings

settings() -> WindlassSettings

Return the process-wide settings, constructing them on first use.

Returns:

Type Description
WindlassSettings

The active :class:WindlassSettings.

Example

isinstance(settings().request_timeout, float) True

Source code in src\windlass\core\config.py
def settings() -> WindlassSettings:
    """Return the process-wide settings, constructing them on first use.

    Returns:
        The active :class:`WindlassSettings`.

    Example:
        >>> isinstance(settings().request_timeout, float)
        True
    """
    global _SETTINGS
    if _SETTINGS is None:
        with _LOCK:
            if _SETTINGS is None:
                _SETTINGS = _build_settings()
    return _SETTINGS

load_config_file

load_config_file(path: str | Path) -> dict[str, Any]

Load a Windlass config file into a plain dict.

Supported formats are TOML (stdlib), JSON (stdlib) and YAML (requires pyyaml). A [windlass] / windlass: top-level table is unwrapped so the file can also live inside a shared config.

Parameters:

Name Type Description Default
path str | Path

Path to the config file.

required

Returns:

Type Description
dict[str, Any]

The parsed mapping, ready to pass to :class:WindlassSettings.

Raises:

Type Description
ConfigurationError

For a missing file, an unknown extension, a parse error, or a non-mapping document.

Example

import tempfile, pathlib p = pathlib.Path(tempfile.mkdtemp()) / "windlass.json" _ = p.write_text('{"windlass": {"default_llm": "fake"}}') load_config_file(p)

Source code in src\windlass\core\config.py
def load_config_file(path: str | Path) -> dict[str, Any]:
    """Load a Windlass config file into a plain dict.

    Supported formats are TOML (stdlib), JSON (stdlib) and YAML (requires
    ``pyyaml``). A ``[windlass]`` / ``windlass:`` top-level table is unwrapped so
    the file can also live inside a shared config.

    Args:
        path: Path to the config file.

    Returns:
        The parsed mapping, ready to pass to :class:`WindlassSettings`.

    Raises:
        ConfigurationError: For a missing file, an unknown extension, a parse
            error, or a non-mapping document.

    Example:
        >>> import tempfile, pathlib
        >>> p = pathlib.Path(tempfile.mkdtemp()) / "windlass.json"
        >>> _ = p.write_text('{"windlass": {"default_llm": "fake"}}')
        >>> load_config_file(p)
        {'default_llm': 'fake'}
    """
    path = Path(path).expanduser()
    if not path.is_file():
        raise ConfigurationError(f"Config file not found: {path}")

    suffix = path.suffix.lower()
    try:
        if suffix == ".toml":
            import tomllib

            data = tomllib.loads(path.read_text("utf-8"))
        elif suffix == ".json":
            data = json.loads(path.read_text("utf-8"))
        elif suffix in {".yaml", ".yml"}:
            try:
                import yaml
            except ImportError as exc:
                raise ConfigurationError(
                    "YAML config files require PyYAML.",
                    hint="Run: pip install pyyaml — or use windlass.toml instead.",
                ) from exc
            data = yaml.safe_load(path.read_text("utf-8")) or {}
        else:
            raise ConfigurationError(
                f"Unsupported config format {suffix!r}.",
                hint="Use .toml, .json or .yaml.",
            )
    except ConfigurationError:
        raise
    except Exception as exc:
        raise ConfigurationError(f"Could not parse {path}: {exc}") from exc

    if not isinstance(data, dict):
        raise ConfigurationError(f"{path} must contain a mapping at the top level.")
    if "windlass" in data and isinstance(data["windlass"], dict):
        data = data["windlass"]
    return data

configure

configure(**overrides: Any) -> WindlassSettings

Update the process-wide settings.

Values are merged onto the current settings, so partial updates are fine.

Parameters:

Name Type Description Default
**overrides Any

Any field of :class:WindlassSettings. Nested retry and cache accept either a dict or the model instance.

{}

Returns:

Type Description
WindlassSettings

The new settings object.

Raises:

Type Description
ConfigurationError

If an override is unknown or fails validation.

Example

configure(temperature=0.0, retry={"attempts": 5}).retry.attempts 5 reset_settings()

Source code in src\windlass\core\config.py
def configure(**overrides: Any) -> WindlassSettings:
    """Update the process-wide settings.

    Values are merged onto the current settings, so partial updates are fine.

    Args:
        **overrides: Any field of :class:`WindlassSettings`. Nested ``retry`` and
            ``cache`` accept either a dict or the model instance.

    Returns:
        The new settings object.

    Raises:
        ConfigurationError: If an override is unknown or fails validation.

    Example:
        >>> configure(temperature=0.0, retry={"attempts": 5}).retry.attempts
        5
        >>> reset_settings()
    """
    global _SETTINGS
    with _LOCK:
        current = settings().model_dump()
        unknown = set(overrides) - set(WindlassSettings.model_fields)
        if unknown:
            raise ConfigurationError(
                f"Unknown setting(s): {', '.join(sorted(unknown))}.",
                hint=f"Valid settings: {', '.join(sorted(WindlassSettings.model_fields))}",
            )
        current.update(overrides)
        try:
            _SETTINGS = WindlassSettings(**current)
        except Exception as exc:
            raise ConfigurationError(f"Invalid configuration override: {exc}") from exc
        return _SETTINGS

reset_settings

reset_settings() -> None

Discard cached settings so the next :func:settings call re-reads the env.

Primarily a test helper.

Source code in src\windlass\core\config.py
def reset_settings() -> None:
    """Discard cached settings so the next :func:`settings` call re-reads the env.

    Primarily a test helper.
    """
    global _SETTINGS
    with _LOCK:
        _SETTINGS = None