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_idvalues when callingchat()orstream()to maintain file uploads, titles, and artifacts across conversation turns. - Upload files before referencing them in prompts to allow
UploadsMiddlewareto automatically inject the<uploaded_files>block. - Manage skill states via
list_skills()andupdate_skill(), knowing that changes write toextensions_config.jsonand 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.pyor viaconfig.yamlto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →