- name
- dify-docs-write
- description
- The entry point for writing or revising any documentation in this repo: user guides, deployment pages, plugin-dev pages, API specs, the env-var reference, CLI pages. Triggers: "write docs for X", "document X", "update this page", "fix/correct this doc", "rewrite/optimize X", "add a page for X".
# Writing Dify Documentation
The deliverable is a page a reader can use: accurate against the shipped product, written for the moment they arrive with, in the fewest words that stay clear. The standard is the style guide, above all its opening section, "What a Good Page Does"; the two reference pages it names calibrate register beside it. The checks catch what a reader pass can miss; passing them is a floor, not the standard.
The owner, wherever these skills ask for an approval or a decision, is the person you're working with: they approve the scope, read what you write, and decide the findings.
Each stage below names what it reads. Read at the stage, not before: the drafting turn should hold the bar and the facts, not the check procedures.
## Route
Pick the rule pack from the target path (most specific match wins). When the target repo carries an `AGENTS.md`, its repo-wide rules apply on top. A page with no pack skips every pack read below; the guides alone govern it. The pack carries what is specific to its surface. When they disagree, the guides win, over this skill too.
| Target path | Rule pack |
|---|---|
| `en/self-host/deploy/configuration/environments.mdx` | `dify-docs-env-vars` |
| `en/{cloud,self-host}/use-dify/`, `en/self-host/deploy/`, `en/develop-plugin/` | `dify-docs-guides` |
| `{en,zh,ja}/api-reference/` | `dify-docs-api-reference` |
| `en/cli/` | `dify-cli-docs` |
| `Dify-Enterprise-Docs/{lang}/{X.Y.x}/deploy/`, `…/administer/` | `ee-ops-docs` (in that repo) |
| `Dify-Enterprise-Docs/{lang}/{X.Y.x}/use/`, `…/develop/plugins/` | `dify-docs-guides` |
| `Dify-Enterprise-Docs/{lang}/{X.Y.x}/develop/api/` | `dify-docs-api-reference` |
| `Dify-Enterprise-Docs/{lang}/{X.Y.x}/develop/cli/` | `dify-cli-docs` |
| any other path | none; the writing guides govern |
Read now: `writing-guides/style-guide.md`; the pack's reader and vocabulary sections; the glossary rows for the surfaces in scope (`writing-guides/glossary.md`, by UI label, not the whole file).
## Choose how to write
At the start of a writing task, propose one of three ways to write it, with the reason, and let the owner choose; none is the default.
- **Drafter**: the research summary goes to a fresh drafter, the checks run, and the owner reviews the result. It suits content the owner already knows, such as a reference table, a rewrite of known content, an env var row, or an API spec.
- **Co-writing**: a plain-language briefing on the feature, an agreed outline, then one section at a time, each shown as full text and landed once the owner approves it. It suits a new feature or a task flow the owner doesn't know, because the briefing is where the owner learns the feature and each section is judged as it is written.
- **Drafter, then a section-by-section read**: the drafter writes the page, then the owner walks it one section at a time before the checks run. It suits a flagship page, or a draft the owner can't read through.
Work that writes little or no new prose, such as a one-line correction, a translation sync, or a carry between product lines, runs as below without a choice.
## Understand before you write (S1–S3)
Read now: `writing-guides/index.md` § "Syncing the Dify codebase safely"; the pack's procedures labeled S2 and S3; `references/task-analysis.md`; `references/research-summary.md`.
Pin the code ref first (for a pre-release feature, the development branch the user names) and verify every claim there. Existing docs are not evidence, because pages go stale, so a rewrite re-checks everything it keeps. Code presence is not a working feature either. A behavior is confirmed when it is tested, or traced in code from the input to what the user sees, including the code that reads each field involved; one inferred short of that is reported as unverified and stays off the page, and so is a claim whose source you cannot reach, marked `UNVERIFIED` in the scope report and the PR description. The depth follows what changed for the reader, not how much of the page changes, and that includes how the reader should think about the product, such as whether a new feature replaces an old one or stays beside it, even when no behavior changes. A change in how the product is positioned runs at targeted depth on the pages that frame it. A correction, where the page says something wrong (a claim, or a label the product renamed) but what the reader does is unchanged, verifies the one disputed claim and records the evidence. A changed behavior, where a task the reader already does now has different steps, prerequisites, limits, or outcome, runs `dify-docs-feature-research` at targeted depth on the surfaces the change touches. A new capability, something the reader could not do before, runs it in full even when it lands as one section of an existing page, and so do a new page, a rewrite, and a pre-release feature. Filling a gap on a page whose product hasn't changed runs at targeted depth on the surfaces the gap covers, or in full when the gap is a whole task. Targeted and full research both include what users have reported, because the reports show what the code cannot: what readers expected, misread, or tried instead. Run the pack's S2 discovery and record each result, including "no match".
In the drafter modes, write the research down, from the research skill's record, as the drafter will need it, in the shape `references/research-summary.md` shows, because the drafter mirrors the shape and vocabulary of what it is handed and the summary's frame decides what it does with a fact. The session decides what the page does not carry; the drafter decides, sentence by sentence, what the reader would ask for, and a summary trimmed to exactly the page leaves it nothing to decide.
Then work out who arrives at this page and what they are trying to do, with `references/task-analysis.md`. Tasks come from the reader's own journeys through the product, not from the issue text or the code trace. For each task, note what they need before starting, what they will wonder mid-way, what they will overlook, and how they will know it worked. What the interface shows at that moment stays out; what it cannot show goes in. A question the docs cannot answer (a UI gap, a product gap) is reported, never papered over in prose.
For a `use-dify` page, both audience copies are in scope: shared improvements land in both, audience-specific blocks stay per copy (the guides pack has the rules).
## Agree the scope (S4)
Before drafting, report the pages and what will change on each, the research summary itself, the task analysis, the unverified claims, and the questions you are routing elsewhere, then stop for approval. In co-writing, a plain-language briefing on the feature takes the summary's place, since no drafter needs one, and the outline is agreed from the task analysis. For each page, the report also states its genre (a concept page, a task page, or a reference) and how deep it goes, such as a quick reference or a full guide. The owner and the session settle it here, and every later stage holds to it. Silent scope drift is the failure this guards against, and the summary is shown so the owner can check the question each section answers and strike facts a reader would not ask for before a drafter states them. A single-page correction proceeds without the stop; in an API spec, that is a correction to one endpoint. When the scope offers a structural choice, give each option's reader impact and size before asking for a decision. A port into another tree is scoped from the feature's full footprint in the source tree (the union of its source PRs' file lists, a link sweep, and a name sweep), never from the target tree or a parked branch, and every footprint file gets an include, adapt, or exclude line.
## Write (S5)
Read now: the pack's procedures labeled S5 and the references they name (page shape, conventions, style overrides). Then, last before the first sentence: the whole style guide, whose opening section "What a Good Page Does" is the standard and whose later sections carry the rules only a drafter can apply (plan badges, the Enterprise tip, how limits are phrased, location-first instructions); `references/drafting-turn.md`; and the reference page in the page's genre, `en/cloud/use-dify/build/new-agent/overview.mdx` for a concept page or `en/cloud/use-dify/build/new-agent/build.mdx` for a task page. A reference page (a CLI command, an API group, a node) takes the task page plus the pack's page shape: the pack decides the sections, tables, and conventions of its document type, and the sample decides only how the sentences inside them sound. The two pages calibrate register; the style guide is the authority when they differ.
In the drafter modes, for a new page or a rewrite, the outline is the summary's question-headed sections in the reader's order; the owner approved it with the summary, so re-propose only what changed since. Exclusions need no defense; an inclusion that answers no question is the thing to defend.
Before handing off, propose how the drafting splits and agree it with the owner: pages that share a through-line go to one drafter as one topic, the touched sections of related pages go to one drafter by topic on a partial edit, and one drafter per page is a choice, not the default.
The session that did the research never drafts: its context is full of code vocabulary, tool output, and its own history, and the prose takes that register. Co-writing is the exception, because the owner reads each section as it is written and catches that register sentence by sentence. A co-writing session holds itself to what a drafter is given: the reader block at the top of the turn, the two planning lines per section, and the read-back in `references/drafting-turn.md`, all before the owner sees a section. It writes one page at a time.
The drafter gets the filled-in reader block at the top of its turn, the research summary, the whole style guide, `references/drafting-turn.md`, the reference page in its genre, and the pack's page-shape and drafting sections, and no research beyond that. It may open the pages this one links to and its siblings in the docs tree, to see what they carry and how they name things; the reference page still sets the register. It names the judgment each section owes its reader, writes toward that rather than toward the fact list, drafts the page whole so the sections carry a through-line, and reads it back once before returning it.
Before the editor test, read the draft against the pages it links to and its siblings for overlap and contradiction. That check is the session's, which has the doc set in view; it is not a rule in the drafter's brief.
Review the whole draft, then sort the corrections by one question: does this change what a unit is for, or only what a sentence says? A fact, a label, a link, a number, or a word: edit it directly. A sentence or paragraph reworked with its idea unchanged: rewrite that unit whole and read it back against the standard. A changed idea, a section or more, or the second round of corrections on the same unit: hand the draft, the corrections, the standard, and the reference page to a fresh drafter and run the editor test after, because by then this session holds the old framing and the discussion about it, and patches accumulate into prose written in three different contexts. In co-writing, the session rewrites such a unit whole itself, since the owner reads it again.
Uncertain content is left out and recorded, never hedged. Concept sections describe, task pages instruct. A frontmatter description says what the page is for, so it changes only when that does: a new page gets it last, from the finished page, and an existing page keeps its own unless its purpose changed at scope, or gets one, written last, if it has none.
## Check (S7)
Read now: `writing-guides/formatting-guide.md`; the pack's procedures labeled S7.
Checking runs in two passes, the English first and the translations after S6, because every English change made after translation sends its sentences back through translation and the translation test. The API pack edits its three specs together at S5, so the owner reviews all three at the freeze, and its parity check stands in for the translation pass.
When a round carries text that already passed the editor and translation tests on the page it came from, as a cloud and self-host pair does, the round's work is the adaptation: the links, the disclaimer backlink, and the audience-specific fragments. Those are the sentences the editor test is told this round changed and the translation test reads on the zh and ja copies; both are skipped when none changed, and both read the whole carried text when you cannot confirm the source round ran them. The format and terminology checks run either way, at the target copy's release, because a carry can leave a link or a label that was right in the source tree and is wrong here.
In co-writing, and when a drafted page gets a section-by-section read, the owner walks the finished English page with the session before the checks below: the page's structure first (the order of its sections, whether each heading covers its section, what sits at the top), then one section at a time. A section the session calls unchanged is one whose every sentence it has read. The checks then judge the page the walk left, so their fixes don't land on text the walk is about to move.
1. Read it back per `references/drafting-turn.md` and fix what you find; a fault found once is swept across the page before it counts as fixed. Then run three checks on the English page; none depends on another, so they run together:
- A fact-check: a fresh agent given the page, the changed units, the pinned ref, the path to the codebase clone, and the read rules in `writing-guides/index.md` § "Syncing the Dify codebase safely" checks each claim this round wrote or changed (every claim, on a new page) and reports only mismatches. Drafting and fixes change claims after the research verified them. Where the pack's S7 verifiers already audit claims against code, as the API pack's do, that audit stands in.
- `dify-docs-editor-test`: a fresh agent reads the page against its standard and returns sentence-level marks and a verdict on this round's work. On a partial edit it gets the changed sections named; marks elsewhere on the page go to the owner as a list, not into the fix.
- `dify-docs-reader-test`: the check most likely to add or move content. On a page carried in part, it waits until the whole page has landed, and what it changes then goes back through S6.
2. Bring the owner the three reports together, with your proposal for each finding, sorted as the test skills say; the owner decides. Read every finding as the editor test reads a mark: evidence that a unit falls short, with any wording the check offers as one possible fix. A fact-check mismatch can't stay as it is, but first ask whether the claim belongs on this page: a rule another page owns becomes a link to it, and a detail this reader wouldn't ask for is cut rather than corrected. When marks cluster on one unit, or return to a unit already fixed, settle the unit's form and which page owns it before touching a sentence, then rewrite it whole as the Write stage sorts it; patches added one finding at a time are what crowd a clear unit. (Mitigation for Opus 5.5, which patched marked sentences one at a time and pasted in checks' wording.) A unit changed or rewritten here goes back through the editor test, and a claim it adds or changes through the fact-check, before step 3.
3. Run `dify-docs-format-check`, then `dify-docs-terminology-check`, then the pack's S7 verifiers on the English, fixing and re-running until each is clean; the terminology check is clean when its only remaining findings sit under its report's Dead glossary rows. The format check's parity step compares the page with its zh and ja twins, so it runs in the translation pass, not this one. A clean run is not a finished page.
4. Bring the owner the English. Their approval freezes it for translation. A single-page correction that skipped S4 still stops here.
This applies to every edit, including a one-line correction made without the rest of this pipeline: check the work before presenting it. Process documents (plans, design notes) are exempt. If you skip or change a stage, say so and why.
## Translate (S6)
Read now: `tools/translate/formatting-zh.md`, `tools/translate/formatting-ja.md`, and the glossary.
Every English change ships `zh/` and `ja/` in the same PR, and a new page is registered in all three navigation sections of `docs.json`.
A translator's brief names the units to carry and the page's own terms; the rules come from the language's formatting guide, and a rule the guide lacks is a change to propose to the guide, not a line in the brief. Translate from the English file on disk as it stands, not from the draft in the conversation. After a review round, diff the English file and carry every changed sentence, structural edits included, into zh and ja; a stated sync is intent, not verified state, and a deletion of content you drafted is confirmed with the owner before it is mirrored. Before translating a `use-dify` page, look for its translation in the sibling audience tree: swap `cloud` and `self-host` in the path under `zh/` and `ja/`. A page that already exists translated there is copied and adjusted (links, the disclaimer backlink, the audience-specific fragment), never re-translated, once its English source is confirmed to match this page's English on the shared content, the audience-specific block being an allowed difference; the two trees can sit on different releases, and a sibling from another release is translated from the current source instead. When the owner deletes from one translation, mirror the deletion in the other.
## Check the Translations (S7, continued)
Run `dify-docs-translation-test` on the zh and ja pages, then `dify-docs-format-check`, `dify-docs-terminology-check`, and the pack's S7 verifiers on them, fixing and re-running until each is clean. On a partial edit the test gets the changed sections named. "Needs retranslation" means the unit is redone whole. An English correction accepted here goes back through the English pass except the reader test, which reads whole pages: the fact-check and the editor test on the changed sentences, step 3, then the owner's freeze. It then returns to S6, so the zh and ja pages are judged as they will ship.
## Close (S8)
Read now, if the page has a sibling copy in the other audience tree or an Enterprise version: that copy, for the propagation proposal.
Report what changed, what stays open (unverified claims, routed questions, follow-ups), any glossary additions, any pack reference or guide the work showed to be stale, and the sibling copies affected.
Ver en GitHub