bytedance/deer-flowPublic

An open-source long-horizon SuperAgent harness that researches, codes, and creates. With the help of sandboxes, memories, tools, skill, subagents and message gateway, it handles different levels of tasks that could take minutes to hours.

AI summary: An open-source super-agent framework that orchestrates sub-agents, memory, and sandboxes to perform deep exploration and research.

Stars
83.4K
+68 today
Forks
11.6K
Watchers
338
Open issues
520
Open PRs
376
Contributors
~499
Commits
3.7K
Branches
41

PythonMITCreated May 7, 2025Last push todayLatest release v2.1.0+402 stars this week+2K this month

Quick answers

What is deer-flow?
An open-source super-agent framework that orchestrates sub-agents, memory, and sandboxes to perform deep exploration and research.
What does deer-flow do?
DeerFlow acts as a highly extensible super-agent harness designed to tackle complex, long-horizon tasks that may take minutes to hours to execute. It systematically coordinates multiple specialized sub-agents alongside managed memory and secure execution sandboxes to automate intricate coding, research, and data gathering workflows. Version 2.0 represents a complete, ground-up rewrite focused on robust task orchestration and integrating intelligent external toolsets, such as deep search and crawling. The framework natively supports seamless integration with various LLM providers and enables developers to trace complex multi-step reasoning natively via LangSmith.
Who is deer-flow for?
AI researchers and senior software engineers looking to build, orchestrate, and debug extremely complex, long-running multi-agent workflows.
How do I get started with deer-flow?
npm install -g @bytedance/deer-flow
How popular is deer-flow on GitHub?
bytedance/deer-flow has 83,385 stars and 11,577 forks on GitHub, and gained 402 stars in the last 7 days.
What license does deer-flow use?
bytedance/deer-flow is released under the MIT license.

Star history

since Jul 28, 2026
025K50K75KJul 2026Aug 2026Sep 2026Oct 2026
83.4K stars as of Oct 4, 2026. Measured daily since Jul 28, 2026; GitHub no longer exposes earlier star timestamps.

Contribution activity

commits per day, last 52 weeks
OctNovDecJanFebMarAprMayJunJulAugSepMonWedFri2025-10-05: 1 commit2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 2 commits2025-10-12: 1 commit2025-10-13: 1 commit2025-10-14: 1 commit2025-10-15: 3 commits2025-10-16: 4 commits2025-10-17: 1 commit2025-10-18: 0 commits2025-10-19: 3 commits2025-10-20: 2 commits2025-10-21: 4 commits2025-10-22: 5 commits2025-10-23: 2 commits2025-10-24: 5 commits2025-10-25: 2 commits2025-10-26: 4 commits2025-10-27: 4 commits2025-10-28: 2 commits2025-10-29: 1 commit2025-10-30: 0 commits2025-10-31: 1 commit2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 1 commit2025-11-07: 0 commits2025-11-08: 0 commits2025-11-09: 0 commits2025-11-10: 1 commit2025-11-11: 1 commit2025-11-12: 0 commits2025-11-13: 0 commits2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 0 commits2025-11-17: 1 commit2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 0 commits2025-11-21: 2 commits2025-11-22: 2 commits2025-11-23: 0 commits2025-11-24: 2 commits2025-11-25: 1 commit2025-11-26: 0 commits2025-11-27: 3 commits2025-11-28: 4 commits2025-11-29: 3 commits2025-11-30: 0 commits2025-12-01: 0 commits2025-12-02: 3 commits2025-12-03: 0 commits2025-12-04: 1 commit2025-12-05: 1 commit2025-12-06: 2 commits2025-12-07: 0 commits2025-12-08: 1 commit2025-12-09: 1 commit2025-12-10: 1 commit2025-12-11: 1 commit2025-12-12: 1 commit2025-12-13: 1 commit2025-12-14: 0 commits2025-12-15: 2 commits2025-12-16: 1 commit2025-12-17: 2 commits2025-12-18: 0 commits2025-12-19: 1 commit2025-12-20: 0 commits2025-12-21: 2 commits2025-12-22: 0 commits2025-12-23: 2 commits2025-12-24: 0 commits2025-12-25: 3 commits2025-12-26: 2 commits2025-12-27: 1 commit2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 2 commits2025-12-31: 0 commits2026-01-01: 1 commit2026-01-02: 0 commits2026-01-03: 0 commits2026-01-04: 0 commits2026-01-05: 1 commit2026-01-06: 2 commits2026-01-07: 2 commits2026-01-08: 0 commits2026-01-09: 3 commits2026-01-10: 1 commit2026-01-11: 0 commits2026-01-12: 0 commits2026-01-13: 0 commits2026-01-14: 25 commits2026-01-15: 14 commits2026-01-16: 56 commits2026-01-17: 71 commits2026-01-18: 26 commits2026-01-19: 26 commits2026-01-20: 25 commits2026-01-21: 25 commits2026-01-22: 39 commits2026-01-23: 15 commits2026-01-24: 52 commits2026-01-25: 25 commits2026-01-26: 11 commits2026-01-27: 10 commits2026-01-28: 22 commits2026-01-29: 52 commits2026-01-30: 16 commits2026-01-31: 30 commits2026-02-01: 24 commits2026-02-02: 59 commits2026-02-03: 24 commits2026-02-04: 9 commits2026-02-05: 9 commits2026-02-06: 69 commits2026-02-07: 33 commits2026-02-08: 28 commits2026-02-09: 61 commits2026-02-10: 8 commits2026-02-11: 3 commits2026-02-12: 2 commits2026-02-13: 5 commits2026-02-14: 7 commits2026-02-15: 1 commit2026-02-16: 0 commits2026-02-17: 0 commits2026-02-18: 3 commits2026-02-19: 1 commit2026-02-20: 0 commits2026-02-21: 3 commits2026-02-22: 0 commits2026-02-23: 0 commits2026-02-24: 4 commits2026-02-25: 8 commits2026-02-26: 3 commits2026-02-27: 2 commits2026-02-28: 4 commits2026-03-01: 6 commits2026-03-02: 4 commits2026-03-03: 2 commits2026-03-04: 5 commits2026-03-05: 5 commits2026-03-06: 7 commits2026-03-07: 1 commit2026-03-08: 8 commits2026-03-09: 4 commits2026-03-10: 8 commits2026-03-11: 8 commits2026-03-12: 2 commits2026-03-13: 10 commits2026-03-14: 7 commits2026-03-15: 0 commits2026-03-16: 4 commits2026-03-17: 7 commits2026-03-18: 7 commits2026-03-19: 1 commit2026-03-20: 5 commits2026-03-21: 2 commits2026-03-22: 9 commits2026-03-23: 8 commits2026-03-24: 13 commits2026-03-25: 15 commits2026-03-26: 15 commits2026-03-27: 15 commits2026-03-28: 8 commits2026-03-29: 20 commits2026-03-30: 12 commits2026-03-31: 8 commits2026-04-01: 13 commits2026-04-02: 11 commits2026-04-03: 17 commits2026-04-04: 10 commits2026-04-05: 11 commits2026-04-06: 15 commits2026-04-07: 12 commits2026-04-08: 8 commits2026-04-09: 14 commits2026-04-10: 14 commits2026-04-11: 12 commits2026-04-12: 9 commits2026-04-13: 2 commits2026-04-14: 10 commits2026-04-15: 6 commits2026-04-16: 6 commits2026-04-17: 1 commit2026-04-18: 10 commits2026-04-19: 6 commits2026-04-20: 5 commits2026-04-21: 2 commits2026-04-22: 2 commits2026-04-23: 7 commits2026-04-24: 10 commits2026-04-25: 5 commits2026-04-26: 22 commits2026-04-27: 0 commits2026-04-28: 12 commits2026-04-29: 0 commits2026-04-30: 10 commits2026-05-01: 8 commits2026-05-02: 7 commits2026-05-03: 1 commit2026-05-04: 6 commits2026-05-05: 5 commits2026-05-06: 2 commits2026-05-07: 5 commits2026-05-08: 9 commits2026-05-09: 12 commits2026-05-10: 5 commits2026-05-11: 7 commits2026-05-12: 8 commits2026-05-13: 4 commits2026-05-14: 1 commit2026-05-15: 7 commits2026-05-16: 3 commits2026-05-17: 5 commits2026-05-18: 3 commits2026-05-19: 2 commits2026-05-20: 10 commits2026-05-21: 13 commits2026-05-22: 5 commits2026-05-23: 8 commits2026-05-24: 0 commits2026-05-25: 1 commit2026-05-26: 7 commits2026-05-27: 1 commit2026-05-28: 11 commits2026-05-29: 8 commits2026-05-30: 1 commit2026-05-31: 2 commits2026-06-01: 3 commits2026-06-02: 3 commits2026-06-03: 9 commits2026-06-04: 1 commit2026-06-05: 2 commits2026-06-06: 2 commits2026-06-07: 7 commits2026-06-08: 15 commits2026-06-09: 11 commits2026-06-10: 7 commits2026-06-11: 6 commits2026-06-12: 11 commits2026-06-13: 13 commits2026-06-14: 8 commits2026-06-15: 1 commit2026-06-16: 4 commits2026-06-17: 14 commits2026-06-18: 7 commits2026-06-19: 18 commits2026-06-20: 5 commits2026-06-21: 18 commits2026-06-22: 8 commits2026-06-23: 13 commits2026-06-24: 11 commits2026-06-25: 9 commits2026-06-26: 2 commits2026-06-27: 5 commits2026-06-28: 5 commits2026-06-29: 0 commits2026-06-30: 2 commits2026-07-01: 9 commits2026-07-02: 10 commits2026-07-03: 14 commits2026-07-04: 23 commits2026-07-05: 9 commits2026-07-06: 15 commits2026-07-07: 10 commits2026-07-08: 4 commits2026-07-09: 12 commits2026-07-10: 14 commits2026-07-11: 23 commits2026-07-12: 26 commits2026-07-13: 14 commits2026-07-14: 27 commits2026-07-15: 14 commits2026-07-16: 13 commits2026-07-17: 10 commits2026-07-18: 9 commits2026-07-19: 16 commits2026-07-20: 14 commits2026-07-21: 24 commits2026-07-22: 16 commits2026-07-23: 15 commits2026-07-24: 13 commits2026-07-25: 11 commits2026-07-26: 25 commits2026-07-27: 18 commits2026-07-28: 24 commits2026-07-29: 21 commits2026-07-30: 9 commits2026-07-31: 11 commits2026-08-01: 12 commits2026-08-02: 8 commits2026-08-03: 2 commits2026-08-04: 6 commits2026-08-05: 7 commits2026-08-06: 0 commits2026-08-07: 2 commits2026-08-08: 7 commits2026-08-09: 0 commits2026-08-10: 3 commits2026-08-11: 16 commits2026-08-12: 3 commits2026-08-13: 4 commits2026-08-14: 9 commits2026-08-15: 7 commits2026-08-16: 7 commits2026-08-17: 8 commits2026-08-18: 1 commit2026-08-19: 2 commits2026-08-20: 1 commit2026-08-21: 0 commits2026-08-22: 8 commits2026-08-23: 9 commits2026-08-24: 17 commits2026-08-25: 9 commits2026-08-26: 0 commits2026-08-27: 11 commits2026-08-28: 6 commits2026-08-29: 9 commits2026-08-30: 17 commits2026-08-31: 7 commits2026-09-01: 19 commits2026-09-02: 16 commits2026-09-03: 9 commits2026-09-04: 10 commits2026-09-05: 2 commits2026-09-06: 18 commits2026-09-07: 4 commits2026-09-08: 19 commits2026-09-09: 8 commits2026-09-10: 8 commits2026-09-11: 10 commits2026-09-12: 30 commits2026-09-13: 10 commits2026-09-14: 28 commits2026-09-15: 12 commits2026-09-16: 26 commits2026-09-17: 23 commits2026-09-18: 24 commits2026-09-19: 12 commits2026-09-20: 29 commits2026-09-21: 5 commits2026-09-22: 39 commits2026-09-23: 27 commits2026-09-24: 43 commits2026-09-25: 31 commits2026-09-26: 14 commits2026-09-27: 30 commits2026-09-28: 31 commits2026-09-29: 11 commits2026-09-30: 38 commits2026-10-01: 32 commits2026-10-02: 0 commits2026-10-03: 0 commits
3,185 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Landmark project

    83,385 stars

  • Very active

    3,185 commits in 52 weeks

  • Community-driven

    ~499 contributors

  • Well documented

    High community health score

  • Permissive license

    MIT

  • Continuous integration

    Automated checks passing

  • Repeat trending

    21 trending appearances

  • Top 10% tracked

    Rank 97 of 1135

