Documentsdify
Plugin Daemon Architecture
Plugin Daemon Architecture
Type
Topic
Status
Published
Created
Jul 13, 2026
Updated
Jul 13, 2026

Plugin Daemon Architecture#

The Dify API communicates with the plugin daemon — a separate Go-based service (default port 5002) — for all plugin execution. The API never runs plugin code directly; every plugin invocation, model dispatch, tool call, and credential validation is proxied over HTTP to the daemon .

Dify API ──(HTTP/SSE)──► Plugin Daemon :5002
             X-Api-Key, X-Plugin-ID headers
             URL path: plugin/{tenant_id}/...

The daemon maintains its own PostgreSQL database (dify_plugin, separate from the main dify DB) and its own filesystem layout for installed plugin packages .


Request Routing: Headers and URL Structure#

All requests flow through BasePluginClient in api/core/plugin/impl/base.py. The request routing uses two complementary identification mechanisms:

  • Tenant ID — in the URL path: Every endpoint is prefixed with plugin/{tenant_id}/, scoping the request to a specific workspace. For example: plugin/{tenant_id}/dispatch/llm/invoke .
  • Plugin ID — in the X-Plugin-ID header: The specific installed plugin to invoke is set in the HTTP header on every dispatch call, e.g. "X-Plugin-ID": plugin_id . This is consistent across all plugin client implementations: model, tool, agent, trigger, datasource, and oauth .

A third header, X-Api-Key, carries PLUGIN_DAEMON_KEY and is injected by _prepare_request() on every call for daemon authentication . An optional traceparent header is appended when OpenTelemetry is enabled .

URL Patterns#

OperationURL Pattern
List model providersGET plugin/{tenant_id}/management/models
Invoke LLMPOST plugin/{tenant_id}/dispatch/llm/invoke
Validate credentialsPOST plugin/{tenant_id}/dispatch/model/validate_provider_credentials
Invoke toolPOST plugin/{tenant_id}/dispatch/tool/invoke

Response Format#

Responses are wrapped in a PluginDaemonBasicResponse envelope; non-zero code values trigger structured error handling in _handle_plugin_daemon_error(). Streaming endpoints (LLM, embeddings, rerank) use SSE; the client reads newline-delimited JSON lines via _stream_request() .


Configuration#

Configured in PluginConfig (api/configs/feature/__init__.py):

VariableDefaultPurpose
PLUGIN_DAEMON_URLhttp://localhost:5002Base URL for the plugin daemon
PLUGIN_DAEMON_KEYplugin-api-keyShared secret injected as X-Api-Key
PLUGIN_DAEMON_TIMEOUT600.0 sRequest timeout (set None to disable)

In Docker Compose the URL is typically http://plugin_daemon:5002 . The HTTP connection pool is bounded at 50 keep-alive / 100 max connections .


Version Synchronization#

The plugin daemon is versioned in lockstep with the Dify API. Protocol changes between releases cause complete communication failures if the versions diverge . Known pairings:

Dify APIPlugin Daemon
1.13.x0.5.x
1.14.x0.6.x
1.15.00.6.3-local

When the daemon version does not match the API, the daemon logs "failed to find the version of the plugin sdk" and the API returns connection errors .

Upgrade Checklist#

After any major version upgrade:

  1. Run the Alembic migration: docker compose exec api flask upgrade-db
  2. Run the plugin backfill: docker compose exec api flask backfill-plugin-auto-upgrade — normalizes plugin records after version identifier changes
  3. Confirm the daemon image tag matches the Dify release
  4. Remove stale plugin version directories from PLUGIN_INSTALLED_PATH

Common Upgrade Failures#

  • "record not found" / "Plugin table missing" (1.15.0+): Stale plugin version directories remain on disk; the backfill command resolves this .
  • "Credential with id … not found" (1.14.x): model_type enum values were renamed without a data migration; see Plugin Database Integrity for the SQL fix .
  • Duplicate plugin_unique_identifier (SQLSTATE 23505): Daemon crashes on startup during index creation; deduplicate the dify_plugin.plugins table before restarting .

Key Source References#

ResourceLink
BasePluginClient (HTTP layer)api/core/plugin/impl/base.py
PluginModelClient (model dispatch)api/core/plugin/impl/model.py
PluginConfig (configuration)api/configs/feature/init.py
Plugin Database Integrity patternsKnowledge Base article
Plugin Daemon Architecture | Dosu