# Provider configuration schema

> Per-agent YAML and AgentsConfig fields: model, temperature, top_p, top_k, max_tokens, json mode, reasoning, price, extra_body; built-in provider config.yml baselines and UI testAgent/testProvider.

- Repository: vxcontrol/pentagi
- GitHub: https://github.com/vxcontrol/pentagi
- Human docs: https://grok-wiki.com/public/docs/vxcontrol-pentagi-eca0cf4de5f5
- Complete Markdown: https://grok-wiki.com/public/docs/vxcontrol-pentagi-eca0cf4de5f5/llms-full.txt

## Source Files

- `backend/pkg/providers/pconfig/config.go`
- `backend/pkg/providers/openai/config.yml`
- `backend/pkg/providers/anthropic/config.yml`
- `backend/pkg/providers/ollama/config.yml`
- `examples/configs/vllm-qwen3.5-27b-fp8.provider.yml`
- `backend/pkg/graph/schema.graphqls`
- `backend/pkg/server/models/providers.go`

---

---
title: "Provider configuration schema"
description: "Per-agent YAML and AgentsConfig fields: model, temperature, top_p, top_k, max_tokens, json mode, reasoning, price, extra_body; built-in provider config.yml baselines and UI testAgent/testProvider."
---

PentAGI maps every LLM call to a **per-agent** options block. Runtime ownership lives in `backend/pkg/providers/pconfig`: `ProviderConfig` holds thirteen `AgentConfig` slots; each slot becomes `llms.CallOption` values via `BuildOptions()`. Built-in providers embed a `config.yml` baseline; custom endpoints load YAML/JSON from `LLM_SERVER_CONFIG`; the UI and GraphQL persist user profiles as JSON on the `providers` table and expose the same agents through `AgentsConfig` / `AgentsConfigInput`.

## Config surfaces

| Surface | Format | Where it applies |
|---|---|---|
| Embedded `config.yml` | YAML | Default agent params for each built-in provider package (`openai`, `anthropic`, `gemini`, `bedrock`, `deepseek`, `glm`, `kimi`, `qwen`, `ollama`) |
| Embedded `models.yml` | YAML list | Optional model catalog + default prices for the Settings UI |
| File path (`LLM_SERVER_CONFIG`) | `.yml` / `.yaml` / `.json` | Custom OpenAI-compatible provider; empty path uses `EmptyProviderConfigRaw` |
| GraphQL `AgentsConfig` | camelCase GraphQL | Create/update/test user provider profiles in Settings |
| DB `providers.config` | JSON | Stored user-defined provider after `createProvider` / `updateProvider` |

Load entry points:

- `pconfig.LoadConfig(path, defaultOptions)` — file by extension
- `pconfig.LoadConfigData(data, defaultOptions)` — YAML first, then JSON
- `pconfig.LoadModelsConfigData(data)` — models catalog only

```text
YAML / GraphQL / DB JSON
        │
        ▼
  pconfig.ProviderConfig
  (simple … pentester)
        │
        ├── GetOptionsForType(agent) → []llms.CallOption
        ├── GetPriceInfoForType(agent) → *PriceInfo
        └── GetModelsMap() → model name per agent
        │
        ▼
  provider.Call / CallEx / CallWithTools
```

## Agent type keys

YAML and Go use **snake_case**. GraphQL and the Settings UI use **camelCase** for compound names.

| YAML / `ProviderOptionsType` | GraphQL `AgentConfigType` / field | Role (typical) |
|---|---|---|
| `simple` | `simple` | Lightweight completion / utility |
| `simple_json` | `simpleJson` | Structured JSON responses |
| `primary_agent` | `primaryAgent` | Flow orchestration |
| `assistant` | `assistant` | Interactive assistant mode |
| `generator` | `generator` | Subtask plan generation |
| `refiner` | `refiner` | Plan refinement |
| `adviser` | `adviser` | Advice / mentor calls |
| `reflector` | `reflector` | Reflection steps |
| `searcher` | `searcher` | Search-oriented calls |
| `enricher` | `enricher` | Context enrichment |
| `coder` | `coder` | Code generation |
| `installer` | `installer` | Install / setup tooling |
| `pentester` | `pentester` | Offensive analysis |