What deer-flow does

DeerFlow acts as a highly extensible super-agent harness designed to tackle complex, long-horizon tasks that may take minutes to hours to execute. It systematically coordinates multiple specialized sub-agents alongside managed memory and secure execution sandboxes to automate intricate coding, research, and data gathering workflows. Version 2.0 represents a complete, ground-up rewrite focused on robust task orchestration and integrating intelligent external toolsets, such as deep search and crawling. The framework natively supports seamless integration with various LLM providers and enables developers to trace complex multi-step reasoning natively via LangSmith.

AI researchers and senior software engineers looking to build, orchestrate, and debug extremely complex, long-running multi-agent workflows.

  • Sub-Agent Orchestration: Dynamically routes complex tasks to specialized, highly focused sub-agents to parallelize long-horizon workflows.
  • Sandbox Execution: Encloses task execution within highly secure environment sandboxes, allowing agents to write and test code safely.
  • Integrated Memory Management: Persists context and intermediate reasoning securely across extremely long, multi-hour agent operations.
  • Extensible Skill System: Allows developers to rapidly plug in new custom tools, APIs, and domain-specific capabilities into the agent framework.
  • InfoQuest Integration: Bundles out-of-the-box support for advanced intelligent search and deep crawling toolsets directly into the harness.
  • Desktop Inspection Tooling: Pairs natively with the LLM Space companion app to visually trace, replay, and benchmark complex agent behaviors.

Where teams use it

Deep Automated Research

Researchers deploy the framework to crawl massive documentation sites iteratively and synthesize comprehensive technical reports automatically over several hours.

Complex Code Generation

Software teams utilize the sandboxed sub-agents to rapidly scaffold, test, and debug massive full-stack application architectures autonomously.

Agent Capability Prototyping

AI developers use the native LLM Space integration to meticulously prototype, step-debug, and benchmark experimental multi-agent workflows.

Long-Horizon Data Extraction

Data engineers instruct the agent to autonomously navigate complex corporate portals, extract specific metrics, and compile structured datasets securely.

Getting started: npm install -g @bytedance/deer-flow

README

main branch

🦌 DeerFlow - 2.0

English | 中文 | 日本語 | Français | Русский

Python Node.js License: MIT

bytedance%2Fdeer-flow | Trendshift

On February 28th, 2026, DeerFlow claimed the 🏆 #1 spot on GitHub Trending following the launch of version 2. Thanks a million to our incredible community — you made this happen! 💪🔥

DeerFlow (Deep Exploration and Efficient Research Flow) is an open-source super agent harness that orchestrates sub-agents, memory, and sandboxes to do almost anything — powered by extensible skills.

deer-flow-720p.mp4

Note

DeerFlow 2.0 is a ground-up rewrite. It shares no code with v1. If you're looking for the original Deep Research framework, it's maintained on the 1.x branch — contributions there are still welcome. Active development has moved to 2.0.

Official Website

Learn more and see real demos on our official website. The landing-page case studies open as allowlisted, read-only showcases without requiring a sign-in.

Sister Projects

image
  • LLM Space - Meet our secret weapon behind DeerFlow — one desktop tool to prototype agent ideas, inspect each harness step, replay failures, and benchmark performance.

Coding Plan from ByteDance Volcengine

InfoQuest

InfoQuest reader, web search, and image search use a 30-second HTTP connect/read inactivity timeout. The crawl timeout and navigation_timeout settings remain separate server-side options; they do not control the local HTTP timeout.

DeerFlow has newly integrated the intelligent search and crawling toolset independently developed by BytePlus--InfoQuest (supports free online experience)

InfoQuest_banner

Table of Contents

One-Line Agent Setup

If you use Claude Code, Codex, Cursor, Windsurf, or another coding agent, you can hand it the setup instructions in one sentence:

Help me clone DeerFlow if needed, then bootstrap it for local development by following https://raw.githubusercontent.com/bytedance/deer-flow/main/Install.md

That prompt is intended for coding agents. It tells the agent to clone the repo if needed, choose Docker when available, and stop with the exact next command plus any missing config the user still needs to provide.

Quick Start

Configuration

Operators can extend lead-agent, subagent, and DeerMem extraction prompts with literal prepend/append configuration without editing source templates. See prompt overlays.

