OpenSource-Hub

deer-flow

프레임워크

bytedance/deer-flow

연구, 코딩 및 창작을 지원하는 오픈 소스 장기 실행 슈퍼 에이전트 프레임워크.

개요

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

FAQ (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에서는 설정되지 않은 셸 변수가 빈 문자열로 확장되는 것을 방지하기 위해 기본값을 제공하세요:

GATEWAY_PORT: ${PORT:-8001}
GATEWAY_HOST: ${GATEWAY_HOST:-0.0.0.0}

backend/app/gateway/config.py의 영구적인 코드 수정: GATEWAY_PORT=0은 유지하면서 None과 ""만 설정되지 않은 것으로 처리합니다:

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"

원본 Issue #5800
문제 해결
디렉터리 스캔 중에 파일이 삭제되어 업로드 목록 조회가 500 FileNotFoundError를 반환하는 문제를 해결하는 방법

backend/packages/harness/deerflow/uploads/manager.py의 list_files_in_dir를 패치하여 파일시스템 경합(race)을 허용하도록 하세요. os.scandir() 이후에 entry.stat(follow_symlinks=False)를 try/except OSError로 감싸고, ENOENT, ENOTDIR, ELOOP와 같은 일시적인 조회 오류의 경우 해당 항목을 건너뛰되, EACCES와 같은 운영 오류는 다시 발생시키세요(re-raise). 또한 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를 발생시키는 상황을 시뮬레이션하여 사라진 항목은 건너뛰고 나머지 파일들은 반환되는지 확인하는 회귀 테스트를 추가하세요.

원본 Issue #6097
문제 해결
Python 3.13으로 업그레이드한 후 RunJournal.flush()가 크로스 스레드 미들웨어 이벤트를 유실하는 문제를 해결하는 방법

Python 3.13.16+ 및 3.14.8+에서 asyncio.to_thread()는 이벤트 루프에 양보하지 않고 재개될 수 있습니다. 따라서 워커에서 call_soon_threadsafe()로 큐에 추가된 콜백은 RunJournal.flush()가 버퍼를 확인하는 시점에 여전히 보류 중일 수 있습니다. flush()는 빈 버퍼를 보게 되고, _detach_runtime_dependencies()가 저널을 닫으며, 이후에 도착한 콜백은 _closed에서 조기 반환되어 마지막 미들웨어 이벤트를 조용히 유실합니다.

드레인하기 전에 한 번 양보한 뒤 닫힘 상태를 다시 확인하도록 flush()를 수정합니다:

async def flush(self):
    # 크로스 스레드 call_soon_threadsafe 콜백이 소유자 루프에 도착하도록 합니다.
    await asyncio.sleep(0)

    if self._closed:
        return

    # 기존 버퍼 드레인/큐 조인 로직이 여기에 이어집니다.

await journal.flush()를 _detach_runtime_dependencies() 앞에 유지하세요. 관찰 가능성/감사 경로에서도 마찬가지로, flush()가 큐를 조인하기 전에 보류 중인 외부 스레드 Usage/Audit 등록을 드레인하고, 워커를 닫힘으로 표시하기 전에 셧다운을 펜스하세요.

다음 명령으로 확인하세요:

cd backend
PYTHONPATH=. uv run pytest tests/test_run_journal.py::test_cross_thread_middleware_events_are_serialized_on_owner_loop

이 회귀는 gh-105836/GH-141696에서 비롯된 CPython _chain_future 변경으로 인해 발생합니다. Python 3.12.15는 추가 루프 반복을 강제하므로 Python 3.12로 고정하는 것이 임시 해결 방법이며, await asyncio.sleep(0) 펜스를 추가하면 3.12, 3.13, 3.14가 모두 수정됩니다.

원본 Issue #6564
문제 해결
glob 필터에 공백, 따옴표 또는 달러 기호가 포함되어 있을 때 E2B grep이 exit code 2로 실패하는 문제를 어떻게 해결하나요?

E2B issue #6528(fix(e2b): quote grep filename filters)에 대한 수정이 포함된 릴리스로 업그레이드하세요. 이 버그는 E2BSandbox.grep()이 --include=release *.txt와 같이 따옴표 처리되지 않은 셸 인수를 생성하기 때문에 발생하며, 이로 인해 셸이 해당 인수를 분할하거나 확장합니다. 어댑터를 패치할 때는 인수의 일부만이 아니라 전체 인수를 셸 인용 처리하세요. sh -c로 실행할 명령에 추가하기 전에 shlex.quote(f"--include={glob}")를 사용하세요. 트랜스포트가 지원하는 경우 ["grep", f"--include={glob}", ...]와 같은 argv 배열을 전달하는 것이 좋습니다. 이렇게 하면 와일드카드 의미를 유지하면서 공백, 아포스트로피, 큰따옴표, 리터럴 $ 문자가 보존됩니다. 임시 해결 방법으로는 *.txt와 같이 셸 메타 문자가 없는 glob을 사용하고 Python에서 일치하는 경로를 필터링하세요.

원본 Issue #6528
문제 해결
Helm으로 DeerFlow를 배포할 때 Live Browser WebSocket 연결이 실패(404 / 101 Switching Protocols 미발생)하는 이유는 무엇인가요?

Helm 차트의 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 핸드셰이크가 완료되지 않습니다.

수정 방법: Docker/로컬 nginx 설정에 이미 존재하는 것과 동일한 전용 location 블록을 configmap-nginx.yaml의 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 파드를 재시작하세요). 핸드셰이크가 성공하면 HTTP/1.1 101 Switching Protocols이 반환됩니다. make dev와 Docker 스택에는 이미 이 location이 포함되어 있으므로, 이 버그는 Helm으로 배포된 환경에서만 나타납니다. Gateway는 업그레이드 후에도 인증과 스레드 소유권을 계속 검사합니다.

원본 Issue #7147