`pconfig.AllAgentTypes` is the authoritative ordered list of these thirteen keys.

### Fallbacks

- **`simple_json`**: if unset, uses `simple` options and appends `llms.WithJSONMode()`.
- **`assistant`**: if unset, uses `primary_agent`, else provider `defaultOptions`.
- **Legacy `agent`**: older configs with top-level `agent` are rewritten to `primary_agent`; if `assistant` is missing it also copies from `primary_agent`.

## AgentConfig fields

Full runtime schema (`pconfig.AgentConfig`). Only keys **present in the source document** are applied as call options (`BuildOptions` checks the unmarshaled `raw` map). Omitting a key leaves it unset rather than forcing a zero value into the provider request.

### Sampling and generation

<ParamField body="model" type="string">
Model id sent with `llms.WithModel`. Required for useful GraphQL profiles (`AgentConfigInput.model` is non-null). Ollama embedded baseline omits model names so the runtime/default model can supply them.
</ParamField>

<ParamField body="max_tokens" type="int">
Completion budget (`llms.WithMaxTokens`).
</ParamField>

<ParamField body="temperature" type="float">
Sampling temperature (`llms.WithTemperature`).
</ParamField>

<ParamField body="top_p" type="float">
Nucleus sampling (`llms.WithTopP`).
</ParamField>

<ParamField body="top_k" type="int">
Top-k sampling (`llms.WithTopK`). Common on local/vLLM configs; less common on OpenAI-style cloud baselines.
</ParamField>

<ParamField body="min_p" type="float">
Min-p sampling (`llms.WithMinP`). YAML-only relative to GraphQL (not on `AgentConfig` / `AgentConfigInput`).
</ParamField>

<ParamField body="n" type="int">
Number of completions (`llms.WithN`). Present in most embedded YAML baselines; not exposed on GraphQL `AgentConfig`.
</ParamField>

<ParamField body="min_length" type="int">
Minimum generation length (`llms.WithMinLength`). Available in GraphQL.
</ParamField>

<ParamField body="max_length" type="int">
Maximum generation length (`llms.WithMaxLength`). Available in GraphQL.
</ParamField>

<ParamField body="repetition_penalty" type="float">
Repetition penalty (`llms.WithRepetitionPenalty`).
</ParamField>

<ParamField body="frequency_penalty" type="float">
Frequency penalty (`llms.WithFrequencyPenalty`).
</ParamField>

<ParamField body="presence_penalty" type="float">
Presence penalty (`llms.WithPresencePenalty`).
</ParamField>

### JSON mode

<ParamField body="json" type="bool">
When the key is present, enables `llms.WithJSONMode()`. Embedded baselines set `json: true` only under `simple_json`.
</ParamField>

<ParamField body="response_mime_type" type="string">
Optional MIME type via `llms.WithResponseMIMEType` when non-empty. YAML-only (not on GraphQL schema).
</ParamField>

### Reasoning

```yaml
reasoning:
  effort: medium   # low | medium | high  (OpenAI-style effort)
  max_tokens: 1024 # token budget for thinking (Anthropic-style / token path)
```

`BuildOptions` behavior:

- If `effort` is `low`, `medium`, or `high` → `llms.WithReasoning(effort, 0)`.
- Else if `max_tokens` is in `(0, 32000]` → `llms.WithReasoning(ReasoningNone, max_tokens)`.
- GraphQL enum `ReasoningEffort`: `high` | `medium` | `low`.

Provider baselines differ:

| Style | Typical providers | Example |
|---|---|---|
| Effort string | OpenAI, Gemini, DeepSeek (pro tiers) | `reasoning: { effort: medium }` |
| Token budget | Anthropic, Bedrock Claude-class | `reasoning: { max_tokens: 1024 }` |
| Off / external | Ollama sampling-only; Qwen/vLLM via `extra_body` | no `reasoning` block, or thinking flags in body |

### Price

```yaml
price:
  input: 1.1        # USD per 1M input tokens
  output: 4.4       # USD per 1M output tokens
  cache_read: 0.275 # USD per 1M cache-read tokens (optional)
  cache_write: 3.75 # USD per 1M cache-write tokens (optional)
```

`CallUsage.UpdateCost` converts token counts using these rates. If the provider already filled cost fields (for example OpenRouter upstream cost), prices are not overwritten. Without cache rates, all input tokens are billed at `input`. With cache rates, uncached tokens use `input`, plus `cache_read` / `cache_write` components.

Prices are for usage accounting and UI display; they do not change model sampling.

### Extra body (YAML / full schema)

```yaml
extra_body:
  chat_template_kwargs:
    enable_thinking: false
  # or provider-specific maps, e.g. DeepSeek:
  # thinking:
  #   type: disabled
```

When present, applied as `openai.WithExtraBody(extra_body)` — intended for OpenAI-compatible endpoints (vLLM, DeepSeek, custom aggregators). **Not** part of GraphQL `AgentConfig` / `AgentConfigInput`; set these in file-based custom configs under `examples/configs` or `LLM_SERVER_CONFIG`.

## GraphQL AgentsConfig vs full YAML

GraphQL types for Settings CRUD and tests:

| GraphQL field | YAML equivalent | Notes |
|---|---|---|
| `model` | `model` | Required in input |
| `maxTokens` | `max_tokens` | |
| `temperature` | `temperature` | |
| `topK` / `topP` | `top_k` / `top_p` | |
| `minLength` / `maxLength` | `min_length` / `max_length` | |
| `repetitionPenalty` / `frequencyPenalty` / `presencePenalty` | same snake_case | |
| `reasoning.effort` / `reasoning.maxTokens` | `reasoning.effort` / `reasoning.max_tokens` | |
| `price.input` … `cacheWrite` | `price.*` | All four floats required when price is sent |

**Not** on GraphQL `AgentConfig` today: `n`, `min_p`, `json`, `response_mime_type`, `extra_body`.

Implications:

- UI-created profiles cannot express thinking toggles that only live in `extra_body`; use custom YAML for those.
- `simple_json` in UI still maps to the agent slot; JSON-mode enforcement for missing `SimpleJSON` config still follows `buildSimpleJSONOptions` when options fall through to `simple` + JSON mode.
- `ConvertAgentConfigFromGqlModel` rebuilds a presence-aware `raw` map so only submitted fields become call options.

## Built-in config.yml baselines

Each provider package (except pure custom) embeds defaults:

:::files
backend/pkg/providers/
  openai/config.yml
  anthropic/config.yml
  gemini/config.yml
  bedrock/config.yml
  deepseek/config.yml
  glm/config.yml
  kimi/config.yml
  qwen/config.yml
  ollama/config.yml
  custom/  → file path or EmptyProviderConfigRaw
:::

| Provider | Baseline pattern |
|---|---|
| **openai** | Mixed GPT / o-series models; effort-based reasoning on agentic slots; `simple` / `simple_json` on cheaper models with temp/top_p; full `price` including `cache_read` |
| **anthropic** | Haiku for utility / JSON; Sonnet for most agents; Opus for generator; reasoning via `max_tokens`; cache read/write prices |
| **gemini** | Flash-lite for simple/JSON; Pro-preview with effort reasoning for primary/assistant/generator-class work |
| **bedrock** | Cross-family model ids (OpenAI-compat + Anthropic Claude); token reasoning on Claude slots |
| **deepseek** | Flash for workhorse with `extra_body.thinking.type: disabled`; Pro for multi-step agents with `reasoning.effort` (avoid temp/top_p on thinking Pro) |
| **glm / kimi / qwen** | Tiered model matrix + provider-specific thinking constraints (see package comments in each `config.yml`) |
| **ollama** | Sampling only (`temperature`, `top_p`, `n`, `max_tokens`); no embedded model names or prices |
| **custom** | Defaults: temp `1.0`, top_p `1.0`, n `1`, max_tokens `16384`, plus optional `LLM_SERVER_MODEL`; config from `LLM_SERVER_CONFIG` or empty skeleton |

