项目简介
DeerFlow 是一个开源超级代理框架,协调子代理、记忆、沙箱与技能,处理从分钟到小时级的任务。支持深度研究、编码和内容创作,具有可扩展工具和多代理工作流。
README 预览
# 🦌 DeerFlow - 2.0\n\nEnglish | [中文](./README_zh.md) | [日本語](./README_ja.md) | [Français](./README_fr.md) | [Русский](./README_ru.md)\n\n[](./backend/pyproject.toml)\n[](./Makefile)\n[](./LICENSE)\n\n\n> 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! 💪🔥\n\nDeerFlow (**D**eep **E**xploration and **E**fficient **R**esearch **Flow**) is an open-source **super agent harness** that orchestrates **sub-agents**, **memory**, and **sandboxes** to do almost anything — powered by **extensible skills**.\n\nhttps://github.com/user-attachments/assets/a8bcadc4-e040-4cf2-8fda-dd768b999c18\n\n> [!NOTE]\n> **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](https://github.com/bytedance/deer-flow/tree/main-1.x) — contributions there are still welcome. Active development has moved to 2.0.\n\n## Official Website\n\n[](https://deerflow.tech)\n\nLearn more and see **real demos** on our [**official website**](https://deerflow.tech).\n\n## Coding Plan from ByteDance Volcengine\n\n\n\n- We strongly recommend using Doubao-Seed-2.0-Code, DeepSeek v3.2 and Kimi 2.5 to run DeerFlow\n- [Learn more](https://www.byteplus.com/en/activity/codingplan?utm_campaign=deer_flow&utm_content=deer_flow&utm_medium=devrel&utm_source=OWO&utm_term=deer_flow)\n- [中国大陆地区的开发者请点击这里](https://www.volcengine.com/activity/codingplan?utm_campaign=deer_flow&utm_content=deer_flow&utm_medium=devrel&utm_source=OWO&utm_term=deer_flow)\n\n## InfoQuest\n\nDeerFlow has newly integrated the intelligent search and crawling toolset independently developed by BytePlus--[InfoQuest (supports free online experience)](https://docs.byteplus.com/en/docs/InfoQuest/What_is_Info_Quest)\n\n\n \n\n\n---\n\n## Table of Contents\n\n- [🦌 DeerFlow - 2.0](#-deerflow---20)\n - [Official Website](#offici
常见问题 (5)
故障排除如何修复由 DeerFlow 中 GATEWAY_PORT 为空导致的 "ValueError: invalid literal for int() with base 10: ''" 错误?
网关启动失败,因为 os.getenv("GATEWAY_PORT", "8001") 只有在变量未设置时才返回默认值;已定义但为空的变量会变成 "",而 int("") 会抛出 ValueError。
临时解决方法:取消设置该变量,或提供一个有效的数字端口:
unset GATEWAY_PORT
uv run uvicorn app.gateway.app:app --port 8001
或者显式设置它:
GATEWAY_PORT=8001 GATEWAY_HOST=0.0.0.0 uv run uvicorn app.gateway.app:app --port 8001
对于 Docker,不要使用 -e GATEWAY_PORT=;要么省略该变量,要么传入一个值:
docker run -e GATEWAY_PORT=8001 ...
在 Docker Compose 中,提供默认值,以防止未设置的 shell 变量展开为空字符串:
GATEWAY_PORT: ${PORT:-8001}
GATEWAY_HOST: ${GATEWAY_HOST:-0.0.0.0}
在 backend/app/gateway/config.py 中进行永久性代码修复:仅将 None 和 "" 视为未设置,同时保留 GATEWAY_PORT=0 的情况:
port_raw = os.getenv("GATEWAY_PORT")
port = 8001 if port_raw is None or port_raw == "" else int(port_raw)
host = os.getenv("GATEWAY_HOST") or "0.0.0.0"故障排除如何修复在目录扫描期间文件被删除时上传列表返回 500 FileNotFoundError 的问题?
修补 backend/packages/harness/deerflow/uploads/manager.py 中的 list_files_in_dir,使其能够容忍文件系统竞态。在 os.scandir() 之后,将 entry.stat(follow_symlinks=False) 包裹在 try/except OSError 中;对于 ENOENT、ENOTDIR 和 ELOOP 等瞬态查找错误,跳过该条目;而对于 EACCES 等操作性错误则重新抛出。还需处理目录在 os.scandir 之前或执行期间消失的情况,此时返回已收集的条目。
示例:
try:
st = entry.stat(follow_symlinks=False)
except OSError as e:
if e.errno in (errno.ENOENT, errno.ENOTDIR, errno.ELOOP):
continue
raise
不要依赖 entry.is_file() 来防止此问题:在 POSIX 上,它可能使用 scandir 缓存的 d_type,而不会再次检查文件系统。添加一个回归测试,模拟 stat() 抛出 FileNotFoundError,并验证已消失的条目被跳过,同时其余文件仍被返回。
故障排除升级到 Python 3.13 后,如何修复 RunJournal.flush() 丢弃跨线程中间件事件的问题?
在 Python 3.13.16+ 和 3.14.8+ 上,asyncio.to_thread() 可以在不让出事件循环的情况下恢复执行。因此,当 RunJournal.flush() 检查缓冲区时,由工作线程通过 call_soon_threadsafe() 排队的回调可能仍处于挂起状态。flush() 看到空缓冲区,_detach_runtime_dependencies() 关闭了 journal,而稍后的回调在 _closed 处提前返回,从而静默丢弃了最后一个中间件事件。
修复 flush():在排空缓冲区之前先让出一次执行权,然后重新检查关闭状态:
async def flush(self):
# Let cross-thread call_soon_threadsafe callbacks land on the owner loop.
await asyncio.sleep(0)
if self._closed:
return
# Existing buffer-drain/queue-join logic follows here.
保持 await journal.flush() 位于 _detach_runtime_dependencies() 之前。对于可观测性/审计路径,同样要在 flush() join 队列之前,先排空来自其他线程的待处理 Usage/Audit 入队操作,并在将工作线程标记为已关闭之前为关闭操作设置屏障(fence)。
使用以下命令验证:
cd backend
PYTHONPATH=. uv run pytest tests/test_run_journal.py::test_cross_thread_middleware_events_are_serialized_on_owner_loop
该回归问题由 CPython 的 _chain_future 变更(gh-105836/GH-141696)引起。Python 3.12.15 会强制执行额外的一次循环迭代,因此固定使用 Python 3.12 只是一个临时变通方案;添加 await asyncio.sleep(0) 屏障可以同时修复 3.12、3.13 和 3.14。
故障排除当 glob 过滤器包含空格、引号或美元符号时,如何修复 E2B grep 以 exit code 2 失败的问题?
升级到包含 E2B issue #6528 修复的版本(fix(e2b): quote grep filename filters)。该 bug 的产生原因是 E2BSandbox.grep() 构建了未加引号的 shell 参数,例如 --include=release *.txt,导致 shell 对其进行拆分或展开。修补适配器时,应对完整参数进行 shell 引号转义,而不仅是其中一部分:在将其追加到通过 sh -c 运行的命令之前,使用 shlex.quote(f"--include={glob}")。如果传输层支持,优先传递 argv 数组,例如 ["grep", f"--include={glob}", ...]。这样既能保留空格、单引号、双引号和字面量 $ 字符,又能保留通配符语义。作为临时变通方案,可使用不含 shell 元字符的 glob(例如 *.txt),并在 Python 中过滤匹配的路径。
故障排除为什么在通过 Helm 部署 DeerFlow 时,Live Browser 的 WebSocket 连接会失败(404 / 没有返回 101 Switching Protocols)?
Helm chart 中的 nginx ConfigMap(deploy/helm/deer-flow/templates/configmap-nginx.yaml)没有为 Live Browser 端点 /api/threads/<thread_id>/browser/stream 配置专用的 location。请求会落入通用的 threads location,该 location 会剥离 Upgrade: websocket 并将 Connection 重写为 close,导致 Gateway 收到的是普通 HTTP 请求,WebSocket 握手永远无法完成。
修复方法:在 configmap-nginx.yaml 的 nginx 模板中添加一个专用的 location 块,与 Docker/本地 nginx 配置中已有的配置保持一致:
location ~ ^/api/threads/[^/]+/browser/stream {
proxy_pass http://gateway;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
}
然后使用 helm upgrade 重新部署(或通过 helm template 重新渲染并重启 nginx pod)。握手成功后会返回 HTTP/1.1 101 Switching Protocols。请注意,make dev 和 Docker 环境已经包含了此 location,因此该 bug 只会出现在通过 Helm 部署的环境中。升级完成后,Gateway 仍会强制执行身份验证和线程所有权校验。