Files
deer-flow/frontend/src/content/en/application/configuration.mdx
T
greatmengqi 3e6a34297d refactor(config): eliminate global mutable state — explicit parameter passing on top of main
Squashes 25 PR commits onto current main. AppConfig becomes a pure value
object with no ambient lookup. Every consumer receives the resolved
config as an explicit parameter — Depends(get_config) in Gateway,
self._app_config in DeerFlowClient, runtime.context.app_config in agent
runs, AppConfig.from_file() at the LangGraph Server registration
boundary.

Phase 1 — frozen data + typed context

- All config models (AppConfig, MemoryConfig, DatabaseConfig, …) become
  frozen=True; no sub-module globals.
- AppConfig.from_file() is pure (no side-effect singleton loaders).
- Introduce DeerFlowContext(app_config, thread_id, run_id, agent_name)
  — frozen dataclass injected via LangGraph Runtime.
- Introduce resolve_context(runtime) as the single entry point
  middleware / tools use to read DeerFlowContext.

Phase 2 — pure explicit parameter passing

- Gateway: app.state.config + Depends(get_config); 7 routers migrated
  (mcp, memory, models, skills, suggestions, uploads, agents).
- DeerFlowClient: __init__(config=...) captures config locally.
- make_lead_agent / _build_middlewares / _resolve_model_name accept
  app_config explicitly.
- RunContext.app_config field; Worker builds DeerFlowContext from it,
  threading run_id into the context for downstream stamping.
- Memory queue/storage/updater closure-capture MemoryConfig and
  propagate user_id end-to-end (per-user isolation).
- Sandbox/skills/community/factories/tools thread app_config.
- resolve_context() rejects non-typed runtime.context.
- Test suite migrated off AppConfig.current() monkey-patches.
- AppConfig.current() classmethod deleted.

Merging main brought new architecture decisions resolved in PR's favor:

- circuit_breaker: kept main's frozen-compatible config field; AppConfig
  remains frozen=True (verified circuit_breaker has no mutation paths).
- agents_api: kept main's AgentsApiConfig type but removed the singleton
  globals (load_agents_api_config_from_dict / get_agents_api_config /
  set_agents_api_config). 8 routes in agents.py now read via
  Depends(get_config).
- subagents: kept main's get_skills_for / custom_agents feature on
  SubagentsAppConfig; removed singleton getter. registry.py now reads
  app_config.subagents directly.
- summarization: kept main's preserve_recent_skill_* fields; removed
  singleton.
- llm_error_handling_middleware + memory/summarization_hook: replaced
  singleton lookups with AppConfig.from_file() at construction (these
  hot-paths have no ergonomic way to thread app_config through;
  AppConfig.from_file is a pure load).
- worker.py + thread_data_middleware.py: DeerFlowContext.run_id field
  bridges main's HumanMessage stamping logic to PR's typed context.

Trade-offs (follow-up work):

- main's #2138 (async memory updater) reverted to PR's sync
  implementation. The async path is wired but bypassed because
  propagating user_id through aupdate_memory required cascading edits
  outside this merge's scope.
- tests/test_subagent_skills_config.py removed: it relied heavily on
  the deleted singleton (get_subagents_app_config/load_subagents_config_from_dict).
  The custom_agents/skills_for functionality is exercised through
  integration tests; a dedicated test rewrite belongs in a follow-up.

Verification: backend test suite — 2560 passed, 4 skipped, 84 failures.
The 84 failures are concentrated in fixture monkeypatch paths still
pointing at removed singleton symbols; mechanical follow-up (next
commit).
2026-04-26 21:45:02 +08:00

274 lines
7.0 KiB
Plaintext

