Refactor DeerFlow to use Gateway's LangGraph-compatible API
- Updated documentation and comments to reflect the transition from LangGraph Server to Gateway. - Changed default URLs in ChannelManager and tests to point to Gateway. - Removed references to LangGraph Server in deployment scripts and configurations. - Updated Nginx configuration to route API traffic to Gateway. - Adjusted frontend configurations to utilize Gateway's API. - Removed LangGraph service from Docker Compose files, consolidating services under Gateway. - Added regression tests to ensure Gateway integration works as expected. Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -4,8 +4,7 @@
|
||||
# Services:
|
||||
# - nginx: Reverse proxy (port 2026)
|
||||
# - frontend: Frontend Next.js dev server (port 3000)
|
||||
# - gateway: Backend Gateway API (port 8001)
|
||||
# - langgraph: LangGraph server (port 2024)
|
||||
# - gateway: Backend Gateway API + agent runtime (port 8001)
|
||||
# - provisioner (optional): Sandbox provisioner (creates Pods in host Kubernetes)
|
||||
#
|
||||
# Prerequisites:
|
||||
@@ -61,9 +60,7 @@ services:
|
||||
start_period: 15s
|
||||
|
||||
# ── Reverse Proxy ──────────────────────────────────────────────────────
|
||||
# Routes API traffic to gateway/langgraph and (optionally) provisioner.
|
||||
# LANGGRAPH_UPSTREAM and LANGGRAPH_REWRITE control gateway vs standard
|
||||
# routing (processed by envsubst at container start).
|
||||
# Routes API traffic to gateway and (optionally) provisioner.
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: deer-flow-nginx
|
||||
@@ -71,16 +68,12 @@ services:
|
||||
- "2026:2026"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf.template:ro
|
||||
environment:
|
||||
- LANGGRAPH_UPSTREAM=${LANGGRAPH_UPSTREAM:-langgraph:2024}
|
||||
- LANGGRAPH_REWRITE=${LANGGRAPH_REWRITE:-/}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
envsubst '$$LANGGRAPH_UPSTREAM $$LANGGRAPH_REWRITE' \
|
||||
< /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
||||
cp /etc/nginx/nginx.conf.template /etc/nginx/nginx.conf
|
||||
test -e /proc/net/if_inet6 || sed -i '/^[[:space:]]*listen[[:space:]]\+\[::\]:2026;/d' /etc/nginx/nginx.conf
|
||||
exec nginx -g 'daemon off;'
|
||||
depends_on:
|
||||
@@ -114,7 +107,6 @@ services:
|
||||
- WATCHPACK_POLLING=true
|
||||
- CI=true
|
||||
- DEER_FLOW_INTERNAL_GATEWAY_BASE_URL=http://gateway:8001
|
||||
- DEER_FLOW_INTERNAL_LANGGRAPH_BASE_URL=http://langgraph:2024
|
||||
env_file:
|
||||
- ../frontend/.env
|
||||
networks:
|
||||
@@ -147,7 +139,7 @@ services:
|
||||
# On macOS/Docker Desktop, uv may fail to create symlinks inside shared
|
||||
# host directories, which causes startup-time `uv sync` to crash.
|
||||
- gateway-uv-cache:/root/.cache/uv
|
||||
# DooD: same as gateway — AioSandboxProvider runs inside LangGraph process.
|
||||
# DooD: AioSandboxProvider runs inside the Gateway process.
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
# CLI auth directories for auto-auth (Claude Code + Codex CLI)
|
||||
- type: bind
|
||||
@@ -166,7 +158,7 @@ services:
|
||||
environment:
|
||||
- CI=true
|
||||
- DEER_FLOW_HOME=/app/backend/.deer-flow
|
||||
- DEER_FLOW_CHANNELS_LANGGRAPH_URL=${DEER_FLOW_CHANNELS_LANGGRAPH_URL:-http://langgraph:2024}
|
||||
- DEER_FLOW_CHANNELS_LANGGRAPH_URL=${DEER_FLOW_CHANNELS_LANGGRAPH_URL:-http://gateway:8001/api}
|
||||
- DEER_FLOW_CHANNELS_GATEWAY_URL=${DEER_FLOW_CHANNELS_GATEWAY_URL:-http://gateway:8001}
|
||||
- DEER_FLOW_HOST_BASE_DIR=${DEER_FLOW_ROOT}/backend/.deer-flow
|
||||
- DEER_FLOW_HOST_SKILLS_PATH=${DEER_FLOW_ROOT}/skills
|
||||
@@ -180,70 +172,11 @@ services:
|
||||
- deer-flow-dev
|
||||
restart: unless-stopped
|
||||
|
||||
# Backend - LangGraph Server
|
||||
langgraph:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: backend/Dockerfile
|
||||
target: dev
|
||||
# cache_from disabled - requires manual setup: mkdir -p /tmp/docker-cache-langgraph
|
||||
args:
|
||||
APT_MIRROR: ${APT_MIRROR:-}
|
||||
UV_IMAGE: ${UV_IMAGE:-ghcr.io/astral-sh/uv:0.7.20}
|
||||
UV_INDEX_URL: ${UV_INDEX_URL:-https://pypi.org/simple}
|
||||
container_name: deer-flow-langgraph
|
||||
command: sh -c "cd backend && { (uv sync || (echo '[startup] uv sync failed; recreating .venv and retrying once' && uv venv --allow-existing .venv && uv sync)) && allow_blocking='' && if [ \"\${LANGGRAPH_ALLOW_BLOCKING:-0}\" = '1' ]; then allow_blocking='--allow-blocking'; fi && uv run langgraph dev --no-browser \${allow_blocking} --host 0.0.0.0 --port 2024 --n-jobs-per-worker \${LANGGRAPH_JOBS_PER_WORKER:-10}; } > /app/logs/langgraph.log 2>&1"
|
||||
volumes:
|
||||
- ../backend/:/app/backend/
|
||||
# Preserve the .venv built during Docker image build — mounting the full backend/
|
||||
# directory above would otherwise shadow it with the (empty) host directory.
|
||||
- langgraph-venv:/app/backend/.venv
|
||||
- ../config.yaml:/app/config.yaml
|
||||
- ../extensions_config.json:/app/extensions_config.json
|
||||
- ../skills:/app/skills
|
||||
- ../logs:/app/logs
|
||||
# Use a Docker-managed uv cache volume instead of a host bind mount.
|
||||
# On macOS/Docker Desktop, uv may fail to create symlinks inside shared
|
||||
# host directories, which causes startup-time `uv sync` to crash.
|
||||
- langgraph-uv-cache:/root/.cache/uv
|
||||
# DooD: same as gateway — AioSandboxProvider runs inside LangGraph process.
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
# CLI auth directories for auto-auth (Claude Code + Codex CLI)
|
||||
- type: bind
|
||||
source: ${HOME:?HOME must be set}/.claude
|
||||
target: /root/.claude
|
||||
read_only: true
|
||||
bind:
|
||||
create_host_path: true
|
||||
- type: bind
|
||||
source: ${HOME:?HOME must be set}/.codex
|
||||
target: /root/.codex
|
||||
read_only: true
|
||||
bind:
|
||||
create_host_path: true
|
||||
working_dir: /app
|
||||
environment:
|
||||
- CI=true
|
||||
- DEER_FLOW_HOME=/app/backend/.deer-flow
|
||||
- DEER_FLOW_HOST_BASE_DIR=${DEER_FLOW_ROOT}/backend/.deer-flow
|
||||
- DEER_FLOW_HOST_SKILLS_PATH=${DEER_FLOW_ROOT}/skills
|
||||
- DEER_FLOW_SANDBOX_HOST=host.docker.internal
|
||||
env_file:
|
||||
- ../.env
|
||||
extra_hosts:
|
||||
# For Linux: map host.docker.internal to host gateway
|
||||
- "host.docker.internal:host-gateway"
|
||||
networks:
|
||||
- deer-flow-dev
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
# Persist .venv across container restarts so dependencies installed during
|
||||
# image build are not shadowed by the host backend/ directory mount.
|
||||
gateway-venv:
|
||||
langgraph-venv:
|
||||
gateway-uv-cache:
|
||||
langgraph-uv-cache:
|
||||
|
||||
networks:
|
||||
deer-flow-dev:
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
# Services:
|
||||
# - nginx: Reverse proxy (port 2026, configurable via PORT env var)
|
||||
# - frontend: Next.js production server
|
||||
# - gateway: FastAPI Gateway API
|
||||
# - langgraph: LangGraph production server (Dockerfile generated by langgraph dockerfile)
|
||||
# - gateway: FastAPI Gateway API + agent runtime
|
||||
# - provisioner: (optional) Sandbox provisioner for Kubernetes mode
|
||||
#
|
||||
# Key environment variables (set via environment/.env or scripts/deploy.sh):
|
||||
@@ -30,12 +29,8 @@ services:
|
||||
- "${PORT:-2026}:2026"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf.template:ro
|
||||
environment:
|
||||
- LANGGRAPH_UPSTREAM=${LANGGRAPH_UPSTREAM:-langgraph:2024}
|
||||
- LANGGRAPH_REWRITE=${LANGGRAPH_REWRITE:-/}
|
||||
command: >
|
||||
sh -c "envsubst '$$LANGGRAPH_UPSTREAM $$LANGGRAPH_REWRITE'
|
||||
< /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
||||
sh -c "cp /etc/nginx/nginx.conf.template /etc/nginx/nginx.conf
|
||||
&& nginx -g 'daemon off;'"
|
||||
depends_on:
|
||||
- frontend
|
||||
@@ -57,7 +52,6 @@ services:
|
||||
environment:
|
||||
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
|
||||
- DEER_FLOW_INTERNAL_GATEWAY_BASE_URL=http://gateway:8001
|
||||
- DEER_FLOW_INTERNAL_LANGGRAPH_BASE_URL=http://langgraph:2024
|
||||
env_file:
|
||||
- ../frontend/.env
|
||||
networks:
|
||||
@@ -102,7 +96,7 @@ services:
|
||||
- DEER_FLOW_HOME=/app/backend/.deer-flow
|
||||
- DEER_FLOW_CONFIG_PATH=/app/backend/config.yaml
|
||||
- DEER_FLOW_EXTENSIONS_CONFIG_PATH=/app/backend/extensions_config.json
|
||||
- DEER_FLOW_CHANNELS_LANGGRAPH_URL=${DEER_FLOW_CHANNELS_LANGGRAPH_URL:-http://langgraph:2024}
|
||||
- DEER_FLOW_CHANNELS_LANGGRAPH_URL=${DEER_FLOW_CHANNELS_LANGGRAPH_URL:-http://gateway:8001/api}
|
||||
- DEER_FLOW_CHANNELS_GATEWAY_URL=${DEER_FLOW_CHANNELS_GATEWAY_URL:-http://gateway:8001}
|
||||
# DooD path/network translation
|
||||
- DEER_FLOW_HOST_BASE_DIR=${DEER_FLOW_HOME}
|
||||
@@ -116,58 +110,6 @@ services:
|
||||
- deer-flow
|
||||
restart: unless-stopped
|
||||
|
||||
# ── LangGraph Server ───────────────────────────────────────────────────────
|
||||
# TODO: switch to langchain/langgraph-api (licensed) once a license key is available.
|
||||
# For now, use `langgraph dev` (no license required) with the standard backend image.
|
||||
langgraph:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: backend/Dockerfile
|
||||
args:
|
||||
APT_MIRROR: ${APT_MIRROR:-}
|
||||
UV_IMAGE: ${UV_IMAGE:-ghcr.io/astral-sh/uv:0.7.20}
|
||||
UV_INDEX_URL: ${UV_INDEX_URL:-https://pypi.org/simple}
|
||||
UV_EXTRAS: ${UV_EXTRAS:-}
|
||||
container_name: deer-flow-langgraph
|
||||
command: sh -c 'cd /app/backend && args="--no-browser --no-reload --host 0.0.0.0 --port 2024 --n-jobs-per-worker $${LANGGRAPH_JOBS_PER_WORKER:-10}" && if [ "$${LANGGRAPH_ALLOW_BLOCKING:-0}" = "1" ]; then args="$$args --allow-blocking"; fi && uv run langgraph dev $$args'
|
||||
volumes:
|
||||
- ${DEER_FLOW_CONFIG_PATH}:/app/backend/config.yaml:ro
|
||||
- ${DEER_FLOW_EXTENSIONS_CONFIG_PATH}:/app/backend/extensions_config.json:ro
|
||||
- ${DEER_FLOW_HOME}:/app/backend/.deer-flow
|
||||
- ../skills:/app/skills:ro
|
||||
- ../backend/.langgraph_api:/app/backend/.langgraph_api
|
||||
# DooD: same as gateway
|
||||
- ${DEER_FLOW_DOCKER_SOCKET}:/var/run/docker.sock
|
||||
# CLI auth directories for auto-auth (Claude Code + Codex CLI)
|
||||
- type: bind
|
||||
source: ${HOME:?HOME must be set}/.claude
|
||||
target: /root/.claude
|
||||
read_only: true
|
||||
bind:
|
||||
create_host_path: true
|
||||
- type: bind
|
||||
source: ${HOME:?HOME must be set}/.codex
|
||||
target: /root/.codex
|
||||
read_only: true
|
||||
bind:
|
||||
create_host_path: true
|
||||
environment:
|
||||
- CI=true
|
||||
- DEER_FLOW_HOME=/app/backend/.deer-flow
|
||||
- DEER_FLOW_CONFIG_PATH=/app/backend/config.yaml
|
||||
- DEER_FLOW_EXTENSIONS_CONFIG_PATH=/app/backend/extensions_config.json
|
||||
- DEER_FLOW_HOST_BASE_DIR=${DEER_FLOW_HOME}
|
||||
- DEER_FLOW_HOST_SKILLS_PATH=${DEER_FLOW_REPO_ROOT}/skills
|
||||
- DEER_FLOW_SANDBOX_HOST=host.docker.internal
|
||||
# LangSmith tracing: set LANGSMITH_TRACING=true and LANGSMITH_API_KEY in .env to enable.
|
||||
env_file:
|
||||
- ../.env
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
networks:
|
||||
- deer-flow
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Sandbox Provisioner (optional, Kubernetes mode) ────────────────────────
|
||||
provisioner:
|
||||
build:
|
||||
|
||||
+4
-10
@@ -26,10 +26,6 @@ http {
|
||||
server gateway:8001;
|
||||
}
|
||||
|
||||
upstream langgraph {
|
||||
server ${LANGGRAPH_UPSTREAM};
|
||||
}
|
||||
|
||||
upstream frontend {
|
||||
server frontend:3000;
|
||||
}
|
||||
@@ -56,13 +52,11 @@ http {
|
||||
return 204;
|
||||
}
|
||||
|
||||
# LangGraph API routes
|
||||
# In standard mode: /api/langgraph/* → langgraph:2024 (rewrite to /*)
|
||||
# In gateway mode: /api/langgraph/* → gateway:8001 (rewrite to /api/*)
|
||||
# Controlled by LANGGRAPH_UPSTREAM and LANGGRAPH_REWRITE env vars.
|
||||
# LangGraph-compatible API routes served by Gateway.
|
||||
# Rewrites /api/langgraph/* to /api/* before proxying to Gateway.
|
||||
location /api/langgraph/ {
|
||||
rewrite ^/api/langgraph/(.*) ${LANGGRAPH_REWRITE}$1 break;
|
||||
proxy_pass http://langgraph;
|
||||
rewrite ^/api/langgraph/(.*) /api/$1 break;
|
||||
proxy_pass http://gateway;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# Headers
|
||||
|
||||
@@ -19,10 +19,6 @@ http {
|
||||
server 127.0.0.1:8001;
|
||||
}
|
||||
|
||||
upstream langgraph {
|
||||
server 127.0.0.1:2024;
|
||||
}
|
||||
|
||||
upstream frontend {
|
||||
server 127.0.0.1:3000;
|
||||
}
|
||||
@@ -48,38 +44,10 @@ http {
|
||||
return 204;
|
||||
}
|
||||
|
||||
# LangGraph API routes (served by langgraph dev)
|
||||
# Rewrites /api/langgraph/* to /* before proxying to LangGraph server
|
||||
# LangGraph-compatible API routes served by Gateway.
|
||||
# Rewrites /api/langgraph/* to /api/* before proxying to Gateway.
|
||||
location /api/langgraph/ {
|
||||
rewrite ^/api/langgraph/(.*) /$1 break;
|
||||
proxy_pass http://langgraph;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# Headers
|
||||
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_set_header Connection '';
|
||||
|
||||
# SSE/Streaming support
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_set_header X-Accel-Buffering no;
|
||||
|
||||
# Timeouts for long-running requests
|
||||
proxy_connect_timeout 600s;
|
||||
proxy_send_timeout 600s;
|
||||
proxy_read_timeout 600s;
|
||||
|
||||
# Chunked transfer encoding
|
||||
chunked_transfer_encoding on;
|
||||
}
|
||||
|
||||
# Experimental: Gateway-backed LangGraph-compatible API
|
||||
# Frontend can opt-in via NEXT_PUBLIC_LANGGRAPH_BASE_URL=/api/langgraph-compat
|
||||
location /api/langgraph-compat/ {
|
||||
rewrite ^/api/langgraph-compat/(.*) /api/$1 break;
|
||||
rewrite ^/api/langgraph/(.*) /api/$1 break;
|
||||
proxy_pass http://gateway;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user