Skip to content

feat: support direct import of Claude workflows#33508

Closed
xi-zhao wants to merge 5 commits intolanggenius:mainfrom
xi-zhao:codex/claude-workflow-direct-import
Closed

feat: support direct import of Claude workflows#33508
xi-zhao wants to merge 5 commits intolanggenius:mainfrom
xi-zhao:codex/claude-workflow-direct-import

Conversation

@xi-zhao
Copy link
Copy Markdown

@xi-zhao xi-zhao commented Mar 16, 2026

Summary

  • add a constrained Claude workflow schema, compiler, and import service so /apps/imports can accept kind: claude-workflow YAML and compile it into native Dify workflow DSL
  • add backend fixtures and tests covering schema validation, DSL compilation, import service behavior, and the app import API path
  • update the web DSL import flow to upload Claude workflow files directly and surface backend validation/compiler errors in the existing import UI

Test Plan

  • uv run --project api pytest api/tests/unit_tests/services/claude_workflow/test_schema.py api/tests/unit_tests/services/claude_workflow/test_compiler.py api/tests/unit_tests/services/claude_workflow/test_import_service.py api/tests/unit_tests/controllers/console/app/test_claude_workflow_import_api.py -q --override-ini addopts=''
  • pnpm test hooks/use-import-dsl.spec.tsx app/components/app/create-from-dsl-modal/index.spec.tsx
  • pnpm lint hooks/use-import-dsl.ts service/apps.ts app/components/app/create-from-dsl-modal/index.tsx app/components/app/create-from-dsl-modal/index.spec.tsx hooks/use-import-dsl.spec.tsx

@dosubot dosubot Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Mar 16, 2026
@github-actions github-actions Bot added the web This relates to changes on the web. label Mar 16, 2026
@dosubot dosubot Bot added the 💪 enhancement New feature or request label Mar 16, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Dify platform by enabling direct import of Claude workflows. It introduces a new backend pipeline that validates Claude workflow YAML against a defined schema, compiles it into Dify's native DSL, and then processes the import. This streamlines the process for users who wish to migrate or utilize workflows designed in the Claude format, providing a more integrated and user-friendly experience for workflow management.

Highlights

  • Claude Workflow Import: Introduced a new backend service to directly import Claude workflow YAML files, which are then validated, compiled into Dify's native workflow DSL, and imported.
  • Schema Validation and Compilation: Implemented a constrained Claude workflow schema using Pydantic for validation and a dedicated compiler to transform Claude workflow structures into Dify's internal DSL format.
  • Robust Error Handling: Added specific error types for schema validation and compilation failures, ensuring that the frontend can display precise, machine-readable error messages to users.
  • Frontend Integration: Updated the web application's DSL import flow to support uploading Claude workflow files and to surface detailed backend validation and compilation errors in the existing import UI.
  • Comprehensive Testing: Included extensive backend unit tests for the new schema, compiler, import service, and API endpoint, as well as frontend tests for the updated import UI.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .gitignore
    • Added '.worktrees/' to the ignore list.
  • api/controllers/console/app/app_import.py
    • Imported new Claude workflow-related services and error types.
    • Modified the post method to use ClaudeWorkflowImportService for handling workflow imports.
    • Implemented error handling for ClaudeWorkflowImportExecutionError to return specific payloads and status codes.
  • api/services/claude_workflow/init.py
    • Added a new Python package initialization file, exposing Claude workflow errors, compiler, and schema components.
  • api/services/claude_workflow/compiler.py
    • Added a new module responsible for compiling validated Claude workflow documents into Dify app DSL YAML.
    • Implemented functions to build Dify graph nodes (start, LLM, if-else, HTTP request, code, end) and edges from Claude workflow structures.
  • api/services/claude_workflow/errors.py
    • Added a new module defining custom error types, including ClaudeWorkflowSchemaErrorCode, ClaudeWorkflowValidationIssue, ClaudeWorkflowSchemaValidationError, and ClaudeWorkflowCompilerError, for structured error reporting.
  • api/services/claude_workflow/import_service.py
    • Added a new service to orchestrate the import of Claude workflow files, including detection, validation, compilation, and delegation to the existing AppDslService.
    • Introduced ClaudeWorkflowImportExecutionError for controller-facing import failures with prebuilt payloads and status codes.
  • api/services/claude_workflow/schema.py
    • Added a new module defining Pydantic models for the Claude workflow document structure, including app metadata, inputs, various node types (LLM, End, IfElse, HttpRequest, Code), and edges.
    • Implemented validation logic for the schema, including cross-node reference checks.
  • api/tests/fixtures/claude_workflow/basic_llm.yml
    • Added a YAML fixture for a basic LLM Claude workflow for testing purposes.
  • api/tests/fixtures/claude_workflow/branching.yml
    • Added a YAML fixture for a branching Claude workflow for testing purposes.
  • api/tests/fixtures/claude_workflow/http_request.yml
    • Added a YAML fixture for an HTTP request and code node Claude workflow for testing purposes.
  • api/tests/fixtures/claude_workflow/invalid_missing_edge_target.yml
    • Added a YAML fixture for an invalid Claude workflow with a missing edge target to test error handling.
  • api/tests/unit_tests/controllers/console/app/test_claude_workflow_import_api.py
    • Added new unit tests for the app_import API endpoint, covering successful Claude workflow imports and mapping schema/compiler failures to appropriate HTTP status codes.
  • api/tests/unit_tests/services/claude_workflow/test_compiler.py
    • Added new unit tests for the Claude workflow compiler, verifying correct transformation of various Claude workflow types into Dify DSL.
  • api/tests/unit_tests/services/claude_workflow/test_import_service.py
    • Added new unit tests for the Claude workflow import service, covering successful compilation and delegation, and proper handling of schema and compiler errors.
  • api/tests/unit_tests/services/claude_workflow/test_schema.py
    • Added new unit tests for the Claude workflow schema validation, ensuring valid documents are parsed and invalid ones are rejected with specific error codes.
  • web/app/components/app/create-from-dsl-modal/index.spec.tsx
    • Added new frontend tests for CreateFromDSLModal, specifically for handling Claude workflow file uploads and displaying backend validation/compiler errors.
  • web/app/components/app/create-from-dsl-modal/index.tsx
    • Removed unused RiCloseLine import.
    • Updated the useEffect hook to properly handle dropped files for DSL import.
    • Modified importDSL calls to include silent: true option.
    • Enhanced error handling to display specific backend error messages for import failures using getImportDSLFailureMessage.
  • web/eslint-suppressions.json
    • Updated ESLint suppression count for react-hooks-extra/no-direct-set-state-in-use-effect in create-from-dsl-modal/index.tsx.
  • web/hooks/use-import-dsl.spec.tsx
    • Added new frontend tests for the useImportDSL hook, verifying correct forwarding of YAML content and display of backend validation errors.
  • web/hooks/use-import-dsl.ts
    • Modified importDSL calls to include silent: true option.
    • Enhanced error handling to display specific backend error messages for import failures using getImportDSLFailureMessage.
  • web/service/apps.ts
    • Added getImportDSLFailureMessage function to extract detailed error messages from API responses for specific HTTP status codes (400, 422).
    • Modified the importDSL function to accept an optional silent parameter for controlling error notifications.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for importing Claude workflows by compiling them into the native Dify DSL. The implementation includes a new schema, a compiler, and an import service, along with updates to the API and frontend to handle the new import path and its specific error conditions. The code is well-structured and thoroughly tested. I have a few suggestions to enhance error handling and code clarity, particularly around database transaction management, exception specificity, and schema validation to prevent unhandled server errors.

