# How to Switch Between LLM Providers Programmatically in VulnClaw

> Easily switch LLM providers programmatically in VulnClaw using apply_provider_preset. Update global config, resolve provider names, and auto fill defaults without touching user settings.

- Repository: [Unclecheng/VulnClaw](https://github.com/Unclecheng-li/VulnClaw)
- Tags: how-to-guide
- Published: 2026-06-30

---

**Use the `apply_provider_preset` helper function to update the global `VulnClawConfig` object, which resolves the provider name to an enum, auto-fills default `base_url` and `model` values when appropriate, and leaves user-customized settings untouched.**

VulnClaw is an open-source security analysis framework that relies on Large Language Models (LLMs) for vulnerability detection. When you need to switch between LLM providers programmatically in VulnClaw, the library provides a dedicated configuration management system that handles provider resolution, default value injection, and persistence through a clean Python API.

## Understanding the Provider Configuration Architecture

The provider state is stored in the global configuration object `VulnClawConfig.llm.provider`, which is managed through the configuration module in [`vulnclaw/config/settings.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/settings.py). The core mechanism relies on the **`apply_provider_preset`** function (source lines 311-348), which orchestrates the switching logic by interacting with preset definitions stored in [`vulnclaw/config/schema.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/schema.py) under the `PROVIDER_PRESETS` mapping.

When invoked, `apply_provider_preset` performs four critical operations: it resolves the provider string to the internal `LLMProvider` enum, updates `config.llm.provider` to its canonical value, auto-fills `base_url` and the default model only when the provider changes or when current fields still contain the old provider's defaults, and preserves any user-customized values that deviate from the presets.

## Switching to a Built-in Provider

To switch to a supported provider like DeepSeek, load the configuration, apply the preset, and optionally persist the changes to disk.

```python
from vulnclaw.config.settings import load_config, save_config, apply_provider_preset

# Load the current configuration

cfg = load_config()

# Switch to the DeepSeek provider (auto-fills its base_url & default model)

cfg = apply_provider_preset(cfg, "deepseek")

# Persist the change (writes ~/.vulnclaw/config.yaml)

save_config(cfg)

print(f"Now using {cfg.llm.provider} @ {cfg.llm.base_url} – model {cfg.llm.model}")

```

This call resolves the string `"deepseek"` to the enum `LLMProvider.deepseek` and injects the corresponding defaults from `PROVIDER_PRESETS` as defined in lines 311-348 of [`vulnclaw/config/settings.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/settings.py).

## Configuring Custom Providers

For providers not included in the built-in presets, `apply_provider_preset` accepts arbitrary provider names and stores them unchanged, allowing you to manually configure the connection parameters.

```python
cfg = load_config()
cfg = apply_provider_preset(cfg, "my-custom-provider")   # not in PROVIDER_PRESETS

cfg.llm.base_url = "https://api.myprovider.com/v1"
cfg.llm.model = "my-model"
save_config(cfg)

```

If the provider name is unknown, the function simply updates the provider field without overwriting existing `base_url` or `model` values (source lines 319-324), enabling seamless integration of private or experimental endpoints.

## Runtime Provider Switching Without Persistence

For temporary provider changes that should not affect the global configuration file, apply the preset and use the configuration object directly without calling `save_config`.

```python
cfg = load_config()
cfg = apply_provider_preset(cfg, "zhipu")

# Use cfg directly with the LLM client; do NOT call save_config()

client = make_openai_client(api_key=cfg.llm.api_key,
                            base_url=cfg.llm.base_url)

# …run queries…

```

This approach keeps the switch in-memory only, ensuring that subsequent executions revert to the persisted defaults.

## Discovering Available Providers

Before switching, enumerate the built-in presets using the `list_providers` function (source lines 352-363) to inspect default models and endpoint configurations.

```python
from vulnclaw.config.settings import list_providers
for p in list_providers():
    print(f"{p['provider']}: {p['label']} – default model {p['default_model']}")

```

This utility walks the `PROVIDER_PRESETS` dictionary in [`vulnclaw/config/schema.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/schema.py), returning metadata for each supported provider including labels and default model identifiers.

## Summary

- The **`apply_provider_preset`** function in [`vulnclaw/config/settings.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/settings.py) (lines 311-348) is the canonical method to switch between LLM providers programmatically in VulnClaw.
- Provider presets are defined in [`vulnclaw/config/schema.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/schema.py) under `PROVIDER_PRESETS`, mapping provider names to their default `base_url` and `model` values.
- The function auto-fills defaults only when switching providers or when existing values match the previous provider's defaults, preserving user customizations.
- Use **`load_config`** to read the current state and **`save_config`** to persist changes to `~/.vulnclaw/config.yaml`.
- Use **`list_providers`** (lines 352-363) to discover available built-in providers before switching.

## Frequently Asked Questions

### How does VulnClaw handle provider defaults when switching?

VulnClaw only auto-fills the `base_url` and `model` fields when the provider actually changes or when these fields still contain the previous provider's default values. If you have manually customized these settings, `apply_provider_preset` leaves them untouched to prevent overwriting user preferences.

### Can I switch to a custom LLM provider not in the preset list?

Yes. When you pass a provider name that is not found in `PROVIDER_PRESETS`, `apply_provider_preset` stores the name as-is without modifying other configuration fields (source lines 319-324). You can then manually set `cfg.llm.base_url` and `cfg.llm.model` to point to your custom endpoint.

### Where are the provider presets defined in the source code?

The preset definitions reside in [`vulnclaw/config/schema.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/schema.py) within the `PROVIDER_PRESETS` dictionary. These presets map provider strings to their corresponding `LLMProvider` enum values and default connection parameters, which are then consumed by the `apply_provider_preset` function in [`vulnclaw/config/settings.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/settings.py).

### Is it possible to switch providers temporarily without saving to disk?

Yes. Simply omit the `save_config(cfg)` call after applying the preset. The configuration object remains modified in-memory for the duration of your Python session, but the underlying `~/.vulnclaw/config.yaml` file retains its original provider settings, making this ideal for one-off analysis tasks or testing different models.