---
title: Configuration
description: DeerFlow App is configured through two files and a set of environment variables. This page covers the application-level configuration that most operators need to set up before deploying.
---
import { Callout, Cards, Tabs } from "nextra/components";
# Configuration
DeerFlow App is configured through two files and a set of environment variables. This page covers the application-level configuration that most operators need to set up before deploying.
## Configuration files
| File | Purpose |
|---|---|
| `config.yaml` | Backend configuration: models, sandbox, tools, skills, memory, and all Harness settings |
| `extensions_config.json` | MCP servers and skill enable/disable state (managed by the App UI and Gateway API) |
Frontend environment variables control the Next.js build and runtime behavior.
## config.yaml
Start by copying the example:
```bash
cp config.example.yaml config.yaml
```
The most important sections for application configuration are:
### Models
Configure the LLM providers the agent can use. At least one model is required.
<Tabs items={["OpenAI", "Anthropic", "DeepSeek", "Ollama", "Gemini"]}>
<Tabs.Tab>
```yaml
models:
- name: gpt-4o
use: langchain_openai:ChatOpenAI
model: gpt-4o
api_key: $OPENAI_API_KEY
request_timeout: 600.0
max_retries: 2
supports_vision: true
```
</Tabs.Tab>
<Tabs.Tab>
```yaml
models:
- name: claude-3-5-sonnet
use: langchain_anthropic:ChatAnthropic
model: claude-3-5-sonnet-20241022
api_key: $ANTHROPIC_API_KEY
default_request_timeout: 600.0
max_retries: 2
max_tokens: 8192
supports_vision: true
supports_thinking: true
when_thinking_enabled:
thinking:
type: enabled
when_thinking_disabled:
thinking:
type: disabled
```
</Tabs.Tab>
<Tabs.Tab>
```yaml
models:
- name: deepseek-v3
use: deerflow.models.patched_deepseek:PatchedChatDeepSeek
model: deepseek-reasoner
api_key: $DEEPSEEK_API_KEY
timeout: 600.0
max_retries: 2
supports_thinking: true
when_thinking_enabled:
extra_body:
thinking:
type: enabled
when_thinking_disabled:
extra_body:
thinking:
type: disabled
```
</Tabs.Tab>
<Tabs.Tab>
```yaml
models:
- name: qwen3-local
use: langchain_ollama:ChatOllama
model: qwen3:32b
base_url: http://localhost:11434 # No /v1 suffix — uses native Ollama API
num_predict: 8192
temperature: 0.7
reasoning: true
supports_thinking: true
supports_vision: false
```
Install Ollama provider: `cd backend && uv add 'deerflow-harness[ollama]'`
<Callout type="warning">
Use <code>langchain_ollama:ChatOllama</code> (not the OpenAI-compatible
endpoint) for Ollama models. The native API correctly separates thinking
content; the OpenAI-compatible endpoint may flatten or drop it.
</Callout>
</Tabs.Tab>
<Tabs.Tab>
```yaml
models:
- name: gemini-2.5-pro
use: langchain_google_genai:ChatGoogleGenerativeAI
model: gemini-2.5-pro
gemini_api_key: $GEMINI_API_KEY
timeout: 600.0
max_retries: 2
max_tokens: 8192
supports_vision: true
```
</Tabs.Tab>
</Tabs>
### Sandbox
Choose the execution environment for agent file and command operations:
<Tabs items={["Local (default)", "Docker container", "K8s Provisioner"]}>
<Tabs.Tab>
```yaml
sandbox:
use: deerflow.sandbox.local:LocalSandboxProvider
allow_host_bash: false # set true only for trusted single-user workflows
```
</Tabs.Tab>
<Tabs.Tab>
```yaml
sandbox:
use: deerflow.community.aio_sandbox:AioSandboxProvider
image: enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest
replicas: 3
idle_timeout: 600
```
Install: `cd backend && uv add 'deerflow-harness[aio-sandbox]'`
</Tabs.Tab>
<Tabs.Tab>
```yaml
sandbox:
use: deerflow.community.aio_sandbox:AioSandboxProvider
provisioner_url: http://provisioner:8002
```
</Tabs.Tab>
</Tabs>
### Tools
Configure which tools the agent has access to. The defaults use DuckDuckGo (no API key) and Jina AI for web operations:
```yaml
tools:
# Web search (choose one)
- use: deerflow.community.ddg_search.tools:web_search_tool # default, no key required
# - use: deerflow.community.tavily.tools:web_search_tool
# api_key: $TAVILY_API_KEY
# Web fetch (choose one)
- use: deerflow.community.jina_ai.tools:web_fetch_tool
# Image search
- use: deerflow.community.image_search.tools:image_search_tool
# File operations
- use: deerflow.sandbox.tools:ls_tool
- use: deerflow.sandbox.tools:read_file_tool
- use: deerflow.sandbox.tools:glob_tool
- use: deerflow.sandbox.tools:grep_tool
- use: deerflow.sandbox.tools:write_file_tool
- use: deerflow.sandbox.tools:str_replace_tool
- use: deerflow.sandbox.tools:bash_tool
```
### Thread state persistence (checkpointer)
By default, DeerFlow uses an SQLite checkpointer for thread state persistence:
```yaml
checkpointer:
type: sqlite
connection_string: checkpoints.db # stored in backend/.deer-flow/
```
For production deployments with multiple processes:
```yaml
checkpointer:
type: postgres
connection_string: postgresql://user:password@localhost:5432/deerflow
```
Install PostgreSQL support: `cd backend && uv add langgraph-checkpoint-postgres psycopg[binary] psycopg-pool`
For in-memory only (state lost on restart):
```yaml
checkpointer:
type: memory
```
### Memory
```yaml
memory:
enabled: true
storage_path: memory.json
debounce_seconds: 30
max_facts: 100
injection_enabled: true
max_injection_tokens: 2000
```
## Frontend environment variables
Set these before running `pnpm build` or starting the frontend in production:
| Variable | Required | Description |
|---|---|---|
| `BETTER_AUTH_SECRET` | **Required** in production | Secret for session signing. Use `openssl rand -base64 32`. |
| `BETTER_AUTH_URL` | Recommended | Public-facing base URL (e.g., `https://your-domain.com`) |
| `SKIP_ENV_VALIDATION` | Optional | Set to `1` to skip env validation during build (not recommended) |
| `NEXT_PUBLIC_API_URL` | Optional | Override the API base URL for the frontend |
In development, set these in a `.env` file at the repo root:
```bash
BETTER_AUTH_SECRET=your-strong-secret-here-min-32-chars
```
## extensions_config.json
This file manages MCP server connections and skill enable/disable state. It is created automatically when you first manage extensions through the App UI or Gateway API.
Manual example:
```json
{
"mcpServers": {
"my-server": {
"command": "npx",
"args": ["-y", "@my-org/my-mcp-server"],
"enabled": true
}
},
"skills": {
"deep-research": { "enabled": true },
"data-analysis": { "enabled": true }
}
}
```
## Config upgrade
When the config schema changes, `config_version` is bumped. To merge new fields into your existing config without losing customizations:
```bash
make config-upgrade
```
<Cards num={2}>
<Cards.Card title="Deployment Guide" href="/docs/application/deployment-guide" />
<Cards.Card title="Harness Configuration" href="/docs/harness/configuration" />
</Cards>