langgenius / langgenius/dify

`extract_dependencies_from_workflow_graph` produces malformed plugin ids for non-langgenius tools

Open Beginner friendly
#38,406 1 comment 1 reaction 0 assignees View on GitHub
🐞 bug project#dify
Dominant language
TypeScript
Stars
156k
Forks
24.6k
Avg merge
22h 9m
Merged PRs (30d)
610

Description

### Self Checks

- [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
- [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
- [x] I confirm that I am using English to submit this report, otherwise it will be closed.
- [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
- [x] Please do not modify this template :) and fill in all the required fields.

### Dify version

main branch (uncommitted)

### Cloud or Self Hosted

Self Hosted (Source)

### Steps to reproduce

Discovered by peaks-loop code-sweep on 2026-07-02.

1. Open any app workflow DSL that contains a TOOL node using a third-party plugin (e.g. `provider="google"`, `provider_type="langgenius"`) and an AGENT node using `provider="openai"`.
2. Trigger the snippet DSL export path (`api/services/snippet_dsl_service.py:_extract_dependencies_from_workflow_graph`).
3. Inspect the returned `dependencies` list — it contains `["google/google", "openai/openai"]` instead of the documented `["langgenius/google", "langgenius/openai"]`.

The bug surfaces as malformed plugin ids (`google/google`) where the two halves of the f-string are the same variable. Downstream `check_dependencies` silently dropped these ids because they never matched any real plugin, so the bug was invisible until the dependency checker started surfacing real missing-plugin warnings.

### ✔️ Expected Behavior

Tool/agent dependency ids must follow the documented `(organization)/(plugin_name)` format:
- For non-langgenius tools: `organization == provider_type`, `plugin_name == provider_name`.
- For langgenius tools: `organization == provider_type == "langgenius"`, `plugin_name == provider_name`.

This must match the format produced by the sibling helper `analyze_tool_dependency()` in `services/plugin/dependencies_analysis.py` (which uses `ToolProviderID(tool_id).plugin_id == "(organization)/(plugin_name)"`) so `check_dependencies` correctly detects missing plugins.

### ❌ Actual Behavior

In `api/services/snippet_dsl_service.py:577` and `:585`, the tool and agent branches of `_extract_dependencies_from_workflow_graph()` both build the dependency id with:

```python
dependencies.append(f"{provider_name}/{provider_name}")
```

That produces ids like `google/google` (the two halves of the f-string are the same variable) which never match a real plugin id. The docstring two lines above explicitly states the expected format is `['langgenius/google']`.

Introduced during the early Snippet DSL implementation; never fixed because the buggy ids were silently dropped downstream (`check_dependencies` would just report no leaked deps for the typo output, instead of detecting the actual missing plugin).

**Proposed change:** Switch both f-strings from `f"{provider_name}/{provider_name}"` to `f"{provider_type}/{provider_name}"`, which matches the docstring and `analyze_tool_dependency()`'s output. Add a regression test asserting:
- A graph with a TOOL node using `provider="google"` and an AGENT node using `provider="openai"` (both `provider_type="langgenius"`) now extracts `['langgenius/google', 'langgenius/openai']`.
- A TOOL node with only `provider_type` set (no `provider`) is correctly skipped instead of being appended as a malformed id.

**Risk:** Only the string format of appended dependency ids is corrected. The function still returns `list[str]` and is still called by the same two call sites (`_extract_dependencies_from_workflow` at lines 393 and 534). The buggy output (`google/google`) was always a no-op downstream — the corrected output may now surface legitimate missing-plugin warnings, which is the intended new behavior. No schema, migration, controller, or frontend changes.

Contributor guide

Open the contributing guide

Research direction

Start in api/services/snippet_dsl_service.py at _extract_dependencies_from_workflow_graph(), especially the TOOL and AGENT branches around lines 577 and 585. Read the docstring and compare the output with analyze_tool_dependency() in services/plugin/dependencies_analysis.py, then add the proposed regression coverage for third-party and missing-provider cases. Done means dependency ids match the documented organization/plugin format and incomplete providers are skipped.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.