DeerFlow Best Practices: Configuring ByteDance's Super-Agent Harness

DeerFlow best practices revolve around proper configuration of the TitleMiddleware for automatic thread naming, leveraging the UploadsMiddleware for seamless file injection, and utilizing the embedded Python client with persistent thread IDs to maintain state across multi-turn conversations.

DeerFlow is a super-agent harness developed by ByteDance that orchestrates sub-agents, long-term memory, and sandboxed execution through an extensible skill system. Following DeerFlow best practices ensures optimal resource utilization, consistent thread management, and reliable file processing when building production AI applications. This guide references the actual bytedance/deer-flow source code to demonstrate authoritative configuration patterns and implementation details.

Core Architecture and Configuration

Understanding the middleware stack and configuration loading mechanisms is essential for optimizing DeerFlow performance.

Title Generation and Thread State Management

DeerFlow automatically generates concise thread titles after the first user-assistant exchange through the TitleMiddleware. Located in backend/src/agents/middlewares/title_middleware.py (lines 24-92), this component stores titles in the ThreadState schema defined in backend/src/agents/thread_state.py (lines 48-55). The thread state serves as a unified container for sandbox IDs, file uploads, artifacts, and viewed images across all middlewares.

Configuration defaults reside in backend/src/config/title_config.py (lines 6-33), including parameters like max_words and prompt_template. The AppConfig loader in backend/src/config/app_config.py (lines 81-84) reads these values from config.yaml at startup, resolving environment variables and injecting them into a singleton instance.

Configuration Loading Patterns

The system uses a centralized configuration approach where AppConfig.from_file processes your config.yaml and populates global configuration objects. This singleton pattern means any changes to environment variables or configuration files reflect immediately in the embedded client without server restarts.

Working with the Embedded Python Client

The DeerFlowClient in backend/src/client.py provides a thin, in-process API that mirrors the HTTP gateway while maintaining agent caching for performance.

Client Initialization and Caching

Always reuse the same client instance across calls to benefit from internal agent caching. The client reads the same configuration as the HTTP gateway, ensuring consistency between programmatic and REST API usage.

from src.client import DeerFlowClient

# Re-use the same client across calls – the internal agent is cached.

client = DeerFlowClient()

Streaming vs. One-Shot Execution

For simple synchronous interactions, use DeerFlowClient.chat (lines 66-89 in backend/src/client.py), which streams internally and returns the final AI message. For interactive UIs, use client.stream to process partial outputs and tool invocations in real-time.


# One-shot chat for simple use cases

response = client.chat(
    "Summarize the key takeaways from the 2024 State of AI report."
)
print(response)

# Streaming for rich UI updates

for event in client.stream(
    "Explain the differences between RAG and traditional search.",
    thread_id="demo-001",  # Persistent ID maintains context

):
    if event.type == "messages-tuple" and event.data["type"] == "ai":
        print(event.data["content"], end="", flush=True)

Supplying a consistent thread_id parameter ensures the check-pointer persists state including uploaded files and generated titles across conversation turns.

File Handling and Middleware Integration

DeerFlow handles file uploads through middleware that automatically injects metadata into prompts, eliminating the need for manual file reference formatting.

UploadsMiddleware Implementation

The UploadsMiddleware in backend/src/agents/middlewares/uploads_middleware.py (lines 23-204) reads file metadata from HumanMessage objects, gathers historical uploads from the thread state, and prepends an <uploaded_files> block to the message. This makes files discoverable by tools like read_file without manual intervention.

File Upload Workflow

Upload files before referencing them in prompts. The client automatically converts PDFs to markdown and registers them in the thread state.


# Upload a PDF (automatically converts to markdown)

upload_res = client.upload_files(
    thread_id="demo-001",
    files=["./reports/2024_state_of_ai.pdf"]
)
print(upload_res["files"][0]["markdown_file"])

# The middleware automatically injects file context

summary = client.chat(
    "Provide a concise summary of the uploaded PDF.",
    thread_id="demo-001"
)

Managing Skills and Toolsets

Skills extend DeerFlow's capabilities through modular toolsets loaded dynamically from the filesystem.

Dynamic Skill Loading

