--- name: dify-docs-feature-research description: "Research a Dify feature before writing or optimizing documentation. Use when starting any doc task that requires understanding a feature's implementation, user pain points, or community feedback. Triggers: 'research this feature', 'investigate the code for', 'what do users say about', 'let's understand how X works before writing', or any documentation task where the current docs are being rewritten or significantly expanded." --- # Dify Feature Research Pre-writing research that combines codebase analysis with community feedback to ensure documentation is grounded in both technical reality and actual user needs. ## Depths When invoked from the `dify-docs-write` pipeline, its S1 supplies the feature, ref, and target pages — consume them instead of re-asking (Before Starting 1–3), and run at the depth the caller sets: - **full**: everything below. - **targeted**: Phase 1 scoped to the surfaces the caller names — the coverage gate still applies, with out-of-scope surfaces recorded as `N/A` plus why; Phase 2 runs when the caller requires it; otherwise skip it and say so in the summary. Standalone use (no caller): run Before Starting 1–3 and full depth. ## Before Starting 1. Ask the user which feature, node, or area to research. 2. Confirm which dify ref to investigate (default: `main`). For graphon, the default is the version dify pins (step 6), never graphon `main`. 3. Check if the user has a specific doc page in mind for the rewrite. 4. Locate the repos: use the dify and graphon working directories configured for this session (`langgenius/dify` and `langgenius/graphon` on GitHub). If either is absent, ask the user for its path. 5. Sync and read code at the target ref by following "Syncing the Dify codebase safely" in `writing-guides/index.md`. 6. Resolve the graphon pin. dify pins graphon to an exact version; verify graphon behavior at that tag. From the dify repo root: ```bash grep '"graphon' api/pyproject.toml # e.g. "graphon==0.6.0" → read graphon at tag v0.6.0, not main ``` Behavior read from graphon `main` may not exist in the version users run. Ask the user before researching graphon `main` (appropriate only when documenting something they know is about to ship). ## Research Process Run Phase 1 and Phase 2 in parallel: dispatch one subagent per phase. If subagents are unavailable, run Phase 1 first, then Phase 2. ### Phase 1: Codebase Investigation 1. Decide which repo owns the backend implementation. Node ownership (which workflow nodes live in dify vs graphon) is maintained in one place: `.claude/skills/dify-docs-feature-research/references/detection-tables.md`. Read that file to route the feature; do not route from memory. - Human Input is split across both repos: graphon executes the node (`src/graphon/nodes/human_input/`), while dify owns the boundary, callback, and session-binding code (`api/core/workflow/nodes/human_input/`). Research both halves. 2. Locate the code: | Layer | Repo | Path | |:------|:-----|:-----| | Workflow node backend | per ownership table (step 1) | graphon: `src/graphon/nodes//` or dify: `api/core/workflow/nodes//` | | Graph engine, runtime state, variable pool, command channels, layers | graphon | `src/graphon/graph_engine/`, `src/graphon/runtime/` | | Model runtime, model providers, LLM/embedding/rerank invocation | graphon | `src/graphon/model_runtime/` | | Workflow orchestration in Flask routes and Celery tasks | dify | `api/controllers/`, `api/tasks/`, `api/services/` | | RAG and knowledge retrieval logic | dify | `api/core/rag/` | | Tool plugins | dify | `api/core/tools/` | | Frontend UI (all features; the web app was never split out) | dify | nodes: `web/app/components/workflow/nodes//` (kebab-case); other features: `web/app/components//` | | UI labels / i18n strings | dify | `web/i18n/{en-US,zh-Hans,ja-JP}/` | | Feature flags + env defaults | dify | backend `api/configs/`; frontend `NEXT_PUBLIC_*`; shipped defaults `docker/.env.example`, `docker/envs/**` | 3. Read the backend implementation: - The main node class (execution logic, `_run()` method) - Entity definitions (data models, enums, supported types) - Any template or streaming logic 4. Read the frontend UI: - Panel component (what configuration options users see) - Type definitions (data shape) - Default values and validation rules - **Permission-gated behavior (RBAC/ACL):** the effective gate is here — read the capability map (`web/utils/permission.ts`: `getAppACLCapabilities` / `getDatasetACLCapabilities`) and the UI that consumes it (e.g. a `canEdit` → read-only hook), and confirm it in a test environment. A backend `@rbac_permission_required` decorator can be looser than the frontend and never fire, so treat it as a lower bound. Permission labels for docs: `web/i18n/{en-US,zh-Hans,ja-JP}/permission-keys.json`. 5. Trace the API surface: how the feature's output reaches the API response. Check controllers, response converters, and serialization (all in dify). 6. **Coverage gate — account for every surface before concluding.** What users experience is the composition of backend + frontend + configuration; a conclusion read off a single surface is not a finding. A backend permission decorator can be looser than the frontend gate and never fire; a frontend option can be dead without its backend flag; a shipped default can disable the code path you just read. For each surface — backend, frontend UI, i18n labels, feature flags / env defaults, API, plugin SDK (plugin-facing features only) — record the files read, or `N/A` plus why that surface cannot affect this feature. Carry the filled table into the Phase 3 summary. 7. Produce a summary of: - What the feature does (based on code, not existing docs) - What configuration options exist - What data types / values are supported - How results are returned to the user (UI, API, streaming) - Any notable edge cases or limitations visible in the code 8. Flag inferred behavior per the rule in [Important](#important). ### Phase 2: Community Feedback Search for user-reported problems and questions across these channels: **GitHub Issues** — Run multiple searches with varied terms. Always search dify; also search graphon when the feature is a built-in workflow node, the graph engine, runtime, or model_runtime: ```bash gh issue list --repo langgenius/dify --search "" --limit 30 # e.g. "human input" gh issue list --repo langgenius/dify --search "" --limit 30 # e.g. "HITL" gh search issues " " --repo langgenius/dify --limit 20 # e.g. "human input timeout" # For built-in nodes, engine, runtime, or model_runtime, also: gh issue list --repo langgenius/graphon --search "" --limit 30 gh search issues " " --repo langgenius/graphon --limit 20 ``` End users typically file in dify even for graphon-owned behavior; graphon's tracker tends to hold engineering-side reports. Check both to avoid missing pain points. **GitHub Discussions** — Search for related discussion topics. `` is a case-insensitive regex, e.g. `"human ?input"`: ```bash gh api "repos/langgenius/dify/discussions?per_page=30" --jq '.[] | select(.title | test(""; "i"))' ``` For each relevant issue or discussion, read the body and top comments to understand: - What the user was trying to do - What went wrong or was confusing - Whether it's a bug, missing feature, or documentation gap **Categorize findings** into: | Category | Description | |:---------|:------------| | **Documentation gap** | User couldn't find information that should be documented | | **Confusion** | User misunderstood behavior the docs should clarify | | **Bug** | Product defect — note but don't document workarounds as features | | **Feature request** | Missing capability — note but don't document as existing | ### Phase 3: Synthesize Combine both phases into a structured research record. It is research output, not the drafter's brief: at S3 the pipeline writes the summary the drafter gets from this record, in the shape `dify-docs-write/references/research-summary.md` gives. ``` ## Feature: [Name] ### How It Works (from code) - [Key behaviors, configuration options, supported types] - [API response structure] - [Edge cases or limitations] - [Unverified inferences — flagged for user testing] ### Surface Coverage (from the Phase 1 coverage gate) | Surface | Files read, or N/A + why | |---------|--------------------------| | Backend | ... | | Frontend UI | ... | | i18n labels | ... | | Flags / env defaults | ... | | API | ... | | Plugin SDK | ... | ### Current Documentation - [What the existing page covers] - [What it's missing] ### Community Pain Points | Theme | Issues | Type | Doc impact | |-------|--------|------|------------| | ... | #123 | gap | Should document | ### Recommended Documentation Scope - [What to add based on gaps] - [What to clarify based on confusion] - [What to explicitly omit and why (bugs, unreleased features, UI-discoverable mechanics)] ``` Present the record to the user. STOP — do not start the writing phase until the user reviews the findings and confirms the scope. Under `dify-docs-write` with no reviewer in the session, that skill's rule applies: the record goes into the PR description and the run continues. ## Important - This skill produces research only. Do not start writing documentation until the user reviews the findings and confirms the scope; under `dify-docs-write` with no reviewer in the session, that skill's rule applies. - Research findings exist to make the page's claims accurate, not to be exhaustively included. When recommending scope, apply the style guide's "Repeating the UI" filter: UI-discoverable mechanics stay out of the page unless especially consequential. - When scope is confirmed and writing begins, return to the `dify-docs-write` pipeline — it loads the doc-type rule pack and the writing guides. This skill carries none of the writing rules. - Flag code-inferred behavior as unverified. Ask the user to test before documenting as fact. - Distinguish bugs from documentation gaps. Documenting buggy behavior as intended causes more harm than leaving a gap. - Note issue numbers for traceability. The user may want to reference them when prioritizing what to cover.