---
title: Configuration
description: "DeerFlow's configuration system is designed around one goal: every meaningful behavior should be expressible in a config file, not hardcoded in the application. This makes deployments reproducible, auditable, and easy to customize per environment."
---

import { Callout, Cards } from "nextra/components";

# Configuration

<Callout type="info" emoji="⚙️">
  All DeerFlow Harness behaviors are driven by <code>config.yaml</code>. One
  file controls which models are available, how the sandbox runs, what tools are
  loaded, and how each subsystem behaves.
</Callout>

DeerFlow's configuration system is designed around one goal: every meaningful behavior should be expressible in a config file, not hardcoded in the application. This makes deployments reproducible, auditable, and easy to customize per environment.

## Config file location

DeerFlow resolves `config.yaml` using the following priority order:

1. The path passed to `AppConfig.from_file(config_path)` explicitly.
2. The `DEER_FLOW_CONFIG_PATH` environment variable.
3. `backend/config.yaml` (relative to the backend directory).
4. `config.yaml` in the repository root.

If none of these paths exist, the application raises an error at startup.

To use a custom location:

```bash
export DEER_FLOW_CONFIG_PATH=/path/to/my-config.yaml
```

## Environment variable interpolation

Any field value can reference an environment variable using `$VAR_NAME` syntax:

```yaml
models:
  - name: gpt-4o
    api_key: $OPENAI_API_KEY
```

This keeps secrets out of the config file itself. The variable is resolved at runtime from the process environment.

## The `use` field

Many configuration entries use a `use:` field to specify the Python class or object to instantiate. The format is:

```
package.subpackage.module:ClassName
```

or for module-level objects:

```
package.subpackage.module:variable_name
```

Examples:

```yaml
sandbox:
  use: deerflow.sandbox.local:LocalSandboxProvider

tools:
  - use: deerflow.community.tavily.tools:web_search_tool
    api_key: $TAVILY_API_KEY
```

This pattern is how DeerFlow achieves pluggability without hardcoding class references.

## Extra fields are passed through

For model configuration, `ModelConfig` uses `pydantic ConfigDict(extra="allow")`. This means any extra fields you add under a model entry are passed directly to the model constructor. This allows provider-specific options (like `extra_body`, `reasoning`, or custom timeout keys) to work without modifying the harness:

```yaml
models:
  - name: my-model
    use: langchain_openai:ChatOpenAI
    model: gpt-4o
    api_key: $OPENAI_API_KEY
    some_provider_specific_option: value  # passed through to ChatOpenAI constructor
```

## Configuration version

`config.yaml` includes a `config_version` field that tracks the schema version:

```yaml
config_version: 6
```

When the schema changes (new fields, renamed sections), this number is bumped. If your local `config.yaml` is behind the current version, run:

```bash
make config-upgrade
```

This merges new fields from `config.example.yaml` into your existing `config.yaml` without overwriting your customizations.

## Module configuration reference

The following table maps each top-level `config.yaml` section to its documentation page:

| Section | Description | Documentation |
|---|---|---|
| `log_level` | Logging level (`debug`/`info`/`warning`/`error`) | — |
| `models` | Available LLM models | [Lead Agent](/docs/harness/lead-agent) |
| `token_usage` | Token tracking per model call | [Middlewares](/docs/harness/middlewares) |
| `tools` | Available agent tools | [Tools](/docs/harness/tools) |
| `tool_groups` | Named groups of tools | [Tools](/docs/harness/tools) |
| `tool_search` | Deferred/on-demand tool loading | [Tools](/docs/harness/tools) |
| `sandbox` | Sandbox provider and options | [Sandbox](/docs/harness/sandbox) |
| `skills` | Skills directory and container path | [Skills](/docs/harness/skills) |
| `skill_evolution` | Agent-managed skill creation | [Skills](/docs/harness/skills) |
| `subagents` | Subagent timeouts and max turns | [Subagents](/docs/harness/subagents) |
| `acp_agents` | External ACP agent integrations | [Subagents](/docs/harness/subagents) |
| `memory` | Cross-session memory storage | [Memory](/docs/harness/memory) |
| `summarization` | Conversation summarization | [Middlewares](/docs/harness/middlewares) |
| `title` | Automatic thread title generation | [Middlewares](/docs/harness/middlewares) |
| `checkpointer` | Thread state persistence | [Agents & Threads](/docs/application/agents-and-threads) |
| `guardrails` | Tool call authorization | — |
| `stream_bridge` | Streaming configuration | — |
| `uploads` | File upload settings (PDF converter) | — |
| `channels` | IM channel integrations (Feishu, Slack, etc.) | — |

## Minimal config to get started

The minimum valid `config.yaml` requires at least one model and a sandbox:

```yaml
config_version: 6

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

sandbox:
  use: deerflow.sandbox.local:LocalSandboxProvider

tools:
  - use: deerflow.community.ddg_search.tools:web_search_tool
  - use: deerflow.community.jina_ai.tools:web_fetch_tool
  - use: deerflow.sandbox.tools:ls_tool
  - use: deerflow.sandbox.tools:read_file_tool
  - use: deerflow.sandbox.tools:write_file_tool
  - use: deerflow.sandbox.tools:bash_tool
```

Start from `config.example.yaml` in the repository root and uncomment the sections you need.

<Cards num={2}>
  <Cards.Card title="Deployment Guide" href="/docs/application/deployment-guide" />
  <Cards.Card title="Application Configuration" href="/docs/application/configuration" />
</Cards>
