CodeVetter
← All unpacks
CodeVetter · Repo Unpack evidence

langgenius/dify

Scanned commit 3a017e8ccc dated 2026-09-22 — last upstream commit. Generated by codevetter 1.12.0 on 2026-09-22.

github.com/langgenius/dify ↗ · 4000 files · 27.1 MB · scan capped

Dify Cloud · Self-hosting · Documentation · Dify edition overview Dify is an open-source LLM app development platform.

Deep analysis by swe-2 via the devin CLI on 2026-09-22 (runtime not recorded) — every claim below links to its cited source files.

Overview

Dify is an open-source platform for building, hosting, and operating LLM applications — chatbots, RAG pipelines, agentic workflows, and MCP services — exposed through four HTTP surfaces (console admin, end-user webapp, service API, and MCP/trigger/webhook ingress). The monorepo contains a Flask/SQLAlchemy/Celery Python backend (`api/`, served via gevent gunicorn at :5001), a Next.js standalone console (`web/`), a generated-contract pnpm workspace (`packages/contracts` feeds an oRPC `consoleClient`), a Go job-sandbox runtime (`dify-agent-runtime/`), a Python agent backend (`dify-agent/`), and a Node/TS CLI (`cli/`, difyctl). Everything is deployed via generated Docker Compose with Postgres+Redis plus a pluggable fleet of ~28 vector stores, object stores, an external plugin daemon, and Squid SSRF proxies. The codebase is heavily productionized: license gating, quota/rate limiting, SSRF protection, human-in-the-loop pause/resume, and edition-aware (community/cloud/enterprise) feature flags are woven into the request path.

System map

The system is a modular monolith API (Flask + flask-restx + SQLAlchemy + Celery) plus a Next.js console, with execution-heavy work pushed to Celery workers and sidecar services (plugin daemon, sandbox, agent runtime, SSRF proxy). `api/app.py` is the process entrypoint; `app_factory.create_app()` builds a `DifyApp`, runs an ordered list of ~30 `extensions/ext_*` initializers, and wraps the result in `socketio.WSGIApp`. HTTP ingress is split across eight Flask blueprints registered in `ext_blueprints.py`, each with its own CORS/auth surface. State lives in Postgres (Alembic, 219 migration files), Redis (broker, cache, rate limits, pub/sub for SSE), pluggable object storage, and pluggable vector DBs loaded via Python entry points.

All 15 system map claims →

Feature catalog

User-facing capability is organized around typed `AppMode`s, each with its own generator under `core/app/apps/*` and matching controller surface. The console blueprint exposes the full authoring/admin surface (apps, datasets/knowledge, plugins, triggers, MCP servers, agent apps, billing/features, auth). The `/api` web blueprint serves published end-user apps; `/v1` service_api serves token-authed programmatic access; `/mcp`, `/triggers`, and `/inner/api` handle protocol ingress. Async work (indexing, mail, cleanup, triggers, telemetry) is a large Celery task fleet under `api/tasks/` and `api/schedule/` with a feature-flagged beat schedule.

All 15 feature catalog claims →

Data flow

Every generate request follows the same spine: blueprint → flask-restx Resource → auth decorator (JWT passport, session, API token, or inner-api key) → Pydantic payload validation → `services/` orchestration → `core/app/apps/*` generator → `graphon` GraphEngine events → Redis pub/sub → SSE stream to the caller. Writes go through SQLAlchemy sessions (Postgres) with explicit tenant scoping; large payloads and files go through `ext_storage` backends; model/tool/plugin invocations egress through the plugin daemon over HTTP; arbitrary outbound HTTP from nodes/tools is forced through the Squid SSRF proxy. Config flows from pydantic-settings (env/.env/TOML/remote) into `app.config` at boot.

All 15 data flow claims →

Behavior traces

Three flows traced end-to-end: (1) API server startup, (2) end-user streaming chat message across the request→Celery→SSE boundary, and (3) the `flask db` migration path plus Celery worker boot. The dominant pattern is 'authenticate at the edge, rehydrate trusted state inside the worker, stream events back through Redis'.