The Skill Loader in backend/src/skills/loader.py (lines 22-98) scans skills/public and skills/custom directories, parsing each SKILL.md file and merging enablement states from extensions_config.json. This hot-reloading mechanism allows runtime skill toggling without restarting the server.

Runtime Skill Configuration

Use the embedded client to inspect and modify skill states programmatically:


# List all loaded skills (enabled & disabled)

all_skills = client.list_skills()
print([s["name"] for s in all_skills["skills"]])

# Enable a custom skill at runtime

client.update_skill("my-awesome-skill", enabled=True)

The update_skill method rewrites extensions_config.json, and subsequent calls to load_skills immediately reflect the change.

Advanced Agent Configuration

Fine-tuning sub-agent behavior and memory persistence prevents resource exhaustion and optimizes latency.

Sub-Agent Concurrency Control

When enabling sub-agents via subagent_enabled=True, the system respects the SubAgentLimitMiddleware in backend/src/agents/middlewares/subagent_limit_middleware.py. By default, this caps concurrency at 3 simultaneous sub-agents to prevent runaway resource usage. Adjust this limit in the source if your use case requires higher parallelism, or disable sub-agents entirely for deterministic single-agent execution.

client = DeerFlowClient(
    subagent_enabled=True,    # Enable delegation

    plan_mode=False,         # Keep simple turn-based flow

    thinking_enabled=True,
)

Memory and Persistence Tuning

The MemoryMiddleware in backend/src/agents/middlewares/memory_middleware.py handles long-term memory injection. Disable the check-pointer in your configuration if you don't require cross-session context, reducing I/O overhead for stateless interactions. For persistent deployments, ensure your memory_config.yaml properly configures the vector store backend.

Control title generation overhead by setting enabled: false in the title block of config.yaml, or pass custom configurations directly to the client constructor for specific runs.

Summary

  • Reuse the DeerFlowClient instance to leverage internal agent caching and reduce initialization overhead.
  • Supply consistent thread_id values when calling chat() or stream() to maintain file uploads, titles, and artifacts across conversation turns.
  • Upload files before referencing them in prompts to allow UploadsMiddleware to automatically inject the <uploaded_files> block.
  • Manage skill states via list_skills() and update_skill(), knowing that changes write to extensions_config.json and take effect immediately.
  • Respect the default sub-agent limit of 3 concurrent agents defined in subagent_limit_middleware.py, or disable sub-agents for deterministic execution.
  • Configure title generation in title_config.py or via config.yaml to control automatic thread naming behavior and reduce latency when disabled.
  • Enable check-pointing and MemoryMiddleware only when necessary for cross-session persistence, otherwise disable to minimize I/O.

Frequently Asked Questions

How do I disable automatic title generation in DeerFlow?

Set enabled: false in the title block of your config.yaml, or ensure the title configuration block is absent entirely. When disabled, the TitleMiddleware._should_generate_title method short-circuits and no title is stored in the ThreadState. You can also override this per-client instance by passing a custom configuration dictionary to DeerFlowClient.

What is the default concurrency limit for sub-agents in DeerFlow?

The default limit is 3 concurrent sub-agents, enforced by the SubAgentLimitMiddleware in backend/src/agents/middlewares/subagent_limit_middleware.py. This prevents resource exhaustion when the super-agent spawns parallel research or computation tasks. You can modify this limit by editing the middleware source code if your infrastructure supports higher parallelism.

How does DeerFlow handle file uploads across multiple conversation turns?

The UploadsMiddleware in backend/src/agents/middlewares/uploads_middleware.py maintains a cumulative list of uploaded files in the ThreadState. When you provide a persistent thread_id, the middleware prepends an <uploaded_files> block containing both new and historical uploads to every HumanMessage, making all files accessible to tools like read_file throughout the conversation history.

Where does DeerFlow store skill enablement configuration?

Skill enablement states are stored in extensions_config.json at the project root. The load_skills function in backend/src/skills/loader.py (lines 22-98) reads this file alongside SKILL.md manifests from skills/public and skills/custom directories. When you call client.update_skill(), the system rewrites this JSON file, and the next request immediately picks up the new state because load_skills reloads the configuration on every invocation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →