# New Agent portable DSL reference ## Contents 1. Source-of-truth files 2. Support matrix 3. Standalone Agent package 4. Workflow Agent V2 package 5. Import semantics 6. Post-import checklist 7. Validation and testing 8. Build Draft and generator boundaries ## 1. Source-of-truth files Confirm these paths in the exact target Dify checkout. Names may move in later releases. | Concern | Current source path | |---|---| | App DSL version | `api/constants/dsl_version.py` | | Agent package DTO and secret stripping | `api/services/agent/dsl_entities.py` | | Agent package export/import | `api/services/agent/dsl_service.py` | | App and Workflow DSL integration | `api/services/app_dsl_service.py` | | Agent V2 discriminator | `api/core/workflow/nodes/agent_v2/discriminator.py` | | Agent V2 publish validation | `api/core/workflow/nodes/agent_v2/validators.py` | | Agent Soul and Workflow job schemas | `api/models/agent_config_entities.py` | | Agent Composer endpoints | `api/controllers/console/agent/composer.py` | | Agent publish/API endpoints | `api/controllers/console/agent/roster.py` | At the inspected current-main snapshot, the app DSL version is `0.7.0` and portable Agent package schema version is `1`. Always re-read the target checkout rather than copying these values blindly. ## 2. Support matrix ### Legacy Agent A legacy Agent node may also use `type: agent`, but it does not have both: ```yaml version: '2' agent_node_kind: dify_agent ``` Never convert a legacy node by changing only those two fields. Agent V2 stores the reusable configuration in an Agent Soul Snapshot and stores Workflow-specific instructions in a separate node binding. ### Agent V2 without portable package support If the target has Agent V2 nodes but lacks `api/services/agent/dsl_service.py`, create/configure/publish the Agent through the target Composer API or UI, then bind it to the Workflow. Use a same-version fresh export as the artifact. Do not generate `agent_packages` for a runtime that does not implement them. ### Portable Agent DSL Portable DSL is supported only when App DSL import/export processes top-level `agent_packages`. It supports: - standalone `app.mode: agent` packages; - Workflow/advanced-chat Agent V2 nodes backed by packages; - dependency analysis for models, Tools, and Knowledge models; - import warnings for resources that need target-workspace setup. ## 3. Standalone Agent package Minimal structural example. Replace model/provider values with identifiers verified in the target workspace. ```yaml version: 0.7.0 kind: app app: name: Portable Research Agent mode: agent icon: "🤖" icon_background: '#FFEAD5' description: Demo-safe reusable research Agent. use_icon_as_answer_icon: false agent: package_ref: agent_1 agent_packages: agent_1: schema_version: 1 metadata: name: Portable Research Agent description: Demo-safe reusable research Agent. role: Researcher icon_type: emoji icon: "🤖" icon_background: '#FFEAD5' soul: schema_version: 1 prompt: system_prompt: >- Review the request, use configured read-only evidence sources, and return a concise recommendation with citations and uncertainty. tools: dify_tools: [] cli_tools: [] knowledge: sets: [] human: contacts: [] tools: [] env: variables: [] secret_refs: [] config_skills: [] config_files: [] config_note: Imported portable draft; configure and publish before use. sandbox: provider: null config: {} memory: scope: null budget: null artifacts: [] model: plugin_id: VERIFIED_MODEL_PLUGIN_ID model_provider: VERIFIED_MODEL_PROVIDER model: VERIFIED_MODEL_NAME credential_ref: null model_settings: temperature: 0.2 app_features: file_upload: enabled: true app_variables: [] misc_legacy: {} omitted_assets: [] dependencies: [] ``` Import creates a new Agent app and an editable unpublished draft. Current import rejects using Agent DSL to overwrite an existing Agent app. ## 4. Workflow Agent V2 package The Workflow retains its ordinary `workflow.graph`. Add a top-level package and use this node-data shape: ```yaml workflow: graph: nodes: - id: agent-review type: custom position: {x: 500, y: 200} positionAbsolute: {x: 500, y: 200} sourcePosition: right targetPosition: left data: type: agent version: '2' agent_node_kind: dify_agent title: Review with New Agent desc: Review live Workflow context with a portable Inline Agent. selected: false agent_binding: binding_type: inline_agent package_ref: agent_1 agent_job: schema_version: 1 mode: tell_agent_what_to_do workflow_prompt: >- Review the upstream request and return the declared fields only. previous_node_output_refs: - selector: [start-node, request] declared_outputs: - name: recommendation type: string description: Concise recommendation for downstream nodes. required: true failure_strategy: retry: enabled: false max_retries: 0 retry_interval_ms: 0 on_failure: stop default_value: null human_contacts: [] metadata: {} agent_packages: agent_1: # Same AgentPackage structure as the standalone example. ``` Important rules: - `agent_binding` in portable DSL uses `package_ref`, not persisted `agent_id` or `current_snapshot_id`. - `agent_job` is required for portable Workflow binding and is removed from graph data after import; the backend persists it in `WorkflowAgentNodeBinding`. - All package-backed Workflow imports materialize node-owned Inline Agents. A source Roster binding is not preserved as a cross-workspace reusable Roster relationship. - To reuse one Roster Agent across Workflows, import/publish the standalone Agent and bind it in the target workspace after import. - `previous_node_output_refs` must point to real upstream nodes. - If `declared_outputs` is empty, runtime defaults are `text`, `files`, and `json`; declare explicit outputs when downstream nodes require a stable contract. - Declared output names must match `^[A-Za-z_][A-Za-z0-9_]*$`. - Do not place Prompt, Skills, Files, Tools, Knowledge, model, memory, or sandbox overrides in Workflow job metadata. - `AgentPackage`, Agent Soul, and `agent_job` use strict schemas. Remove legacy fields such as `workspace_skills` and `agent_strategy_*`; do not copy graph-projected `agent_task` or `agent_declared_outputs` into the portable package/job contract. ## 5. Import semantics Portable export deliberately strips workspace-sensitive values. ### Model - `credential_ref` is removed. - The model provider plugin and selected model identifiers remain dependencies. - Import does not prove the target workspace has an authorized model credential. ### Dify Tools - credentials and secret-like runtime parameters are removed; - exported Tools become `credential_type: unauthorized` with no `credential_ref`; - provider/tool identity remains for dependency analysis; - reconnect credentials and run a minimum tool test after import. ### Skills and Files - binary/file payloads are not embedded in YAML; - exported `config_skills` and `config_files` receive `file_id: ''` and `is_missing: true`; - `omitted_assets` preserves names, sizes, hashes, and MIME hints; - re-upload/recreate the Skill archive and File, then replace missing references; - insert structured Skill/File Prompt mentions when their contents must be eagerly loaded every run. Do not claim that a successful YAML import carried Skill or File content. ### Knowledge - package DSL retains dataset IDs and names; - import preserves datasets found in the target tenant; - missing datasets are replaced with unresolved portable IDs and warnings; - recreate/remap datasets, verify indexing, and hit-test retrieval. Agent V2 uses explicit `knowledge.sets`. Each set contains: - unique `id` and case-insensitive unique `name`; - one or more datasets; - `query.mode`: `user_query` or `generated_query`; - retrieval mode/settings; - metadata filtering: `disabled`, `automatic`, or `manual`. ### Human contacts and secrets - workspace/contact IDs and tenant IDs are removed; - secret references retain only non-secret metadata; - import warnings identify unresolved contacts and secrets; - resolve them in the target workspace before publish. ## 6. Post-import checklist Do these in order: 1. Save the complete import response and inspect `status`, `app_mode`, and `warnings`. 2. Confirm all declared plugin dependencies are installed. 3. Select and authorize the Agent model. 4. Reconnect every Tool credential and verify a minimal read-only call. 5. Reattach each omitted Skill and File; confirm hashes/names when available. 6. Remap Knowledge datasets and verify expected retrieval hits. 7. Resolve contacts, environment variables, and secret references. 8. Validate Agent Composer configuration. 9. Apply any Build draft; Build output alone is not active configuration. 10. Publish the Agent. 11. If using a Roster Agent, bind the intended published Agent in the Workflow Composer and republish the Workflow. 12. Confirm the runtime trace reports the intended Agent and Snapshot. ## 7. Validation and testing Static validation: ```bash python3 "$SKILL_DIR/scripts/validate_new_agent_dsl.py" app.yml \ --target-repo /path/to/dify \ --out validation/new-agent.json ``` Import: ```bash python3 "$SKILL_DIR/scripts/dify_ce_console.py" import app.yml \ --confirm-pending \ --out import-result.json ``` Published Agent Service API: ```bash python3 "$SKILL_DIR/scripts/dify_ce_console.py" service-chat-run \ --api-key-env DIFY_AGENT_API_KEY \ --query "Review this demo request." \ --inputs-json '{}' \ --out agent-service-run.json ``` Workflow Agent V2 acceptance must prove: - the Agent is published or the imported Inline Agent is valid; - the binding references the intended current Snapshot; - upstream values reach the Agent job; - Skills/Files/Knowledge/Tools actually participate when claimed; - declared outputs pass type validation; - downstream nodes use the expected output; - published behavior matches the tested draft/current version. ## 8. Build Draft and generator boundaries ### Build Draft is temporary editor state New Agent Build Mode writes an editor-scoped Build Draft. It is not the ordinary Agent Draft and is not exported as App DSL. The reliable lifecycle is: 1. checkout/save the Build Draft; 2. review generated Prompt, Skill, File, and other changes; 3. Apply the Build Draft to the ordinary Draft; 4. validate the ordinary Draft; 5. publish the Agent to create an immutable Snapshot; 6. bind or refresh the Workflow Agent node; 7. publish and runtime-test the Workflow. The current Console surfaces are rooted at: ```text POST /console/api/agent PUT /console/api/agent/{agent_id}/composer POST /console/api/agent/{agent_id}/composer/validate POST /console/api/agent/{agent_id}/publish PUT /console/api/apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer ``` Build Draft checkout/save/apply endpoints live beside the Agent roster endpoints and must be re-read from the target checkout before automation because that surface is newer and may change independently from App DSL. ### The current graph generator is not an Agent-package generator At the inspected current-main snapshot, the Workflow generator planner has no first-class Agent V2 node contract, its snippets do not own the V2 package schema, and the generated result is a graph rather than a complete App DSL envelope. Adding one `agent` node snippet is insufficient because New Agent portability also needs top-level `agent_packages` and import materialization. Use one of two paths: - **External portable YAML:** generate the whole App DSL, package, V2 node, and job; validate; import; reconcile assets and credentials. - **Studio materialization:** generate/save a V2 node shell, then use Agent Composer to create the Inline Agent, Snapshot, and `WorkflowAgentNodeBinding`; read back the projected graph before publish. Do not place `package_ref` in a normal graph-only save and assume it will materialize. Package materialization is an App DSL import behavior.