Comment on lines +264 to +272
for index, edge in enumerate(document.edges):
if edge.target not in node_ids:
issues.append(
ClaudeWorkflowValidationIssue(
code=ClaudeWorkflowSchemaErrorCode.UNKNOWN_EDGE_TARGET,
path=("edges", index, "target"),
message=f"Unknown edge target: {edge.target}",
)
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The cross-reference validation correctly checks edge.target, but it misses validation for edge.source. An invalid edge.source (one that is not 'start' or a valid node ID) will cause the compiler to fail with an unhandled StopIteration, leading to a 500 Internal Server Error. You should add validation for edge.source to ensure a clean 400 Bad Request is returned for invalid workflows. You might also consider adding a new UNKNOWN_EDGE_SOURCE error code for more precise error reporting.

    for index, edge in enumerate(document.edges):
        if edge.source not in valid_sources:
            issues.append(
                ClaudeWorkflowValidationIssue(
                    code=ClaudeWorkflowSchemaErrorCode.UNKNOWN_EDGE_TARGET,
                    path=("edges", index, "source"),
                    message=f"Unknown edge source: {edge.source}",
                )
            )
        if edge.target not in node_ids:
            issues.append(
                ClaudeWorkflowValidationIssue(
                    code=ClaudeWorkflowSchemaErrorCode.UNKNOWN_EDGE_TARGET,
                    path=("edges", index, "target"),
                    message=f"Unknown edge target: {edge.target}",
                )
            )

app_id=args.app_id,
)
except ClaudeWorkflowImportExecutionError as exc:
session.commit()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This session.commit() call within the except block is unnecessary and potentially misleading. Since the ClaudeWorkflowImportExecutionError is raised before any database modifications are made within the import service, there is nothing to commit. The with Session(...) context manager will correctly handle the transaction. Removing this line will make the code clearer and avoid potential issues if the service logic changes in the future.

response = ssrf_proxy.get(yaml_url.strip(), follow_redirects=True, timeout=(10, 10))
response.raise_for_status()
content = response.content.decode()
except Exception:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Catching a bare Exception is generally discouraged as it can hide unexpected errors and even catch system-level exceptions like KeyboardInterrupt. It would be safer to catch more specific exceptions related to the HTTP request (e.g., from the ssrf_proxy library). If a broad exception is necessary, consider capturing and logging it (e.g., except Exception as e:) to aid in debugging.

@crazywoola crazywoola closed this Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💪 enhancement New feature or request size:XXL This PR changes 1000+ lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants