Workflow Agent Node Configuration#
A Workflow Agent Node (type agent, version 2) embeds an Agent V2 execution unit inside a Dify workflow graph. Its configuration is split across two persisted objects:
- Agent Soul (
AgentSoulConfig) — the agent's identity: model, prompt, tools, knowledge, environment, and sandbox. Stored as a JSON snapshot inAgentConfigSnapshot.config_snapshot. - Node Job (
WorkflowNodeJobConfig) — workflow-specific wiring: declared outputs, previous-node output refs, human contacts, and task prompt. Stored inWorkflowAgentNodeBinding.node_job_config.
This separation means the same Agent Soul can be reused across multiple workflow nodes (Roster agents), while each node carries its own workflow wiring independently.
Key source files:
| File | Role |
|---|---|
api/core/workflow/nodes/agent_v2/validators.py | WorkflowAgentNodeValidator — draft and publish validation |
api/core/workflow/nodes/agent_v2/dify_tools_builder.py | WorkflowAgentDifyToolsBuilder — tool layer construction |
api/core/workflow/nodes/agent_v2/runtime_request_builder.py | WorkflowAgentRuntimeRequestBuilder — assembles CreateRunRequest at runtime |
api/models/agent_config_entities.py | All config DTOs (AgentSoulConfig, WorkflowNodeJobConfig, AgentSoulDifyToolConfig, etc.) |
Validation: Draft vs. Publish#
WorkflowAgentNodeValidator has two entry points with different strictness levels:
validate_draft_workflow— iterates all Agent v2 nodes in the graph, validates the node schema viaDifyAgentNodeData.model_validate, and checks any existing binding. A missing binding is silently skipped (the node is unconfigured but not yet in error).validate_published_workflow— same checks, but a missing binding is a hard error. It also validates graph topology (upstream relationships for previous-node output refs).
Agent v2 nodes are identified by node_data.type == BuiltinNodeTypes.AGENT and node_data.version == "2".
Binding Validation#
validate_binding runs these checks in order:
- Agent existence — the bound
Agentrow must exist, be in the correct scope (ROSTER vs. inline), and not be archived. - Snapshot existence — the active
AgentConfigSnapshotmust exist for the resolved snapshot ID. - Model presence —
AgentSoulConfig.modelmust not beNone. RaisesWorkflowAgentNodeValidationErrorif missing. - Environment variables — agent-level and CLI tool env names must be unique and all secret refs must have an authorized permission status.
- Tools — enabled Dify tool names must be unique; enabled CLI tools must be pre-authorized, have no denied permissions, and acknowledge dangerous commands.
- Knowledge datasets — all referenced dataset IDs must exist within the tenant.
Node Job Validation#
validate_node_job checks:
- Locked soul fields — the
node_job.metadatamust not contain any key from_LOCKED_AGENT_SOUL_KEYS(e.g.,agent_soul,tools,model). This prevents the node job from overriding soul-owned configuration. - Duplicate output names — declared outputs must have unique names.
- File refs — benchmark file refs on output checks must be resolvable
UploadFilerows within the same tenant. - Previous-node output refs — each ref must resolve to a valid
[node_id, output_name]selector, and at publish time, the source node must exist upstream of the agent node in graph topology. - Human contact refs — each human contact must have a valid
contact_idand an allowedchannel.
Tool Node Agentic Mode (Publish-time)#
At publish time, the validator also checks all Tool nodes in the graph. If a tool node has an agentic_mode config, it must be complete, authorized, and either in a manual state or have an inferred parameter draft.
Runtime: Tool Layer Construction#
When a run starts, WorkflowAgentDifyToolsBuilder.build_layers translates the AgentSoulToolsConfig into two Agent backend layer configs:
DifyPluginToolsLayerConfig— forPLUGINprovider types (routed to Plugin Daemon)DifyCoreToolsLayerConfig— forBUILT_IN,API,WORKFLOW, andMCPproviders (routed to internal API atPOST /inner/api/agent/tools/invoke)
The builder follows these steps per tool:
-
Provider expansion — if
tool_nameisNone(provider-level entry = "all tools"),_expand_provider_entriesqueries the provider for its declared tool names (viaToolManager,WorkflowToolProviderController, orMCPToolManageService) and emits one entry per tool. Already-explicit tool names are skipped to avoid duplication. -
MCP normalization — MCP provider IDs are resolved to their runtime server identifiers via
_resolve_mcp_provider_id. -
Tool runtime fetch —
_fetch_tool_runtimecallsToolManager.get_agent_tool_runtime. Errors map to stableWorkflowAgentDifyToolsBuildErrorcodes:agent_tool_declaration_not_found— provider or tool not foundagent_tool_credential_invalid— credential validation failedagent_tool_config_invalid— otherValueErrorduring runtime construction
-
Required parameter check —
_runtime_parameterschecks that every non-LLM, required parameter with no default has a value inruntime_parameters. Missing ones raiseagent_tool_runtime_parameter_missing.Note: This is the source of the
"tool parameter {name} not found in tool config"error seen in issue #15468. The lower-levelinit_frontend_parameterinparameters.pyraises aValueErrorwhen a required parameter (e.g.,instruction) has no value and no default. This propagates up through the tool initialization chain. -
Plugin JSON schema augmentation —
_plugin_parameters_json_schemapatchesFILEandFILES-typed LLM parameters into the schema using aanyOfshape that accepts URL strings or{transfer_method, url/reference}objects. -
Credential normalization — only scalar values (
str,int,float,bool,None) are forwarded to the Plugin Daemon; non-scalar credential values raiseagent_tool_credential_shape_invalid.
Runtime: Request Assembly#
WorkflowAgentRuntimeRequestBuilder.build assembles the final CreateRunRequest sent to the Agent backend:
- Validates the soul model config is present (raises
agent_model_not_configuredif not). - Calls
build_layersto produce tool layer configs; mapsWorkflowAgentDifyToolsBuildErrortoWorkflowAgentRuntimeRequestBuildError. - Builds prompts:
- Soul prompt — from
agent_soul.prompt.system_promptwith prompt-mention resolution (skills, files). - Workflow task prompt — from
node_job.workflow_promptwith mention resolution. Staleprevious_node_output_refsnot referenced in the current prompt are discarded. - Workflow context prompt — assembles
sys.query,sys.files, and resolved previous-node output values.
- Soul prompt — from
- Builds structured output schema from
node_job.declared_outputs— if no outputs are declared, PRD-mandated defaults (text,files,json) are injected at runtime (not persisted). - Builds knowledge, shell, ask-human, and execution-context layer configs from agent soul fields.
- Assigns an idempotency key scoped to
(workflow_run_id, node_execution_id, attempt)so retries get distinct keys.
Stale Tool Parameters#
When a tool is removed from the Agent Soul config, its saved runtime_parameters entries in AgentSoulDifyToolConfig are simply absent from the enabled tool list. build_layers only processes tools where tool.enabled == True, so orphaned parameter entries for removed tools are implicitly dropped — they are never forwarded to the Agent backend.
However, if a tool is re-added with changed parameter definitions, any previously stored runtime_parameters that no longer match declared parameters will surface as agent_tool_runtime_parameter_missing errors at runtime if a now-required parameter is absent. The fix is to update the tool's stored runtime_parameters in the Agent Soul config via the Composer UI.