Optional per-model request_admission paces requests to help stay within provider request-per-minute limits. It is disabled by default; see the linked guide to enable it.

  1. Clone the DeerFlow repository

    git clone https://github.com/bytedance/deer-flow.git
    cd deer-flow
  2. Run the setup wizard

    From the project root directory (deer-flow/), run:

    make setup

    This launches an interactive wizard that guides you through choosing an LLM provider, optional web search, and execution/safety preferences such as sandbox mode, bash access, and file-write tools. It generates a minimal config.yaml and writes your keys to .env. Takes about 2 minutes.

    The wizard also lets you configure an optional web search provider, or skip it for now.

    Jina, Browserless, and InfoQuest web fetches resolve relative links and image sources using the requested page URL (or a usable HTML base URL), so returned Markdown includes complete destinations. Link resolution preserves the surrounding HTML source, including malformed-page formatting.

    Run make doctor at any time to verify your setup and get actionable fix hints. If you are opening a GitHub issue about a local setup or runtime problem, run make support-bundle. The command prints reporter next steps, writes a *-issue-summary.md file to paste into the issue, a *-issue-draft.md file for AI-assisted issue filing, and an optional evidence zip under .deer-flow/support-bundles/. If an AI assistant files the issue, start from the draft and replace every REQUIRED placeholder instead of inventing missing facts. Attach the zip only if a maintainer asks for it, or if the summary alone is not enough. Maintainers and AI triage tools can start with triage.json; the bundle includes redacted diagnostics and file manifests only, and does not include .env, raw conversation messages, or user file contents.

    Advanced / manual configuration: If you prefer to edit config.yaml directly, run make config instead to copy the full template. Optional dependency auto-detection accepts UTF-8 configuration files with or without a byte-order mark (BOM). See config.example.yaml for the complete reference including CLI-backed providers (Codex CLI, Claude Code OAuth), OpenRouter, Responses API, subagent runtime caps such as subagents.max_total_per_run, and more.

    Optional per-model pricing must use one currency across all priced models. DeerFlow disables Console cost estimates when currencies are mixed rather than presenting an invalid aggregate.

    Administrators can also open Settings → Models to add, edit, test, and enable/disable shared OpenAI-compatible Chat Completions models without editing config.yaml. Enter a unique name, base URL, model ID, and optional API key; saving refreshes the chat model list. Connection testing sends a short streaming tool-call request and may incur provider charges. It does not save the draft or verify image support; set image support and token limits from provider documentation. Official DeepSeek models at https://api.deepseek.com or https://api.deepseek.com/v1 (default HTTPS port) automatically use DeerFlow's DeepSeek adapter, preserving reasoning content across tool calls and honoring output token limits. Chat uses the selected thinking mode; the connection test temporarily disables thinking because DeepSeek rejects forced tool selection in thinking mode. The test checks streaming tool connectivity, not every agent workflow or thinking-mode behavior. Existing saved DeepSeek profiles receive this adapter without re-entering credentials. DeepSeek-specific settings for third-party proxies, other native adapters, and advanced reasoning settings remain YAML-configured.

    DeepSeek regression tests run offline with the normal backend suite. To verify the real provider explicitly, set DEEPSEEK_TEST_API_KEY in your environment and run from backend/:

    DEER_FLOW_RUN_LIVE_TESTS=1 uv run --no-sync pytest tests/test_managed_deepseek_live.py -q

    These opt-in tests send short requests to DeepSeek and may incur charges; they use temporary state, never save credentials to the deployment catalog, and are skipped in CI. DEEPSEEK_TEST_MODEL optionally selects a different DeepSeek model ID (default: deepseek-flash). The same tests can be run on unfixed and fixed revisions; success is always the expected result.

    YAML models remain read-only in this page and take precedence on name conflicts. Managed models are appended after YAML models; edits apply to new configuration snapshots, while active runs retain their existing snapshot. Disabling a model removes it from future selection/resolution, so update any custom-agent or scheduled task definitions that explicitly reference it before disabling it. Managed models are shared by the deployment, not personal API-key profiles, and remain subject to the existing model authorization policy.

    The encrypted catalog and a generated local encryption key are stored in $DEER_FLOW_HOME/managed-models/ (default .deer-flow/managed-models/). Persist and back up the whole directory, restrict filesystem access, and share it across Gateway workers/replicas that should use the same catalog. The local key is protected by filesystem permissions; encryption does not protect against someone who can read both files. Losing the key requires restoring the backup. Reads and writes fail if the catalog cannot be decrypted, rather than replacing it. This storage is independent of the SQL backend and works with read-only YAML mounts.

    When several models are configured, open either model picker and use the star beside a model to favorite it. Favorites appear first in both the main chat and Side Chat pickers without changing either chat's selected or default model. They are stored for the signed-in user in the current browser, so they do not sync to another browser or device and do not require a startup setting. The compact favorites picker intentionally omits search and only adds favorite ordering to the two-line model list.

    Manual model configuration examples
    models:
      - name: gpt-4o
        display_name: GPT-4o
        use: langchain_openai:ChatOpenAI
        model: gpt-4o
        api_key: $OPENAI_API_KEY
    
      - name: openrouter-gemini-2.5-flash
        display_name: Gemini 2.5 Flash (OpenRouter)
        use: langchain_openai:ChatOpenAI
        model: google/gemini-2.5-flash-preview
        api_key: $OPENROUTER_API_KEY
        base_url: https://openrouter.ai/api/v1
    
      - name: gpt-5-responses
        display_name: GPT-5 (Responses API)
        use: langchain_openai:ChatOpenAI
        model: gpt-5
        api_key: $OPENAI_API_KEY
        use_responses_api: true
        output_version: responses/v1
    
      - name: qwen3-32b-vllm
        display_name: Qwen3 32B (vLLM)
        use: deerflow.models.vllm_provider:VllmChatModel
        model: Qwen/Qwen3-32B
        api_key: $VLLM_API_KEY
        base_url: http://localhost:8000/v1
        supports_thinking: true
        when_thinking_enabled:
          extra_body:
            chat_template_kwargs:
              enable_thinking: true

    OpenRouter and similar OpenAI-compatible gateways should be configured with langchain_openai:ChatOpenAI plus base_url. If you prefer a provider-specific environment variable name, point api_key at that variable explicitly (for example api_key: $OPENROUTER_API_KEY).

    To route OpenAI models through /v1/responses, keep using langchain_openai:ChatOpenAI and set use_responses_api: true with output_version: responses/v1.

    Models whose provider contract differs from DeerFlow's generic thinking/effort assumptions can declare a per-model mapping-valued reasoning: block (thinking unsupported/optional/required, the accepted effort values with aliases and a default, the payload dialect, and the reasoning-history requirement). The setup wizard's Z.AI GLM-5.3-Flash profile uses it: thinking stays on for every foreground and background call, and the effort selector offers the model's own low/high/max levels. Ollama's existing boolean reasoning: true remains a native provider setting and is forwarded to ChatOllama. When migrating a profile to a custom effort path, remove any old reasoning_effort setting from the profile and thinking templates; configuration validation rejects the leftover key. The chat UI drops a remembered provider-specific effort when switching to a legacy model that does not advertise it. Profiles without the block keep their existing provider behavior. See config.example.yaml for the shape and the equivalent manual configuration.

    For vLLM 0.19.0, use deerflow.models.vllm_provider:VllmChatModel. For Qwen-style reasoning models, DeerFlow toggles reasoning with extra_body.chat_template_kwargs.enable_thinking and preserves vLLM's non-standard reasoning field across multi-turn tool-call conversations. Legacy thinking configs are normalized automatically for backward compatibility. If the endpoint reports a cumulative usage snapshot on every streaming chunk, set cumulative_stream_usage: true so DeerFlow converts those snapshots into per-chunk deltas; the option is disabled by default and leaves usage unchanged when a stable completion id is unavailable. Reasoning models may also require the server to be started with --reasoning-parser .... If your local vLLM deployment accepts any non-empty API key, you can still set VLLM_API_KEY to a placeholder value.

    CLI-backed provider examples:

    models:
      - name: gpt-5.4
        display_name: GPT-5.4 (Codex CLI)
        use: deerflow.models.openai_codex_provider:CodexChatModel
        model: gpt-5.4
        supports_thinking: true
        supports_reasoning_effort: true
    
      - name: claude-sonnet-4.6
        display_name: Claude Sonnet 4.6 (Claude Code OAuth)
        use: deerflow.models.claude_provider:ClaudeChatModel
        model: claude-sonnet-4-6
        max_tokens: 4096
        supports_thinking: true
    • Codex CLI reads ~/.codex/auth.json
    • The Codex model provider returns completed responses without waiting for the SSE connection to close. Failed or incomplete responses report the provider's error or reason; partial output is not returned as a successful answer. Non-object error details are reported as text.
    • Claude Code accepts CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_AUTH_TOKEN, CLAUDE_CODE_CREDENTIALS_PATH, or ~/.claude/.credentials.json
    • ACP agent entries are separate from model providers — if you configure acp_agents.codex, point it at a Codex ACP adapter such as npx -y @zed-industries/codex-acp
    • MiniMax Code speaks ACP directly. Install and authenticate it, then add it as an ACP agent:
    npm install --global @minimax-ai/code
    mcode login
    acp_agents:
      mcode:
        command: mcode
        args: ["acp"]
        description: MiniMax Code for implementation, refactoring, debugging, and repository tasks
        auto_approve_permissions: false

    mcode must be on the Gateway process's PATH; installing it only on the Docker host does not make it available inside the Gateway container. DeerFlow invokes it through invoke_acp_agent in a per-thread ACP workspace and forwards enabled MCP servers. Keep auto_approve_permissions: false for untrusted tasks; enable it only when MCode must edit files or run commands and you trust the task.

    • On macOS, export Claude Code auth explicitly if needed:
    eval "$(python3 scripts/export_claude_code_oauth.py --print-export)"

    API keys can also be set manually in .env (recommended) or exported in your shell:

    OPENAI_API_KEY=your-openai-api-key
    TAVILY_API_KEY=your-tavily-api-key

Running the Application

Deployment Sizing

Use the table below as a practical starting point when choosing how to run DeerFlow:

Deployment target Starting point Recommended Notes
Local evaluation / make dev 4 vCPU, 8 GB RAM, 20 GB free SSD 8 vCPU, 16 GB RAM Good for one developer or one light session with hosted model APIs. 2 vCPU / 4 GB is usually not enough.
Docker development / make docker-start 4 vCPU, 8 GB RAM, 25 GB free SSD 8 vCPU, 16 GB RAM Image builds, bind mounts, and sandbox containers need more headroom than pure local dev.
Long-running server / make up 8 vCPU, 16 GB RAM, 40 GB free SSD 16 vCPU, 32 GB RAM Preferred for shared use, multi-agent runs, report generation, or heavier sandbox workloads.
  • These numbers cover DeerFlow itself. If you also host a local LLM, size that service separately.
  • Linux plus Docker is the recommended deployment target for a persistent server. macOS and Windows are best treated as development or evaluation environments.
  • If CPU or memory usage stays pinned, reduce concurrent runs first, then move to the next sizing tier.
Option 1: Docker (Recommended)

Requires Docker Desktop / Docker Engine and Docker Compose v2.24+ (docker compose version). Older Compose clients cannot parse the optional env_file syntax in docker/docker-compose-dev.yaml.

Development (hot-reload, source mounts):

make docker-init    # Pull sandbox image (only once or when image updates)
make docker-start   # Start services (auto-detects sandbox mode from config.yaml)
make docker-logs    # View logs

make docker-start starts provisioner only when config.yaml uses provisioner mode (sandbox.use: deerflow.community.aio_sandbox:AioSandboxProvider with provisioner_url).

Docker builds use the upstream uv registry by default. If you need faster mirrors in restricted networks, export UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple and NPM_REGISTRY=https://registry.npmmirror.com before running make docker-init or make docker-start.

Local AIO sandbox control traffic is always direct: loopback/private addresses, single-label cluster hosts, and Docker/Podman internal hostnames do not inherit HTTP_PROXY or HTTPS_PROXY. External sandbox FQDNs and public IPs still honor environment proxy settings.

Backend processes automatically pick up config.yaml changes on the next config access, so model metadata updates do not require a manual restart during development.

Gateway runs use the top-level recursion_limit in config.yaml when an API request does not provide one. The default is 100; valid per-request values take precedence, and max_recursion_limit (default 1000) caps both. Changes apply to the next run without restarting the Gateway. This top-level setting applies to Gateway API runs; IM channel and embedded DeerFlowClient runs retain their own defaults and per-call override paths. The checkpoint storage settings database.checkpoint_channel_mode and database.checkpoint_delta.snapshot_frequency (default 10) are exceptions: both are frozen when the process first builds an agent (including through DeerFlowClient) and require a process restart to change safely.

The optional database.checkpoint_cache section (delta channel mode only) caches materialized checkpoint histories: type is memory (default) or redis, and max_entries: 0 disables the cache. The redis backend is Gateway/async-only; the sync TUI/embedded path supports memory only. The cache is performance-only — results are identical with it disabled — so it is never frozen and workers sharing one checkpoint database may safely run different cache settings.

Tip

On Linux, if Docker-based commands fail with permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock, add your user to the docker group and re-login before retrying. See CONTRIBUTING.md for the full fix.

Production (builds images locally, mounts runtime config and data):

make up     # Build images and start all production services
make down   # Stop and remove containers

Access: http://localhost:2026

make up waits for the Gateway /health endpoint before reporting success. If the Gateway does not become healthy within the startup window, deployment exits non-zero and prints the container status plus recent Gateway logs. The production image starts from its already-built environment and never resolves or installs Python dependencies at container startup.

For persistent deployments, configure database.backend as sqlite or postgres. The selected backend is shared by the LangGraph checkpointer, LangGraph Store, and DeerFlow application data. The deprecated checkpointer section, when present, overrides the first two for backward compatibility.

