Agent Runtime Backend Initialization#
Overview#
The dify-agent FastAPI server initializes runtime backends at startup through a two-stage process: ServerSettings resolves environment variables into a RuntimeBackendProfile, and create_default_layer_providers() wires that profile into the layer provider set consumed by the run scheduler. Layers and providers never read environment variables directly β all credentials and endpoints are injected by the server at construction time.
Initialization Flow#
create_app() in app.py orchestrates startup:
ServerSettingsis instantiated, loading allDIFY_AGENT_*environment variables via Pydantic Settings.settings.build_runtime_backend_profile()callscreate_runtime_backend_profile(RuntimeBackendSettings(...))to produce aRuntimeBackendProfileβ orNonewhenruntime_backend == "local"but nolocal_sandbox_endpointis set .create_default_layer_providers()receives the profile plus plugin-daemon/inner-API credentials, building a tuple ofLayerProviderobjects. TheDifyRuntimeLayerprovider is only appended whenruntime_backend_profile is not None.- The resulting
layer_providerstuple is passed toRunSchedulerduring the FastAPI lifespan , where it services all subsequent run requests in-process.
ServerSettings (env vars)
ββ build_runtime_backend_profile()
ββ create_runtime_backend_profile(RuntimeBackendSettings)
ββ RuntimeBackendProfile { execution_bindings, home_snapshots }
β
create_default_layer_providers(runtime_backend_profile=...)
ββ LayerProvider[DifyRuntimeLayer] (injected with execution_bindings)
ββ LayerProvider[DifyShellLayer] (injected with redact_patterns + agent_stub settings)
ββ ... other providers
β
RunScheduler (lifespan-scoped)
Runtime Backend Selection (runtime_backend)#
DIFY_AGENT_RUNTIME_BACKEND selects one of three backends ; create_runtime_backend_profile() constructs the matching driver pair :
| Backend | Required env vars | execution_bindings type |
|---|---|---|
local (default) | DIFY_AGENT_LOCAL_SANDBOX_ENDPOINT | LocalExecutionBindingBackend |
enterprise | DIFY_AGENT_ENTERPRISE_SANDBOX_GATEWAY_ENDPOINT | EnterpriseExecutionBindingBackend |
e2b | DIFY_AGENT_E2B_API_KEY | E2BExecutionBindingBackend |
Each backend validation is enforced by RuntimeBackendSettings.validate_selected_backend() at startup ; missing required credentials raise ValueError before the server accepts traffic.
Local backend#
Connects to a local shellctl sandbox via DIFY_AGENT_LOCAL_SANDBOX_ENDPOINT (also accepted as the legacy alias DIFY_AGENT_SHELLCTL_ENTRYPOINT) . Home directories are materialized under DIFY_AGENT_LOCAL_SANDBOX_MATERIALIZED_HOME_ROOT (default /home/dify) and snapshots under DIFY_AGENT_LOCAL_SANDBOX_HOME_SNAPSHOT_ROOT (default /home/dify/.snapshots) .
Enterprise backend#
Uses an enterprise sandbox gateway at DIFY_AGENT_ENTERPRISE_SANDBOX_GATEWAY_ENDPOINT with control-plane / proxy timeout separation .
E2B backend#
Uses the E2B SDK (E2BSDKControlPlane) keyed by DIFY_AGENT_E2B_API_KEY, with configurable sandbox template and active timeout .
Shell Layer Provider Factory Pattern#
DifyShellLayer blocks direct construction β calling from_config() raises TypeError . Instead, it must be instantiated via from_config_with_settings(), which accepts three server-injected settings not present in the per-run config payload:
shell_redact_patternsβ server-level regex list for masking secrets in shell outputagent_stub_api_base_urlβ the public Agent Stub endpoint URLagent_stub_token_factoryβ a callable that mints JWE tokens for shell jobs
In compositor_factory.py, the shell layer is registered as a factory provider that closes over these settings :
LayerProvider.from_factory(
layer_type=DifyShellLayer,
create=lambda config: DifyShellLayer.from_config_with_settings(
DifyShellLayerConfig.model_validate(config),
shell_redact_patterns=shell_redact_patterns or [],
agent_stub_api_base_url=agent_stub_api_base_url,
agent_stub_token_factory=agent_stub_token_factory,
),
)
The shell layer itself does not own the sandbox connection β it reads the RuntimeLease from DifyRuntimeLayer.lease at call time . HOME is set from lease.layout.home_dir, which is controlled entirely by the runtime backend .
Key Settings Reference#
All settings are in ServerSettings under the DIFY_AGENT_ env-var prefix:
| Setting | Default | Purpose |
|---|---|---|
DIFY_AGENT_RUNTIME_BACKEND | local | Backend selector |
DIFY_AGENT_LOCAL_SANDBOX_ENDPOINT | None | Shellctl server URL (local backend) |
DIFY_AGENT_ENTERPRISE_SANDBOX_GATEWAY_ENDPOINT | None | Gateway URL (enterprise backend) |
DIFY_AGENT_E2B_API_KEY | None | API key (e2b backend) |
DIFY_AGENT_SHELL_REDACT_PATTERNS | "" | JSON array of regex patterns for output redaction |
DIFY_AGENT_STUB_API_BASE_URL | None | Agent Stub endpoint (required for Agent Stub JWE) |
DIFY_AGENT_SANDBOX_FILES_BASE_URL | http://host.docker.internal:5001 | Base URL for file transfers accessible from the sandbox container; uses host.docker.internal for Docker environments to allow the sandbox to reach the API server |
DIFY_AGENT_STUB_UPLOAD_FILE_SIZE_LIMIT | 50 | Agent service-owned maximum Agent Stub upload size in MiB. The file-request handler factory converts it to bytes and sends it to Dify API as the required max_size used to sign a size-limited upload URL |
DIFY_AGENT_INNER_API_URL | http://127.0.0.1:5001 | Inner API URL for host-side control-plane calls on loopback; separate from DIFY_AGENT_SANDBOX_FILES_BASE_URL which is used for sandbox container file access |
DIFY_AGENT_SERVER_SECRET_KEY | None | 32-byte base64url key; required when Stub URL is set |
Key Entry Points#
| File | Purpose |
|---|---|
server/app.py | create_app() β top-level wiring |
server/settings.py | ServerSettings, build_runtime_backend_profile() |
runtime/compositor_factory.py | create_default_layer_providers() β provider factory set |
runtime_backend/profile.py | RuntimeBackendSettings, create_runtime_backend_profile() |
layers/shell/layer.py | DifyShellLayer.from_config_with_settings() β enforced factory pattern |