`EmptyProviderConfigRaw` is a JSON skeleton of all thirteen agent keys with empty objects — used when custom has no config path.

`patchProviderConfig` fills any **nil** agent pointer from the type’s default config and copies that provider’s `defaultOptions` before create/test/run.

## Models catalog

Optional per-provider `models.yml` entries become `ModelConfig`:

| Field | Meaning |
|---|---|
| `name` | Model id |
| `description` | UI copy |
| `release_date` | `YYYY-MM-DD` |
| `thinking` | Whether the model is treated as a thinking/reasoning model in UI |
| `price` | Same shape as agent `price` |

Exposed under GraphQL `ProvidersModelsList` / `settingsProviders.models`. Custom providers may instead discover models over HTTP (`LoadModelsFromHTTP`).

## Minimal YAML examples

<CodeGroup>

```yaml title="Cloud-style agent (effort reasoning)"
primary_agent:
  model: o4-mini
  n: 1
  max_tokens: 16384
  reasoning:
    effort: medium
  price:
    input: 1.1
    output: 4.4
    cache_read: 0.275

simple_json:
  model: gpt-5.4-nano
  temperature: 0.5
  top_p: 0.5
  n: 1
  max_tokens: 4096
  json: true
```

```yaml title="Local vLLM / Qwen (extra_body thinking control)"
simple:
  model: "Qwen/Qwen3.5-27B-FP8"
  temperature: 0.7
  top_k: 20
  top_p: 0.8
  min_p: 0.0
  presence_penalty: 1.5
  repetition_penalty: 1.0
  n: 1
  max_tokens: 32768
  extra_body:
    chat_template_kwargs:
      enable_thinking: false

coder:
  model: "Qwen/Qwen3.5-27B-FP8"
  temperature: 0.6
  top_k: 20
  top_p: 0.95
  n: 1
  max_tokens: 32768
```

</CodeGroup>

Copy-paste full provider files live under `examples/configs/` (vLLM, Ollama, OpenRouter, DeepInfra, Azure, and others).

## Test agent and test provider

Settings → provider form calls GraphQL mutations before or after save. Backend path: resolver → `providerController.TestAgent` / `TestProvider` → temporary provider from patched config → `tester.TestProvider`.

### Mutations

:::endpoint POST /api/v1/graphql GraphQL mutation testAgent
**Permission:** `settings.providers.view`

**Arguments**

| Arg | Type | Description |
|---|---|---|
| `type` | `ProviderType!` | Backend transport (`openai`, `anthropic`, `custom`, …) |
| `agentType` | `AgentConfigType!` | Which agent slot to exercise |
| `agent` | `AgentConfigInput!` | Single-agent config |

**Behavior:** Builds a one-slot `ProviderConfig`, patches missing slots from defaults, constructs a temporary provider, runs the built-in test registry filtered to that agent type.

**Returns:** `AgentTestResult { tests: [TestResult!]! }`
:::

:::endpoint POST /api/v1/graphql GraphQL mutation testProvider
**Permission:** `settings.providers.view`

**Arguments**

| Arg | Type | Description |
|---|---|---|
| `type` | `ProviderType!` | Backend transport |
| `agents` | `AgentsConfigInput!` | All thirteen agent configs |

**Behavior:** Same as full-provider test over every agent type with default parallel workers.

**Returns:** `ProviderTestResult` with one `AgentTestResult` per agent key (`simple`, `simpleJson`, `primaryAgent`, …).
:::

### TestResult fields

| Field | Type | Meaning |
|---|---|---|
| `name` | `String!` | Case name from registry |
| `type` | `String!` | `completion`, `json`, tool-oriented types, etc. |
| `result` | `Boolean!` | Pass/fail |
| `reasoning` | `Boolean!` | Whether reasoning path was involved |
| `streaming` | `Boolean!` | Streaming case |
| `latency` | `Int` | Milliseconds when measured |
| `error` | `String` | Failure detail |

### Compatibility rules

- `simple_json` runs **only** JSON suite cases.
- All other agent types run **non-JSON** cases (completion / tools / messages).
- Built-in registry: `backend/pkg/providers/tester/testdata/tests.yml` (basic math/text, multi-message, JSON shape checks, tool calling).
- Streaming cases are skipped unless streaming mode is enabled on the tester options (default UI path uses non-verbose, parallel workers; streaming not forced on).