Gateway startup automatically repairs the missing run-change schema affecting some existing databases (#5516). The repair preserves run history and existing change positions; downgrading the repair to its predecessor also retains the schema and positions required by that version.

For lightweight single-process event persistence, run_events.backend: jsonl keeps Unicode message content intact, including line and paragraph separators. Existing valid JSONL records remain readable without rewriting the files.

The unified nginx endpoint is same-origin by default and does not emit browser CORS headers. If you run a split-origin or port-forwarded browser client, set GATEWAY_CORS_ORIGINS to comma-separated exact origins such as http://localhost:3000; the Gateway then applies the CORS allowlist and matching CSRF origin checks.

When fine-grained authorization is enabled, Live Browser connections require threads:write as well as ownership of the thread, even when only viewing frames: the same connection can control the browser. Permission checks run when connecting. Restart Gateway after upgrading to disconnect sessions admitted by older code.

Browser login uses HttpOnly session cookies. The login page offers a "keep me signed in" option that extends the browser session when the request is HTTPS (including trusted X-Forwarded-Proto: https) or localhost HTTP. The localhost exception uses the direct request Host and ignores forwarded host headers. Public HTTP deployments, including many temporary sandbox URLs, fall back to session cookies by default. DeerFlow never stores the password in browser storage; the UI may remember only the email address.

DeerFlow still uses Forwarded / X-Forwarded-* headers to recover the browser-facing scheme and origin behind a proxy. The bundled nginx sets X-Forwarded-Proto, but preserves an upstream HTTPS value and does not overwrite every forwarded header. Configure the outer trusted proxy to replace or strip client-supplied forwarding headers before traffic reaches DeerFlow.

Important

The Gateway still owns active run tasks in process, so production defaults to a single Gateway worker (GATEWAY_WORKERS=1). Multi-worker deployments require Postgres, the Redis stream bridge (stream_bridge.type: redis), run_ownership.heartbeat_enabled: true, and run_events.backend: db; process-local memory/JSONL event stores cannot enforce singleton delivery receipts across workers. The bridge shares SSE delivery and bounded Last-Event-ID replay across workers. When a valid reconnect cursor has been trimmed, or a subscriber that already established an empty-stream wait falls behind before its first delivery, Memory and Redis emit a machine-readable SSE gap event instead of silently returning a partial replay; the Web UI reloads durable thread/event state and resumes from the retained tail. Lease reconciliation marks runs from dead workers as errors, persists their delivery receipts, publishes the terminal stream marker, schedules retained-stream cleanup, and updates the affected thread status. SSE, /wait, and internal stream consumers use stream_bridge.heartbeat_interval_seconds (default 15) for idle liveness checks; changing it requires a Gateway restart. Malformed Redis reconnect IDs live-tail new events instead of replaying the retained buffer, and the rolling retained-buffer TTL (stream_ttl_seconds) remains a cleanup safety net rather than a run timeout. IM channel state and other process-local services still need their own multi-worker coordination.

In single-process JSONL deployments, cancelling an admitted event-store mutation waits for its background file I/O, rollback, and bookkeeping to settle before releasing the thread write lock. This prevents an older cancelled write from recreating deleted records or rolling back a later successful write. Cancellation can therefore wait on slow storage; it does not stop an in-flight filesystem operation. Callers still waiting to acquire the lock can cancel without starting a mutation. A batch spanning multiple threads drains its current thread group before propagating cancellation; subsequent thread groups do not start.

After a run publishes its terminal stream marker, its process-local RunRecord remains available for the existing five-minute grace period before cleanup; durable run history remains available through RunStore, while the stream bridge retains its delivery tail on its separate cleanup schedule.

Run cancellation may land on any Gateway worker. A non-owning worker now persists the interrupt or rollback request for the live owner, which observes it during lease renewal and performs the normal cancellation flow; load-balancer routing alone no longer produces a 409. The first accepted action wins even if a retry lands on the owner, and accepted cancellation competes atomically with owner completion. Dead owners still follow lease takeover and orphan recovery. Cancellation latency is therefore bounded by the lease heartbeat interval.

Cancelling a model recovery probe, including while it is queued or waiting to retry, lets the next call check whether the provider has recovered. Cancellation does not count as a provider failure or release another call's active recovery probe.

With lease heartbeat enabled, a transient RunStore renewal error is retried only until the last confirmed lease expires; the stale worker then cancels local execution and suppresses checkpoint, completion-hook, delivery-receipt, and thread-status finalization. A remote tool side effect already in flight may still be outside local cancellation.

Reconciliation uses an atomic takeover claim that re-checks the lease after candidate selection, so a successful owner renewal wins over orphan recovery and only one reconciler can report a run as recovered. When multiple Gateway workers share the Docker/AIO or E2B sandbox backend, also configure sandbox.ownership.type: redis; E2B uses the leases during background startup and periodic reconciliation so duplicate/orphan cleanup cannot terminate a live peer's sandbox.

See CONTRIBUTING.md for detailed Docker development guide.

Upgrading an existing checkout

Keep config.yaml, .env, and extensions_config.json. Stop the services you currently use, run git pull --ff-only, then start the same mode again. Do not run make config or make docker-init again for a routine source upgrade. If the new version requires configuration changes, run make config-upgrade before restarting. See Operations and Troubleshooting for the commands for each mode.

Option 2: Local Development

If you prefer running services locally:

Prerequisite: complete the "Configuration" steps above first (make setup). make dev requires a valid config.yaml in the project root. Set DEER_FLOW_PROJECT_ROOT to define that root explicitly, or DEER_FLOW_CONFIG_PATH to point at a specific config file. Runtime state defaults to .deer-flow under the project root and can be moved with DEER_FLOW_HOME; skills default to skills/ under the project root and can be moved with DEER_FLOW_SKILLS_PATH. Run make doctor to verify your setup before starting. On Windows, run the local development flow from Git Bash. Native cmd.exe and PowerShell shells are not supported for the bash-based service scripts, and WSL is not guaranteed because some scripts rely on Git for Windows utilities such as cygpath.

The documented root make commands invoke repository .sh files through Bash explicitly. They therefore continue to work from source archives or filesystems that do not preserve POSIX executable bits. When calling a script directly from such a checkout, use bash ./scripts/<name>.sh ....

  1. Check prerequisites:

    make check  # Verifies Node.js 22+, pnpm, uv, nginx

    The local make check, make install, make dev, and make start entry points use a direct pnpm executable when available and otherwise fall back to corepack pnpm. With native Windows Python, the shared runner checks pnpm.cmd before the generic pnpm lookup, which follows PATH/PATHEXT and may select an .exe or .bat in the same or an earlier PATH directory. The Corepack fallback likewise checks corepack.cmd before corepack. POSIX Python keeps the generic names first, including when running under MSYS/Cygwin. The runner and diagnostics resolve repository paths absolutely, so these checks work regardless of the caller's current directory. Corepack runs from frontend/, so it honors the packageManager version pinned in frontend/package.json; enabling a global pnpm shim is not required.

  2. Install dependencies:

    make install  # Install backend + frontend dependencies + pre-commit hooks

    Hook setup calls pre-commit through uv, so uv's tool directory need not be on PATH.

  3. (Optional) Pre-pull sandbox image:

    # Recommended if using Docker/Container-based sandbox
    make setup-sandbox

    Reads the configured sandbox image from UTF-8 config.yaml, with or without a leading BOM, using LF or CRLF line endings. On macOS, a successful Apple Container pull completes this step even when Docker is not installed. If Docker is available, its image is also pulled.

  4. Start services:

    make dev
  5. Access: http://localhost:2026

  6. (Optional) Load sample memory data for local review: open Settings > Memory, click Import memory, and select backend/docs/memory-settings-sample.json. The browser imports into the signed-in user's memory.

    To replace memory for every registered user in a disposable review environment:

    cd backend
    uv run python ../scripts/load_memory_sample.py --all-users

    Bulk mode supports SQLite/PostgreSQL user registries, creates timestamped backups under .deer-flow/memory-sample-backups/, and rejects the non-persistent database.backend: memory mode. See backend/docs/MEMORY_SETTINGS_REVIEW.md for the complete review flow.

Local services always use their internal ports (8001, 3000, and 2026). The root .env variable PORT configures only the published Docker ingress; it does not change the Next.js port used by make dev.

Startup Modes

DeerFlow runs the agent runtime inside the Gateway API. Development mode enables hot-reload; production mode uses a pre-built frontend.

Local Foreground Local Daemon Docker Dev Docker Prod
Dev ./scripts/serve.sh --dev
make dev
./scripts/serve.sh --dev --daemon
make dev-daemon
./scripts/docker.sh start
make docker-start
—
Prod ./scripts/serve.sh --prod
make start
./scripts/serve.sh --prod --daemon
make start-daemon
— ./scripts/deploy.sh
make up
Action Local Docker Dev Docker Prod
Stop ./scripts/serve.sh --stop
make stop
./scripts/docker.sh stop
make docker-stop
./scripts/deploy.sh down
make down
Restart ./scripts/serve.sh --restart [flags] ./scripts/docker.sh restart —

make start and make start-daemon rebuild the frontend with next build on every run. To reuse the last build instead, pass SKIP_FRONTEND_BUILD=1 (or add --skip-frontend-build when calling ./scripts/serve.sh --prod directly). This is opt-in: it fails fast when frontend/.next has no completed build.

Gateway owns /api/langgraph/* and translates those public LangGraph-compatible paths to its native /api/* routers behind nginx.

For a read-only demo without the Gateway, run make build-static from frontend/, then HOSTNAME=127.0.0.1 PORT=3000 node --env-file=.env .next/standalone/server.js from the same directory. The build includes public demo assets and resolves supported demo API reads locally; writes are unavailable. To display the homepage GitHub star count, set GITHUB_OAUTH_TOKEN in frontend/.env before starting Node. The token stays on the server; missing credentials or GitHub failures hide the count. Restart Node after changing the token; no rebuild is needed.

LangGraph Studio (Optional)

The default make dev topology uses DeerFlow's Gateway-embedded runtime and does not require LangGraph Studio. To inspect and test the registered lead-agent graph with the standalone development server, run the command from backend/ so the CLI discovers langgraph.json:

cd backend
uv run langgraph dev --allow-blocking

The command prints the local API and Studio UI URLs. This in-memory server is for development and testing only. The flag permits DeerFlow's synchronous configuration and graph-factory setup during local Studio requests; it must not be treated as a production-server setting. Local Studio authentication is handled automatically, so the connection does not require custom headers. Use DeerFlow's documented production startup modes or a supported LangSmith deployment for production workloads. Assistant ownership and provenance in this standalone mode are server-owned: Studio can discover registered graphs and the assistants it creates, and normal assistant-version selection remains available. Before the locked local runtime loads its persisted development store, DeerFlow repairs legacy assistant rows and version history so historical client metadata cannot restore server privileges or be discarded by the runtime's startup cleanup. Keep the backend dependencies synchronized with uv sync; this compatibility path requires the declared LangGraph runtime versions and logs a warning if the persisted-store contract no longer matches its expectations. The documented command uses LangGraph's file-based custom-app loader, which is also covered directly by DeerFlow's regression tests.

Standalone runs using if_not_exists="create" retain config and run metadata on the newly created thread, including searchable tags; run metadata takes precedence for duplicate keys. Thread ownership and MCP incarnation remain server-owned, and later runs do not replace the thread's creation metadata.

For workflows that invoke backend/langgraph.json through LangGraph Studio or a direct LangGraph Server, DeerFlow consumes the authenticated identity published by that runtime and uses it for custom-agent configuration/SOUL, user skills and skill policy, uploads, thread data, and memory reads/writes. This keeps authenticated runs out of the shared default filesystem bucket, and the server-owned identity takes precedence over ordinary client-supplied user_id values. External identities such as email addresses are mapped to stable, collision-resistant directory-safe user IDs before accessing DeerFlow storage. The default DeerFlow service topology remains the Gateway-embedded runtime described above.

Gateway runs automatically enforce native delivery for artifacts created or modified under /mnt/user-data/outputs: present_files must present at least one output produced by the current run, and the terminal run.delivery receipt must be durably recorded. Virtual artifact paths are resolved within the same authenticated user and thread scope that produced the output before the output-directory boundary is validated. Runs that do not produce output artifacts keep ordinary conversational behavior.

DeerFlow's built-in custom events are available through both LangGraph streaming interfaces: native clients can continue subscribing to stream_mode="custom", while callback-based integrations can consume the same payloads as on_custom_event records from astream_events(version="v2"). The callback event name matches the payload's type field.

Docker Production Deployment

deploy.sh supports building and starting separately:

# One-step (build + start)
deploy.sh

# Two-step (build once, start later)
deploy.sh build              # build all images
deploy.sh start              # start pre-built images

# Stop
deploy.sh down

Advanced

Sandbox Mode

DeerFlow supports multiple sandbox execution modes:

  • Local Execution (runs sandbox code directly on the host machine)
  • Docker Execution (runs sandbox code in isolated Docker containers)
  • Docker Execution with Kubernetes (runs sandbox code in Kubernetes pods via provisioner service)

Sandbox references in conversation state are server-owned. External run and thread-state APIs reject caller-supplied sandbox values; when restoring a checkpoint, the runtime resolves the reference against the authenticated user and thread before a tool can reuse it. A missing runtime thread ID raises an error even when the referenced sandbox is cached.

When host Bash is enabled for Local Execution, DeerFlow starts OS detection with uname -s, then uses sw_vers on Darwin. On Linux, it reads host system files such as /etc/os-release only when the active sandbox policy permits it. Host filesystem path checks still apply; after a blocked path, the agent is directed to use a permitted command-only probe or virtual path instead of repeating the rejected command.

For Docker development, service startup follows config.yaml sandbox mode. In Local/Docker modes, provisioner is not started.

See the Sandbox Configuration Guide to configure your preferred mode.

Remote directory listings report traversal failures (for example, unreadable directories) as incomplete results, even when no entries were returned. A missing start path is reported separately as “Directory not found.”

MCP Server

In the chat UI, enable Token Usage → Debug to inspect generic/MCP tool calls. Each Tool details panel starts collapsed and shows the tool name, call ID, input, and received result or explicit error. Large previews are truncated; fields whose names exceed the remaining preview budget are omitted rather than renamed. Structured previews retain complete JSON syntax, including escaped strings and closing delimiters. Array previews stop when the text budget cannot display another element; literal ellipsis values are preserved. Consecutive generated markers at an array's end share one ellipsis indicating an omitted suffix; markers before later values retain their positions. Text results retain their original representation, including large numeric IDs and duplicate JSON keys, without reparsing. Text exceeding the limit is shown as a prefix with a truncation notice; structured objects and arrays are formatted separately. Copy actions copy only the displayed preview. This is a frontend view of data already received by the browser, without an additional secret-redaction layer.

Tool-produced paths and URLs can be retained as short artifact handles across context compaction (tool_artifacts in config.yaml). Handles distinguish separate tool-result occurrences, even when a provider reuses call IDs. Detected file URLs preserve their query strings and fragments. When PII redaction is enabled, model-visible artifact labels follow that policy; internal references stay intact for tool argument resolution. The configured registry limit retains the newest artifacts, while checkpointed processing identities prevent evicted results from being recaptured after restart. Resolution runs before authorization and write-safety checks; unknown or expired handles return an error without executing the tool. Small unknown structured results may be retained as complete JSON up to 4096 UTF-8 bytes; empty or oversized payloads are skipped. Handles are agent-local: task arguments resolve parent handles to concrete references, and delegated reports must return concrete references rather than child-local handles. A truncated model projection reports how many handles are omitted.

DeerFlow supports configurable MCP servers and skills to extend its capabilities. For HTTP/SSE MCP servers, OAuth token flows are supported (client_credentials, refresh_token). Durable HTTP/SSE task status and cancellation calls select configured user_auth credentials using the persisted task owner, including after restart; per-request secrets are not retained for background calls. If a request-scoped credential overrides submit authentication, both credentials must authorize access to the same remote task. For stdio MCP servers, per-tool call timeouts can be configured with tool_call_timeout; durable background-task calls honor the same setting for HTTP/SSE servers as well. For stdio file outputs, a bare filename is linked to a uniquely matching file created or changed by that call. Filenames embedded in unrelated paths, including Windows backslash paths, are left intact. For HTTP/SSE background-task calls, session_init_timeout separately bounds connection setup (including the SSE endpoint event) and MCP initialization together; it stops applying once the tool call begins. Initialization deadline errors identify the server and configured time limit. Ordinary task subagents retain the parent run's captured thread incarnation for MCP calls, including legacy threads, so delegation preserves the same lifecycle scope. MCP tool names are prefixed with <server_name>_ by default to prevent collisions across servers. If a server already namespaces its own tools, set tool_name_prefix: false on that server in extensions_config.json to keep the original names. Disable the prefix only when the resulting names remain unique across all enabled servers. Signed-in users' notification toggle, default model, conversation mode, and reasoning effort are saved to their account and restored on other browsers or after clearing browser storage. Browser notification permission still needs to be granted on each device. Changes retry after network failures; unsent changes survive a reload in the same tab. Concurrent edits to different fields are preserved; for the same field, the last server write wins. Existing unscoped browser preferences are not uploaded automatically because they have no account owner; reselect those settings once after upgrading. Static demos and auth-disabled development keep browser-local settings. Thread-specific model overrides and other display preferences remain local.

In a new chat, the submitted question stays above its streamed reasoning and tool steps while the server creates the conversation and confirms the message.

Capability Center groups plugins by office collaboration, documents and knowledge, search and research, business and data, and development and operations. The directory includes setup references alongside existing MCP configurations and Lark. Recommended integrations and built-in support do not imply an installed or verified connection; the Installed filter shows configured MCP entries and installed Lark only.

Personal MCP connections configured in the web interface are persisted per user. Deployment tools remain shared. Administrators can add, edit, enable, disable and delete shared MCP servers under Platform provided; ordinary users see their status without controls. Personal plugin switches affect only the signed-in user's connections. See connection ownership.

For plugin manifests, adapter registration, and Agent capability selection, see Capability Center integration contract.

DingTalk and WeCom group notifications and HubSpot CRM are bundled configurable plugins. Administrators supply robot credentials or a HubSpot private app token; Agents can then send requested group notifications, list companies, or create contacts. Saving configuration performs no external write. These plugins reuse the existing MCP lifecycle and require no separate plugin service. See the integration contract above for required fields, scopes, and feature boundaries.

Plugin brand icons are bundled locally. When adding or editing one personal MCP plugin, users can upload a PNG, JPG, or WebP image (up to 2 MB), preview it, or restore the default icon. Changes take effect only after Save; custom icons persist across browsers as a normalized 128px PNG in the server entry's display-only presentation.icon metadata. They are not sent to the MCP transport.

Capability Center > Plugins adds, replaces, and deletes one MCP server at a time through targeted mutations that preserve concurrent sibling changes; deletes use a bodyless URL-addressed request. An invalid stdio command on one server no longer blocks toggling another, while enabling that invalid server remains protected by the command allowlist and surfaces the backend validation message in the UI. Targeted updates accept both DeerFlow's type field and the MCP-spec transport field for SSE/HTTP servers. Runtime MCP and skill updates replace extensions_config.json atomically, so an interrupted write cannot leave the shared configuration truncated or partially written. The admin MCP cache reset advances a durable generation marker in the writable config directory. Every Gateway worker mounting that same directory retires its own cached tools and pooled sessions before the next lookup; replicas with independent filesystems are not implicitly covered. If no config path is available, the API reports a process-local reset instead. extensions_config.json accepts UTF-8 with or without a leading byte-order mark (BOM), including files saved as UTF-8 with BOM by an editor. MCP routing hints can also prefer a specific MCP tool for matching requests without forbidding other tools. When tool_search defers MCP schemas, matching routing metadata can auto-promote up to tool_search.auto_promote_top_k deferred schemas before the model call.

OpenViking users can register the official Streamable HTTP endpoint at /mcp with an owner-bound USER API key. The native forget tool is exposed for capability parity; deletion is irreversible, so it should be called only after explicit user confirmation. DeerFlow does not enforce that confirmation. This explicit, model-selected MCP tool path can run alongside the separate automatic OpenViking memory backend; it does not replace automatic turn capture or recall. See the OpenViking MCP tools configuration.

The Gateway can adapt an MCP server's ordinary submit / status / cancel tools into durable background tasks. The Agent sees only the configured submit tool and a DeerFlow-local task ID; remote IDs are persisted before the submit call returns, while status and cancel stay internal to the runtime. Polling uses cross-worker leases, exponential retry backoff, scoped MCP sessions, bounded result storage, and restart recovery. A status-tool isError is retained as a bounded diagnostic and retried; servers report a permanent remote-task outcome through a normal structured result with status: "failed". Remote poll hints are finite positive numbers capped at 24 hours, artifact-reference JSON is limited to 64 KiB, and task/server identifiers are validated against their durable SQL column limits before persistence. Input-required and terminal updates wake the current chat through idempotent Agent runs, while list_background_tasks and cancel_background_task let the Agent manage tasks without asking users for remote handles. Current-thread tasks are available through GET /api/threads/{thread_id}/mcp-tasks, its detail endpoint, and POST /api/threads/{thread_id}/mcp-tasks/{task_id}/cancel; when the task runtime actually starts, the Web UI exposes the same safe local view from the chat header with live status refresh, cancellation, and on-demand result, artifact, input-request, status-error, and cancellation-retry details. Default-disabled and memory-backend deployments hide that UI and do not poll the task endpoints. A failed remote cancellation remains queued with backoff, and its latest bounded error and attempt count stay visible in the expanded task card. Enable mcp_tasks in config.yaml, configure task_toolsets with exact raw tool names in extensions_config.json, and use a SQL database backend (sqlite or postgres). Task-enabled server connection, authentication, interceptor, timeout, or binding changes require a Gateway restart so Agent tool discovery and background calls cannot use different configuration versions. input_required is notification-only for now: DeerFlow can display the request but cannot yet submit the user's answer back to the remote task.

Notification launch and failed Agent-run deliveries use capped exponential backoff with a visible attempt count and stop after five failed attempts. When a bounded ordinary release exceeds its drain deadline, the service retains ownership until it settles. A permanently rejected target such as a deleted chat is dead-lettered immediately instead of retried forever or recreated. Cancellation endpoints return after durably recording the request; the background service owns the potentially slow remote MCP call and its retry schedule.

Notification runs keep their trusted delivery instruction separate from the framed, untrusted remote event payload. The process-started task runtime—not a hot config read—controls whether the task-management tools are exposed, so changing mcp_tasks requires a Gateway restart. When a skill's allowed-tools policy is active, list_background_tasks and cancel_background_task must be declared explicitly like other business tools. See the MCP Server Guide for detailed instructions.

Security: pass per-request MCP credentials only through config.context.secrets; credentials must never be placed in either run metadata surface (metadata.auth_token or config.metadata.auth_token). See MCP credential migration and cleanup for the supported interceptor flow and the required rotation and retained-copy cleanup when migrating from legacy metadata credentials.

IM Channels

DeerFlow supports receiving tasks from messaging apps. Channels auto-start when configured — no public IP required for any of them.

DeerFlow can also expose user-owned IM channel connections in the workspace UI. When channel_connections is enabled, logged-in users can bind Telegram, Slack, Discord, Feishu/Lark, DingTalk, WeChat, WeCom, or Buzz from the sidebar / Settings > Channels. It reuses the existing outbound channels.* transports, so no public IP or provider callback URL is required. Incoming IM messages then run under the connected DeerFlow user account. See IM Channel Connections for setup and security notes.

Channel Transport Difficulty
Telegram Bot API (long-polling) Easy
Slack Socket Mode Moderate
Feishu / Lark WebSocket Moderate
WeChat Tencent iLink (long-polling) Moderate
WeCom WebSocket Moderate
DingTalk Stream Push (WebSocket) Moderate
Buzz Nostr relay (WebSocket, NIP-42) Moderate

Configuration in config.yaml:

channels:
  # LangGraph-compatible Gateway API base URL (default: http://localhost:8001/api)
  langgraph_url: http://localhost:8001/api
  # Gateway API URL (default: http://localhost:8001)
  gateway_url: http://localhost:8001

  # Maximum queued or provider-reserved inbound messages (default: 1000)
  inbound_queue_maxsize: 1000
  # Fixed number of long-lived inbound handler workers (default: 5)
  max_concurrency: 5
  # Seconds to drain accepted work before cancelling active handlers (default: 3)
  shutdown_grace_period_seconds: 3

  # Optional: global session defaults for all mobile channels
  session:
    assistant_id: lead_agent  # or a custom agent name; custom agents are routed via lead_agent + agent_name
    config:
      recursion_limit: 100
    context:
      thinking_enabled: true
      is_plan_mode: false
      subagent_enabled: false

  feishu:
    enabled: true
    app_id: $FEISHU_APP_ID
    app_secret: $FEISHU_APP_SECRET
    # domain: https://open.feishu.cn       # China (default)
    # domain: https://open.larksuite.com   # International

  wecom:
    enabled: true
    bot_id: $WECOM_BOT_ID
    bot_secret: $WECOM_BOT_SECRET
    # Optional: extra host suffixes inbound media downloads may come from, in
    # addition to the built-in qq.com family and WeCom's official COS media
    # host (ww-aibot-img-1258476243.<region>.myqcloud.com); add one here if
    # WeCom rotates to a new COS account or media goes through a proxy
    allowed_media_hosts: []

  slack:
    enabled: true
    bot_token: $SLACK_BOT_TOKEN     # xoxb-...
    app_token: $SLACK_APP_TOKEN     # xapp-... (Socket Mode)
    (README truncated)

View on GitHub

Recent activity

commits and pull requests

Releases and announcements

2 total
  1. v2.1.0 Releasev2.1.0Sep 24, 2026

    # DeerFlow 2.1.0 DeerFlow 2.1 builds on the 2.0 super-agent harness with a focus on **trust, scale, and operability**: verifiable agent execution, durable batch delegation, pluggable memory backends, four new sandbox providers, an out-of-tree extension system, and enterprise-grade authentication and authorization — wrapped in a much richer workspace with projects, conversation branching, and referenced conversations. This release closes the [2.1.0 milestone](https://github.com/bytedance/deer-flow/milestone/2) with **772 merged PRs** since the 2.0.0 release. > 📖 Full notes: [CHANGELOG.md](CHANGELOG.md) · [中文版](CHANGELOG_zh.md) --- ## ⚠️ Breaking changes - **Trace ids are unconditional** — every Gateway HTTP response carries an `X-Trace-Id` header, and `logging.enhance.enabled` now controls log output only. Client-supplied `deerflow_trace_id` values in run metadata are overwritten so header, logs, and the persisted run cannot disagree — send the `X-Trace-Id` request header to pin a correlation id. ([#5119]) - **`/mnt/skills` is reserved** for managed enabled-only skill projections. `DEER_FLOW_HOST_SKILLS_PATH` / `SKILLS_HOST_PATH` are no longe

  2. DeerFlow 2.0.0 releasedv2.0.0Jun 25, 2026

    # DeerFlow 2.0.0 DeerFlow 2.0 is a **ground-up rewrite** around a "super agent" harness that orchestrates **sub-agents**, **persistent memory**, **sandboxed execution**, and an extensible **skills/tools** system. It shares no code with the 1.x line, which lives on the [`main-1.x` branch](https://github.com/bytedance/deer-flow/tree/main-1.x). This release closes the [2.0.0 milestone](https://github.com/bytedance/deer-flow/milestone/1) with **182 merged PRs** since the first 2.0 milestone tag. > 📖 Full notes: [CHANGELOG.md](CHANGELOG.md) · [中文版](CHANGELOG_zh.md) --- ## ⚠️ Breaking change - **Run hydration** — runs now hydrate from `RunStore` and persist `interrupted` status. Cancellation now requires the worker who owns the run; cross-worker cancels return `409` instead of silently appearing successful. ([#2932]) ## ✨ Highlights - **Custom agents that update themselves** — agents can persist edits to their own `SOUL.md` / `config.yaml` from a normal chat, with full per-user isolation. ([#2713]) - **User-owned IM channel connections** — users can bind their own Slack, Telegram, Discord, Feishu/Lark, DingTalk, WeChat, and WeCom accounts on t

Code frequency

additions and deletions
+154.6K-154.6KWeek of 2025-10-05: +95 linesWeek of 2025-10-05: -5 linesWeek of 2025-10-12: +1,275 linesWeek of 2025-10-12: -119 linesWeek of 2025-10-19: +9,965 linesWeek of 2025-10-19: -502 linesWeek of 2025-10-26: +3,883 linesWeek of 2025-10-26: -169 linesWeek of 2025-11-02: +351 linesWeek of 2025-11-02: -12 linesWeek of 2025-11-09: +1,418 linesWeek of 2025-11-09: -32 linesWeek of 2025-11-16: +486 linesWeek of 2025-11-16: -23 linesWeek of 2025-11-23: +2,642 linesWeek of 2025-11-23: -491 linesWeek of 2025-11-30: +2,510 linesWeek of 2025-11-30: -338 linesWeek of 2025-12-07: +451 linesWeek of 2025-12-07: -106 linesWeek of 2025-12-14: +1,831 linesWeek of 2025-12-14: -121 linesWeek of 2025-12-21: +3,064 linesWeek of 2025-12-21: -66 linesWeek of 2025-12-28: +44 linesWeek of 2025-12-28: -11 linesWeek of 2026-01-04: +1,046 linesWeek of 2026-01-04: -144 linesWeek of 2026-01-11: +49,970 linesWeek of 2026-01-11: -6,862 linesWeek of 2026-01-18: +78,212 linesWeek of 2026-01-18: -18,786 linesWeek of 2026-01-25: +48,357 linesWeek of 2026-01-25: -10,453 linesWeek of 2026-02-01: +42,129 linesWeek of 2026-02-01: -20,898 linesWeek of 2026-02-08: +19,581 linesWeek of 2026-02-08: -154,609 linesWeek of 2026-02-15: +246 linesWeek of 2026-02-15: -114 linesWeek of 2026-02-22: +5,064 linesWeek of 2026-02-22: -811 linesWeek of 2026-03-01: +9,025 linesWeek of 2026-03-01: -1,219 linesWeek of 2026-03-08: +34,770 linesWeek of 2026-03-08: -19,522 linesWeek of 2026-03-15: +4,263 linesWeek of 2026-03-15: -535 linesWeek of 2026-03-22: +14,256 linesWeek of 2026-03-22: -1,905 linesWeek of 2026-03-29: +30,174 linesWeek of 2026-03-29: -8,825 linesWeek of 2026-04-05: +46,382 linesWeek of 2026-04-05: -2,840 linesWeek of 2026-04-12: +10,377 linesWeek of 2026-04-12: -3,605 linesWeek of 2026-04-19: +5,354 linesWeek of 2026-04-19: -2,097 linesWeek of 2026-04-26: +13,047 linesWeek of 2026-04-26: -4,251 linesWeek of 2026-05-03: +8,378 linesWeek of 2026-05-03: -921 linesWeek of 2026-05-10: +8,854 linesWeek of 2026-05-10: -1,165 linesWeek of 2026-05-17: +15,769 linesWeek of 2026-05-17: -1,151 linesWeek of 2026-05-24: +7,382 linesWeek of 2026-05-24: -969 linesWeek of 2026-05-31: +5,337 linesWeek of 2026-05-31: -1,614 linesWeek of 2026-06-07: +35,386 linesWeek of 2026-06-07: -2,096 linesWeek of 2026-06-14: +12,234 linesWeek of 2026-06-14: -1,490 linesWeek of 2026-06-21: +21,998 linesWeek of 2026-06-21: -2,469 linesWeek of 2026-06-28: +56,734 linesWeek of 2026-06-28: -4,045 linesWeek of 2026-07-05: +47,553 linesWeek of 2026-07-05: -2,658 linesWeek of 2026-07-12: +36,277 linesWeek of 2026-07-12: -8,430 linesWeek of 2026-07-19: +63,046 linesWeek of 2026-07-19: -5,251 linesWeek of 2026-07-26: +72,482 linesWeek of 2026-07-26: -7,745 linesWeek of 2026-08-02: +18,508 linesWeek of 2026-08-02: -1,842 linesWeek of 2026-08-09: +26,877 linesWeek of 2026-08-09: -3,390 linesWeek of 2026-08-16: +13,601 linesWeek of 2026-08-16: -595 linesWeek of 2026-08-23: +41,970 linesWeek of 2026-08-23: -2,313 linesWeek of 2026-08-30: +61,294 linesWeek of 2026-08-30: -3,849 linesWeek of 2026-09-06: +57,912 linesWeek of 2026-09-06: -3,542 linesWeek of 2026-09-13: +79,965 linesWeek of 2026-09-13: -7,064 linesWeek of 2026-09-20: +87,195 linesWeek of 2026-09-20: -5,533 linesWeek of 2026-09-27: +53,720 linesWeek of 2026-09-27: -3,835 linesOct 5, 2025Sep 27, 2026
+1.3M lines added, -331.4K removed over the last year.

Commits per week

last 52 weeks
2270Week of 2025-10-05: 3 commitsWeek of 2025-10-12: 11 commitsWeek of 2025-10-19: 23 commitsWeek of 2025-10-26: 12 commitsWeek of 2025-11-02: 1 commitsWeek of 2025-11-09: 2 commitsWeek of 2025-11-16: 5 commitsWeek of 2025-11-23: 13 commitsWeek of 2025-11-30: 7 commitsWeek of 2025-12-07: 6 commitsWeek of 2025-12-14: 6 commitsWeek of 2025-12-21: 10 commitsWeek of 2025-12-28: 3 commitsWeek of 2026-01-04: 9 commitsWeek of 2026-01-11: 166 commitsWeek of 2026-01-18: 208 commitsWeek of 2026-01-25: 166 commitsWeek of 2026-02-01: 227 commitsWeek of 2026-02-08: 114 commitsWeek of 2026-02-15: 8 commitsWeek of 2026-02-22: 21 commitsWeek of 2026-03-01: 30 commitsWeek of 2026-03-08: 47 commitsWeek of 2026-03-15: 26 commitsWeek of 2026-03-22: 83 commitsWeek of 2026-03-29: 91 commitsWeek of 2026-04-05: 86 commitsWeek of 2026-04-12: 44 commitsWeek of 2026-04-19: 37 commitsWeek of 2026-04-26: 59 commitsWeek of 2026-05-03: 40 commitsWeek of 2026-05-10: 35 commitsWeek of 2026-05-17: 46 commitsWeek of 2026-05-24: 29 commitsWeek of 2026-05-31: 22 commitsWeek of 2026-06-07: 70 commitsWeek of 2026-06-14: 57 commitsWeek of 2026-06-21: 66 commitsWeek of 2026-06-28: 63 commitsWeek of 2026-07-05: 87 commitsWeek of 2026-07-12: 113 commitsWeek of 2026-07-19: 109 commitsWeek of 2026-07-26: 120 commitsWeek of 2026-08-02: 32 commitsWeek of 2026-08-09: 42 commitsWeek of 2026-08-16: 27 commitsWeek of 2026-08-23: 61 commitsWeek of 2026-08-30: 80 commitsWeek of 2026-09-06: 97 commitsWeek of 2026-09-13: 135 commitsWeek of 2026-09-20: 188 commitsWeek of 2026-09-27: 142 commitsOct 5, 2025Sep 27, 2026
3.2K commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 11 commitsSun 1:00 — 0 commitsSun 2:00 — 1 commitsSun 3:00 — 1 commitsSun 4:00 — 4 commitsSun 5:00 — 4 commitsSun 6:00 — 2 commitsSun 7:00 — 17 commitsSun 8:00 — 21 commitsSun 9:00 — 29 commitsSun 10:00 — 43 commitsSun 11:00 — 45 commitsSun 12:00 — 10 commitsSun 13:00 — 12 commitsSun 14:00 — 17 commitsSun 15:00 — 32 commitsSun 16:00 — 25 commitsSun 17:00 — 27 commitsSun 18:00 — 9 commitsSun 19:00 — 26 commitsSun 20:00 — 29 commitsSun 21:00 — 47 commitsSun 22:00 — 63 commitsSun 23:00 — 31 commitsMon 0:00 — 11 commitsMon 1:00 — 2 commitsMon 2:00 — 2 commitsMon 3:00 — 9 commitsMon 4:00 — 2 commitsMon 5:00 — 1 commitsMon 6:00 — 8 commitsMon 7:00 — 26 commitsMon 8:00 — 29 commitsMon 9:00 — 39 commitsMon 10:00 — 25 commitsMon 11:00 — 26 commitsMon 12:00 — 16 commitsMon 13:00 — 18 commitsMon 14:00 — 35 commitsMon 15:00 — 39 commitsMon 16:00 — 37 commitsMon 17:00 — 19 commitsMon 18:00 — 17 commitsMon 19:00 — 21 commitsMon 20:00 — 18 commitsMon 21:00 — 27 commitsMon 22:00 — 29 commitsMon 23:00 — 26 commitsTue 0:00 — 9 commitsTue 1:00 — 3 commitsTue 2:00 — 1 commitsTue 3:00 — 2 commitsTue 4:00 — 2 commitsTue 5:00 — 2 commitsTue 6:00 — 2 commitsTue 7:00 — 15 commitsTue 8:00 — 27 commitsTue 9:00 — 36 commitsTue 10:00 — 33 commitsTue 11:00 — 42 commitsTue 12:00 — 8 commitsTue 13:00 — 29 commitsTue 14:00 — 21 commitsTue 15:00 — 21 commitsTue 16:00 — 20 commitsTue 17:00 — 29 commitsTue 18:00 — 22 commitsTue 19:00 — 24 commitsTue 20:00 — 16 commitsTue 21:00 — 37 commitsTue 22:00 — 51 commitsTue 23:00 — 44 commitsWed 0:00 — 3 commitsWed 1:00 — 4 commitsWed 2:00 — 4 commitsWed 3:00 — 5 commitsWed 4:00 — 2 commitsWed 5:00 — 3 commitsWed 6:00 — 5 commitsWed 7:00 — 26 commitsWed 8:00 — 35 commitsWed 9:00 — 44 commitsWed 10:00 — 61 commitsWed 11:00 — 21 commitsWed 12:00 — 16 commitsWed 13:00 — 12 commitsWed 14:00 — 28 commitsWed 15:00 — 24 commitsWed 16:00 — 31 commitsWed 17:00 — 19 commitsWed 18:00 — 15 commitsWed 19:00 — 26 commitsWed 20:00 — 18 commitsWed 21:00 — 32 commitsWed 22:00 — 29 commitsWed 23:00 — 36 commitsThu 0:00 — 7 commitsThu 1:00 — 10 commitsThu 2:00 — 2 commitsThu 3:00 — 3 commitsThu 4:00 — 6 commitsThu 5:00 — 3 commitsThu 6:00 — 1 commitsThu 7:00 — 20 commitsThu 8:00 — 34 commitsThu 9:00 — 42 commitsThu 10:00 — 28 commitsThu 11:00 — 40 commitsThu 12:00 — 22 commitsThu 13:00 — 23 commitsThu 14:00 — 36 commitsThu 15:00 — 49 commitsThu 16:00 — 43 commitsThu 17:00 — 37 commitsThu 18:00 — 18 commitsThu 19:00 — 16 commitsThu 20:00 — 26 commitsThu 21:00 — 25 commitsThu 22:00 — 32 commitsThu 23:00 — 29 commitsFri 0:00 — 5 commitsFri 1:00 — 1 commitsFri 2:00 — 1 commitsFri 3:00 — 1 commitsFri 4:00 — 3 commitsFri 5:00 — 2 commitsFri 6:00 — 2 commitsFri 7:00 — 16 commitsFri 8:00 — 25 commitsFri 9:00 — 39 commitsFri 10:00 — 28 commitsFri 11:00 — 30 commitsFri 12:00 — 6 commitsFri 13:00 — 14 commitsFri 14:00 — 55 commitsFri 15:00 — 53 commitsFri 16:00 — 41 commitsFri 17:00 — 31 commitsFri 18:00 — 19 commitsFri 19:00 — 20 commitsFri 20:00 — 24 commitsFri 21:00 — 53 commitsFri 22:00 — 51 commitsFri 23:00 — 35 commitsSat 0:00 — 15 commitsSat 1:00 — 0 commitsSat 2:00 — 4 commitsSat 3:00 — 2 commitsSat 4:00 — 0 commitsSat 5:00 — 4 commitsSat 6:00 — 5 commitsSat 7:00 — 7 commitsSat 8:00 — 21 commitsSat 9:00 — 26 commitsSat 10:00 — 38 commitsSat 11:00 — 36 commitsSat 12:00 — 9 commitsSat 13:00 — 7 commitsSat 14:00 — 17 commitsSat 15:00 — 37 commitsSat 16:00 — 42 commitsSat 17:00 — 38 commitsSat 18:00 — 41 commitsSat 19:00 — 26 commitsSat 20:00 — 26 commitsSat 21:00 — 46 commitsSat 22:00 — 65 commitsSat 23:00 — 35 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.
DateListRankStars gained
Sep 8, 2026daily#7+188
Sep 7, 2026daily#7+188
Aug 3, 2026daily#14+209
Aug 2, 2026daily#14+209
Jun 23, 2026daily#17+7
Jun 22, 2026daily#20+13
Mar 30, 2026daily#8+199
Mar 29, 2026daily#12+224
Mar 28, 2026daily#11+190
Mar 27, 2026daily#5+236
Mar 26, 2026daily#5+238
Mar 25, 2026daily#1+407
Mar 24, 2026daily#1+532
Mar 23, 2026daily#3+423
Mar 22, 2026daily#4+594