Contributing to DeerFlow Backend
Thank you for your interest in contributing to DeerFlow! This document provides guidelines and instructions for contributing to the backend codebase.
Table of Contents
- Getting Started
- Development Setup
- Project Structure
- Code Style
- Making Changes
- Testing
- Pull Request Process
- Architecture Guidelines
Getting Started
Prerequisites
- Python 3.12 or higher
- uv package manager
- Git
- Docker (optional, for Docker sandbox testing)
Fork and Clone
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/deer-flow.git cd deer-flow
Development Setup
Install Dependencies
# From project root
cp config.example.yaml config.yaml
# Install backend dependencies
cd backend
make install
Configure Environment
Set up your API keys for testing:
export OPENAI_API_KEY="your-api-key"
# Add other keys as needed
Run the Development Server
# Terminal 1: LangGraph server
make dev
# Terminal 2: Gateway API
make gateway
Project Structure
backend/src/
βββ agents/ # Agent system
β βββ lead_agent/ # Main agent implementation
β β βββ agent.py # Agent factory and creation
β βββ middlewares/ # Agent middlewares
β β βββ thread_data_middleware.py
β β βββ sandbox_middleware.py
β β βββ title_middleware.py
β β βββ uploads_middleware.py
β β βββ view_image_middleware.py
β β βββ clarification_middleware.py
β βββ thread_state.py # Thread state definition
β
βββ gateway/ # FastAPI Gateway
β βββ app.py # FastAPI application
β βββ routers/ # Route handlers
β βββ models.py # /api/models endpoints
β βββ mcp.py # /api/mcp endpoints
β βββ skills.py # /api/skills endpoints
β βββ artifacts.py # /api/threads/.../artifacts
β βββ uploads.py # /api/threads/.../uploads
β
βββ sandbox/ # Sandbox execution
β βββ __init__.py # Sandbox interface
β βββ local.py # Local sandbox provider
β βββ tools.py # Sandbox tools (bash, file ops)
β
βββ tools/ # Agent tools
β βββ builtins/ # Built-in tools
β βββ present_file_tool.py
β βββ ask_clarification_tool.py
β βββ view_image_tool.py
β
βββ mcp/ # MCP integration
β βββ manager.py # MCP server management
β
βββ models/ # Model system
β βββ factory.py # Model factory
β
βββ skills/ # Skills system
β βββ loader.py # Skills loader
β
βββ config/ # Configuration
β βββ app_config.py # Main app config
β βββ extensions_config.py # Extensions config
β βββ summarization_config.py
β
βββ community/ # Community tools
β βββ tavily/ # Tavily web search
β βββ jina/ # Jina web fetch
β βββ firecrawl/ # Firecrawl scraping
β βββ aio_sandbox/ # Docker sandbox
β
βββ reflection/ # Dynamic loading
β βββ __init__.py # Module resolution
β
βββ utils/ # Utilities
βββ __init__.py
Code Style
Linting and Formatting
We use ruff for both linting and formatting:
# Check for issues
make lint
# Auto-fix and format
make format
Style Guidelines
- Line length: 240 characters maximum
- Python version: 3.12+ features allowed
- Type hints: Use type hints for function signatures
- Quotes: Double quotes for strings
- Indentation: 4 spaces (no tabs)
- Imports: Group by standard library, third-party, local
Docstrings
Use docstrings for public functions and classes:
def create_chat_model(name: str, thinking_enabled: bool = False) -> BaseChatModel:
"""Create a chat model instance from configuration.
Args:
name: The model name as defined in config.yaml
thinking_enabled: Whether to enable extended thinking
Returns:
A configured LangChain chat model instance
Raises:
ValueError: If the model name is not found in configuration
"""
...
Making Changes
Branch Naming
Use descriptive branch names:
feature/add-new-tool- New featuresfix/sandbox-timeout- Bug fixesdocs/update-readme- Documentationrefactor/config-system- Code refactoring
Commit Messages
Write clear, concise commit messages:
feat: add support for Claude 3.5 model
- Add model configuration in config.yaml
- Update model factory to handle Claude-specific settings
- Add tests for new model
Prefix types:
feat:- New featurefix:- Bug fixdocs:- Documentationrefactor:- Code refactoringtest:- Testschore:- Build/config changes
Testing
Running Tests
uv run pytest
Writing Tests
Place tests in the tests/ directory mirroring the source structure:
tests/
βββ test_models/
β βββ test_factory.py
βββ test_sandbox/
β βββ test_local.py
βββ test_gateway/
βββ test_models_router.py
Example test:
import pytest
from src.models.factory import create_chat_model
def test_create_chat_model_with_valid_name():
"""Test that a valid model name creates a model instance."""
model = create_chat_model("gpt-4")
assert model is not None
def test_create_chat_model_with_invalid_name():
"""Test that an invalid model name raises ValueError."""
with pytest.raises(ValueError):
create_chat_model("nonexistent-model")
Pull Request Process
Before Submitting
- Ensure tests pass:
uv run pytest - Run linter:
make lint - Format code:
make format - Update documentation if needed
PR Description
Include in your PR description:
- What: Brief description of changes
- Why: Motivation for the change
- How: Implementation approach
- Testing: How you tested the changes
Review Process
- Submit PR with clear description
- Address review feedback
- Ensure CI passes
- Maintainer will merge when approved
Architecture Guidelines
Adding New Tools
- Create tool in
src/tools/builtins/orsrc/community/:
# src/tools/builtins/my_tool.py
from langchain_core.tools import tool
@tool
def my_tool(param: str) -> str:
"""Tool description for the agent.
Args:
param: Description of the parameter
Returns:
Description of return value
"""
return f"Result: {param}"
- Register in
config.yaml:
tools:
- name: my_tool
group: my_group
use: src.tools.builtins.my_tool:my_tool
Adding New Middleware
- Create middleware in
src/agents/middlewares/:
# src/agents/middlewares/my_middleware.py
from langchain.agents.middleware import BaseMiddleware
from langchain_core.runnables import RunnableConfig
class MyMiddleware(BaseMiddleware):
"""Middleware description."""
def transform_state(self, state: dict, config: RunnableConfig) -> dict:
"""Transform the state before agent execution."""
# Modify state as needed
return state
- Register in
src/agents/lead_agent/agent.py:
middlewares = [
ThreadDataMiddleware(),
SandboxMiddleware(),
MyMiddleware(), # Add your middleware
TitleMiddleware(),
ClarificationMiddleware(),
]
Adding New API Endpoints
- Create router in
src/gateway/routers/:
# src/gateway/routers/my_router.py
from fastapi import APIRouter
router = APIRouter(prefix="/my-endpoint", tags=["my-endpoint"])
@router.get("/")
async def get_items():
"""Get all items."""
return {"items": []}
@router.post("/")
async def create_item(data: dict):
"""Create a new item."""
return {"created": data}
- Register in
src/gateway/app.py:
from src.gateway.routers import my_router
app.include_router(my_router.router)
Configuration Changes
When adding new configuration options:
- Update
src/config/app_config.pywith new fields - Add default values in
config.example.yaml - Document in
docs/CONFIGURATION.md
MCP Server Integration
To add support for a new MCP server:
- Add configuration in
extensions_config.json:
{
"mcpServers": {
"my-server": {
"enabled": true,
"type": "stdio",
"command": "npx",
"args": ["-y", "@my-org/mcp-server"],
"description": "My MCP Server"
}
}
}
- Update
extensions_config.example.jsonwith the new server
Skills Development
To create a new skill:
- Create directory in
skills/public/orskills/custom/:
skills/public/my-skill/
βββ SKILL.md
- Write
SKILL.mdwith YAML front matter:
---
name: My Skill
description: What this skill does
license: MIT
allowed-tools:
- read_file
- write_file
- bash
---
# My Skill
Instructions for the agent when this skill is enabled...
Questions?
If you have questions about contributing:
- Check existing documentation in
docs/ - Look for similar issues or PRs on GitHub
- Open a discussion or issue on GitHub
Thank you for contributing to DeerFlow!