### UI flow

<Steps>
  <Step title="Edit agent parameters">
    Open Settings → Providers, pick a base type (must be ready in `ProvidersReadinessStatus`), set per-agent `model` and optional sampling / reasoning / price fields.
  </Step>
  <Step title="Test one agent or the whole profile">
    Run **test agent** (`testAgent`) for a single slot or **test provider** (`testProvider`) for all slots. Failures surface as `TestResult.error` with latency.
  </Step>
  <Step title="Save profile">
    `createProvider` / `updateProvider` require `settings.providers.edit`, patch nil agents from defaults, marshal JSON into `providers.config`.
  </Step>
  <Step title="Verify">
    Query `settingsProviders` for `userDefined`, readiness flags, and default baselines. Create a flow selecting the provider name only after tests pass for critical agents (`primary_agent`, `generator`, `pentester`, `simple_json`).
  </Step>
</Steps>

## Persistence and provider types

REST/DB model `models.Provider`:

| Column / field | Role |
|---|---|
| `type` | `ProviderType` enum: `openai`, `anthropic`, `gemini`, `bedrock`, `ollama`, `custom`, `deepseek`, `glm`, `kimi`, `qwen` |
| `name` | Unique display/runtime provider name for flow selection |
| `config` | JSON blob of the full `ProviderConfig` |
| `user_id` | Owner of user-defined profiles |

Invalid `ProviderType` values fail validation (`Valid()` whitelist) and surface as API errors (422 path on REST-style validation).

## Constraints and failure modes

| Symptom | Likely cause |
|---|---|
| Options ignored for a field | Key omitted from YAML/JSON; `BuildOptions` only applies keys present in `raw` |
| Reasoning not applied | Missing `reasoning` key, invalid effort, or `max_tokens` outside `(0, 32000]` |
| JSON tests fail only on `simple_json` | Model ignores JSON mode; or UI profile lost `json: true` (YAML-only flag) while fallback still adds JSON mode only when `SimpleJSON` options are empty |
| Thinking flags ignored in UI profile | `extra_body` not in GraphQL; use file config for custom/vLLM |
| `default provider config not found` | Provider type not loaded into `defaultConfigs` (credentials/env not enabling that type) |
| Custom provider empty agents | No `LLM_SERVER_CONFIG` → empty skeleton; set model via env and/or a full YAML file |
| Legacy `agent` key | Still accepted → mapped to `primary_agent` |
| Cost stays zero | No `price` on that agent and no upstream cost in usage metadata |
| Unsupported file extension | Only `.json`, `.yaml`, `.yml` |

<Warning>
GraphQL and UI profiles are a **subset** of the full `AgentConfig` schema. For `extra_body`, `min_p`, `n`, and explicit `json` flags, prefer YAML under `LLM_SERVER_CONFIG` or the examples in `examples/configs/`, then validate with live calls or the tester against type `custom`.
</Warning>

## Related pages

<CardGroup cols={2}>
  <Card title="Configure LLM providers" href="/configure-llm-providers">
    Env keys, readiness, and wiring cloud providers before editing agent schemas.
  </Card>
  <Card title="Local and custom providers" href="/local-and-custom-providers">
    `LLM_SERVER_*`, Ollama, legacy/preserve reasoning, aggregator endpoints.
  </Card>
  <Card title="Example provider configs" href="/example-provider-configs">
    Full copy-paste YAML for vLLM, Ollama, OpenRouter, DeepInfra, Azure.
  </Card>
  <Card title="Deploy with vLLM and Qwen" href="/vllm-qwen-deployment">
    Thinking vs non-thinking provider YAML and supervision for local models.
  </Card>
  <Card title="GraphQL API" href="/graphql-api">
    Full mutation/query surface including providers and test operations.
  </Card>
  <Card title="Agents and supervision" href="/agents-and-supervision">
    How agent slots map to execution roles and hard limits during flows.
  </Card>
</CardGroup>