All 13 behavior traces claims →

Testing signals

Testing is layered and unusually heavy: ~1655 Python test files split into `unit_tests`, `integration_tests` (Docker-backed, CI-only), and `test_containers_integration_tests`, plus per-provider `vdb/*/tests` and `trace/*/tests` in the uv workspace. Web uses Vitest (+browser mode), e2e uses Cucumber+Playwright with accessibility (axe/WCAG) lanes, cli uses Vitest against a real Hono mock server, and the Go runtime has colocated `*_test.go`. CI shards API unit tests by historical durations and gates on codecov.

All 13 testing signals claims →

Risk map

The highest-risk surface is execution of untrusted work: SSRF-bearing HTTP egress, sandboxed code execution, shell job runtime with Landlock, and plugin-daemon RPC — all defended in depth but dependent on every caller routing through the right proxy. Auth is layered (session JWT, passport JWT, API tokens, shared inner-api key) with enterprise license gating able to fail closed across nearly every surface. Fragile spots: committed static test secrets, `ignoreBuildErrors` on the web build, a giant ordered extension-init list, and tenant-scoping discipline enforced by convention.

All 15 risk map claims →

Extension points

Dify is built for extension at every layer: app modes via generator classes + a match-dispatch, workflow nodes via `DifyNodeFactory`/`resolve_workflow_node_class` (with most builtins now in the external `graphon` package), vector/trace backends via Python entry-point packages, storage via a `StorageType` match, remote config via named sources, HTTP routes via flask-restx Namespaces + module import lists, Celery work via the imports+beat_schedule assembly, moderation/tool/providers via factories and the external plugin daemon, CLI verbs via a generated command tree, and frontend calls via regenerated oRPC contracts.

All 15 extension points claims →

Contributor handoff

This repo is agent-aware: layered AGENTS.md files (root, api/, web/, cli/, e2e/, dify-agent/) define per-area rules that must be read before editing. Backend work runs through `uv run --project api` and root `make` targets; frontend through pnpm/vp; CLI through pnpm with generated artifacts. Generated files (docker-compose.yaml, tree.generated.ts, contracts/generated, openapi specs) must never be hand-edited. The dominant correctness disciplines are tenant scoping, explicit bounded transactions, SSRF-routed egress, Pydantic v2 contracts at controller boundaries, and idempotent Celery tasks.

All 14 contributor handoff claims →

Languages

LanguageFilesShare of source
TypeScript684561%
Python410137%
JSON1002docs/config
Markdown178docs/config
JavaScript1361%
YAML128docs/config
CSS68docs/config
Go661%

Start reading here

Probable source entrypoint: packages/ — inferred from the directory tree and manifest, not the upstream docs.

Source roots

packages/ (928 files)

Repository structure

Top-level pathFiles
api/928
packages/928
web/927
cli/362
dify-agent/290
e2e/155
docker/82
dify-agent-runtime/73

Docs found: AGENTS.mdCONTRIBUTING.mdREADME.mddocs/ADVANCED_SETUP.mddocs/ar-SA/ADVANCED_SETUP.mddocs/ar-SA/README.mddocs/bn-BD/ADVANCED_SETUP.mddocs/bn-BD/README.mddocs/cross-env-app-migration/README.mddocs/de-DE/ADVANCED_SETUP.md

Package

package.json — dify, 33 declared dependencies.

@eslint-community/eslint-plugin-eslint-comments@eslint-react/eslint-plugin@eslint/markdown@iconify-json/heroicons@iconify-json/ri@shadcn/lint@tanstack/eslint-plugin-query@types/node@typescript-eslint/parser@typescript/nativeconcurrentlyeslint

CI & config entrypoints

Structural health signals

Average score 6.5/10 across 96 analyzed source files; 45 hotspots surfaced.

These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.

Recent history