`extract_dependencies_from_workflow_graph` produces malformed plugin ids for non-langgenius tools
- 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
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