- 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>
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, andMultiConfig, 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:
- resolve the data directory and locate
.anyllm.env - load file-based env vars before Tokio starts
- compute LiteLLM env aliases
- apply env vars previously imported into SQLite through the admin UI
- auto-detect
config.yamlintoPROXY_CONFIGwhen present - if the config is LiteLLM YAML, extract
general_settings.master_keyearly - only then build the async runtime
MultiConfig::load in crates/proxy/src/config/mod.rs uses the following detection rules:
PROXY_CONFIGending in.yamlor.ymlwith a top-levelmodels:key -> simple native YAMLPROXY_CONFIGending in.yamlor.ymlwithmodel_list:-> LiteLLM-compatible YAML- any other
PROXY_CONFIGfile -> TOML multi-backend config - no
PROXY_CONFIG-> env-onlyConfig::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.