Files
anyllm-proxy/docs/codedocs/configuration-and-modes.md
whit3rabbitandClaude Sonnet 5 9456d1ad1b feat: opt-in forge-guardrails tool-call policy + Anthropic thinking-block repair
- Tool-call guardrails (lsp_first/quiet_command/write_payload_cap nudges,
  fingerprint dedup) for local-LLM tool loops. Configurable via YAML
  tool_execution.guardrails, FORGE_TOOL_CALL_POLICY env fallback, or the
  admin UI (live, no restart).
- Anthropic thinking-block record/repair (ANTHROPIC_THINKING_REPAIR):
  records ground truth off the real API and repairs client-corrupted
  thinking/redacted_thinking blocks in replayed conversations.
- Bidirectional thinking_blocks (signature/redacted state) round-trip
  through the OpenAI-compat wire format for LiteLLM-style clients.
- Review fixes: guardrail-mode divergence between streaming/non-streaming
  paths, cross-backend/tenant cache-namespace collision, client-controlled
  integer overflow in thinking budget_tokens, dropped reasoning_content and
  citations on repair/translation paths, a fail-closed race under cache
  eviction, plus dedup/simplification cleanup and doc corrections.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 13:03:02 -05:00

5.7 KiB

title, description
title description
Configuration And Modes Learn the config precedence rules, environment variables, and the differences between simple mode, simple YAML, LiteLLM YAML, and TOML multi-backend configs.

Configuration is the operator-facing abstraction in anyllm-proxy. It exists because the project supports a low-friction .anyllm.env flow for local use and a more explicit config-file flow for multi-backend, routed, and admin-managed deployments.

What It Solves

  • Local users want three or four variables and a working proxy.
  • Teams need repeatable config files, secret indirection, and named backends.
  • The admin UI needs runtime-mutated state without forcing a full process restart.

crates/proxy/src/main.rs and crates/proxy/src/config/mod.rs implement that precedence model.

How It Relates To Other Concepts

  • Configuration creates ModelMapping, Config, BackendConfig, and MultiConfig, which are then consumed by Routing And Backends.
  • It determines whether degradation warnings are exposed for the Translation Pipeline.
  • It also decides whether the admin server, tool engine, or batch storage have the inputs they need.

How It Works Internally

Startup in crates/proxy/src/main.rs happens in a strict order:

  1. resolve the data directory and locate .anyllm.env
  2. load file-based env vars before Tokio starts
  3. compute LiteLLM env aliases
  4. apply env vars previously imported into SQLite through the admin UI
  5. auto-detect config.yaml into PROXY_CONFIG when present
  6. if the config is LiteLLM YAML, extract general_settings.master_key early
  7. only then build the async runtime

MultiConfig::load in crates/proxy/src/config/mod.rs uses the following detection rules:

  • PROXY_CONFIG ending in .yaml or .yml with a top-level models: key -> simple native YAML
  • PROXY_CONFIG ending in .yaml or .yml with model_list: -> LiteLLM-compatible YAML
  • any other PROXY_CONFIG file -> TOML multi-backend config
  • no PROXY_CONFIG -> env-only Config::from_env()

Basic Usage

Minimal .anyllm.env:

OPENAI_API_KEY=sk-...
BIG_MODEL=gpt-4o
SMALL_MODEL=gpt-4o-mini
PROXY_API_KEYS=proxy-user

This lands in the Config::from_env branch and produces a single backend, one ModelMapping, and a default LISTEN_PORT of 3000.

Advanced Usage

Simple YAML with named models and tool config:

listen_port: 3000
log_bodies: false
routing_strategy: weighted
models:
  - name: claude-3-5-haiku-latest
    model: llama-3.1-8b-instant
    provider: groq
    api_key: env:GROQ_API_KEY
    api_base: https://api.groq.com/openai/v1
    weight: 3
  - name: claude-3-5-haiku-latest
    model: qwen2.5-coder:32b
    provider: openai
    api_key: unused
    api_base: http://localhost:11434/v1
    weight: 1
tool_execution:
  max_iterations: 6
  tool_timeout_secs: 30
  guardrails: standard
  max_write_payload_bytes: 65536

parse_simple_yaml turns that file into a MultiConfig, a ModelRouter, and a ToolStartupConfig. The server can then build named backends, route by virtual model name, and optionally initialize server-side tool execution from the same document.

tool_execution.guardrails: standard enables Forge-style advisory tool-call guardrails inside the tool loop. The proxy can nudge noisy shell commands, oversized write/edit payloads, and grep/glob symbol lookups when an LSP-style tool is available. FORGE_TOOL_CALL_POLICY=standard can also enable the same preset when a tool engine is already configured.

tool_execution and guardrails are only read from this simple native YAML format (the models: root key) or from FORGE_TOOL_CALL_POLICY. The LiteLLM-compatible model_list: format has no tool sections at all: MultiConfig::load() hard-codes tool_config: None for that branch, so a tool_execution/guardrails block written into a LiteLLM YAML file is silently ignored. This is intentional (not a bug) — see crates/proxy/src/config/multi/loader.rs.

Config precedence is easy to misunderstand. Shell env vars still win over .anyllm.env, .anyllm.env wins over admin-imported env vars from SQLite, and PROXY_CONFIG changes the runtime mode entirely. If a global OPENAI_API_KEY is set in your shell, it can override the provider-specific key fallback for stub backends like Groq or OpenRouter.

Simple mode is defined by the absence of `PROXY_CONFIG`. It is intentionally optimized for a single backend and a pair of model aliases, which makes local development fast and keeps the startup path obvious. Config file mode expands the feature set significantly by enabling named backends, model routers, managed callbacks, tool sections, and degradation headers by default. The trade-off is cognitive load: once `PROXY_CONFIG` is present, you are operating the proxy as infrastructure rather than as a small local helper. The env parser in `crates/proxy/src/env_parser.rs` is pure and safe to call anywhere, which is why the admin import endpoint can validate content before writing it to SQLite. Imported values are convenient because they survive restarts and can be changed from the admin UI, but they intentionally have lower precedence than explicit env files. That makes `.anyllm.env` the source of truth when you want reproducible local behavior, while admin imports are better suited for interactive operations or bootstrap flows. In practice, keep secrets and deployment-critical values in env files or your process manager, and use admin imports for controlled overrides and migrations.