Take an articlealready writtenthrough a series of deterministic steps, save it into the user's own Official Accountdraft box, return mediaId。
Body text belongs to dby-write(or user-provided); data fetching, viral samples, and cover formulas belong to dby-api; compliance checking belongs to dby-banned-words。
🔴 End-state discipline: if the user only wants a finished draft,do not run this package— this package will write into their own Official Account backend, which is a real side effect.
If the end state is unclear, ask first; don't default to pushing forward.
Only want to save a draft, no formatting
Body textis already Official Account-style HTML, with no local images and no local cover, hit the CLI directly; no need to go through pipeline.mjs。
$SKILL_DIR = this package's directory (the directory given when the host loads this SKILL.md):
node "$SKILL_DIR/scripts/dby.mjs" wechat publish --appid <authorizerAppid> --title "标题" --html article.html --confirm
--confirm must already have the user's explicit confirmation to publish this one (see "Anti-mis-send red lines" below); without --confirm
it will stop at confirmation_required, exit code 6, and nothing happens. For parameter details see node "$SKILL_DIR/scripts/dby.mjs" wechat publish --help.
When there are local images / a local cover, switch to scripts/preprocess-and-publish.mjs, see references/draft-only.md。
Process declaration:pipeline.json
The 10-step SOP and all hard rules are declared in pipeline.json(steps[] + hardRules[]) — it is ahuman-readable convention document,
pipeline.mjs does not read it; if you change the process, you must manually sync both sides.The "cover / illustrations" step is executed by the agent(this package does not generate images, see the next section); the remaining steps are pipeline.mjs run mechanically to completion.
This document uses only step names, not numbers;pipeline.mjs the "step N" in the logs is the script's own mechanical step order and does not correspond to the SOP numbering.
→ When you want to check step by step what these 10 steps each do, read references/sop.md; if you don't need to, don't read it.
All calls explode duck: the two capabilities used by this Skill
Only name the capabilities and detail endpoints; pull the input parameters fresh before each call.
| operationKey | Detail endpoint | Used at which step |
|---|---|---|
skill.wechat.render ⚠️dedicated |
GET /api/skills/wechat-render |
"md→HTML" (the server-side formatting path) |
skill.wechat.draftPublish ⚠️dedicated |
GET /api/skills/wechat-draft-publish |
"Save draft" |
Generate cover / generate illustrationsnot in this package, the image generation capability is currently temporarily offline; whether it will be restored in the future needs re-evaluation, and no restoration time is currently promised. This package only consumesuser-provided or agent-generated with its own toolslocal files, and does not call offline capabilities or old packages.
Requests are sent on your behalf by scripts/pipeline.mjs(and the preprocess-and-publish.mjsit calls);
only read dby-gateway/references/protocol.mdwhen bypassing the script and assembling requests yourself (authentication, how to get the key,
pull the spec first then assemble parameters,execution.target, envelope format).
🔴 error codes are the exception; even when going through the script you must read: the script throws errors as-is with zero interpretation; if you hit one, read item 6 of that file
(429 is bucketed by IP; changing keys or opening a new session won't help; back off ≤3 times and don't add concurrency).
🔴 Twodedicated routesThe call address is only in target in, from the detail endpointcannot be inferred。
Saving a draft costs money; server-side layout rendering does not cost money; the current price is pulled live from the detail response and stated as-is; before taking the step that costs money, ask the user first.
→ What the user wantsgoes beyond the above two itemswhen, read dby-gateway/references/capability-index.md to choose the route,
read routing-pitfalls.md to see known pitfalls; in the normal flow neither of these needs to be read.
Before writing the body
- 🔴 The body does not include the title; the title only goes through
--title—the official account always takes the drafttitleto render the large title; if it is written again in the body it displays twice;--htmldirect-send pathas-issent out, with no deduplication; do not put<h1>。--mdat the beginning. For what the path covers, seereferences/rendering.md。 - bodyis not written via
dby-writewritten → first pull the writing spec, readreferences/writing-spec.md(dby-writestep 1 has already pulled this one, do not pull it again). - Billing only occurs when saving the draft succeeds, and on failure it is automatically refunded; the exact amount deducted is subject to the real-time points field of the detail endpoint,
do not calculate money for the user based on the numbers in the documentation.
402 INSUFFICIENT_CREDITSwhen, prompt the user to check the balance and how to obtain it on the account page (points are only gifted, not sold), and do not retry. - If you do not write
--themeit uses the default layout you saved in the layout studio; md→HTML only goes through the platformPOST /api/wechat/render(free),on failure always abort, never fall back to the local renderer. Which layout to apply / why rerunning an old draft looks different /> [!NOTE]prompt block → readreferences/rendering.md。
Cover and inline images (optional; this package does not produce images)
This packagedoes not produce images. When new images are needed, hand off to dby-image(rebuilt in 2026-09 as the server-side image generation capability is restored);
images can also come fromuser-providedoryour own agent's image generation tool:
after obtaining thelocal file pathconnect it back to the pipeline—
the cover goes through --cover <路径>; inline images are placed with <img src=本地路径> manually judged into the end of the corresponding h2 subsection in the Markdown source,
after entering the source, rerun rendering so the inline images get the theme image style. Uploading and arrangement still belong to this package (the pipeline preserves every <img src>
and pre-uploads local images). If the user has already said "push" anddid not mention cover / inline images, do not proactively arrange it: only prompt once
"if no cover is uploaded, the fallback cover will be used", then run directly.
CLI usage
🔴 Red lines against accidental sending(holds regardless of which entry point is used):Only save drafts, never mass-send—there is no mass-send path at all; the pipelinerejectsany
--mass-send/--broadcast/mass-send parameter;the account must be bound first(first authorize and bind the official account at doubaoya.com; this skill cannot bind it for you);
when the user only wants a finished draft, do not run it on your own initiative. After saving, ask the user to confirm with their own eyes in the backend; the hand that mass-sends is always the user's own.
export DOUBAOYA_API_KEY="dyh_…" # 或放 ~/.doubaoya/key、Keychain(account-verify 会找)
node scripts/pipeline.mjs --md article.md --title "标题" # 渲染 → 传图 → 存草稿
node scripts/pipeline.mjs --md a.md --title "标题" --render-only # 只渲染,拿在线预览链接
node scripts/pipeline.mjs --md a.md --title "标题" --dry-run # 发布前彩排,什么都不发
When the local machine has multiple keys corresponding to different accounts, account validation will stop and ask for --account <账号>, then add the accounts listed in the error and rerun.
The body comes frommanuscript surface(a manuscript the user has reviewed on the web review page), carry --draft <稿件 id>(optional --draft-version <n>,
omitted = latest version) — after the draft is successfully saved, the server will automatically associate the manuscript with this publish record; without it, it is a normal publish.
If carried but that manuscript does not belong to you → 422 VALIDATION_ERROR, the publish is not executed and no credits are deducted.
🔴 After it finishes, only trust the mediaIdin the final report — it is the sole proof of "saved to drafts"; without it, do not treat it as saved.
Draft save failed / Ctrl-C midway / unsure whether it is in drafts → read references/recovery.md(rerunning is not idempotent and will save an extra copy).
→ To specify an account / official account / local cover / summary, or to use the full form of --html、--theme , read
references/cli.md; if you do not need it, do not read it.
Uncommon branches: read only when needed; if not needed, do not read
| What the user is saying / what you need to do | Which one to read |
|---|---|
| Only check the layout(produce output locally to see the effect, do not publish) | Read only references/rendering.md, do not read anything else |
Which script does which thing, want to avoid pipeline.mjs and combine it yourself |
references/modules.md |
First time using this package(do not yet have config.json / identity card) |
references/setup.md(config.json belongs to you personally, do not commit it) |
Replicate the layout of a certain official account as theme.json |
references/clone-theme.md(contracts, validators, and how to choose ready-made themes are all in there) |
Prerequisites
Unified prerequisite Node ≥ 18, zero external dependencies. Local rendering requires no key and has no online links; platform rendering (--render-only) requires a key, has online links, and does not require binding an account;
--dry-run and saving draftsrequire a key and require binding an account.
→ For layer-by-layer details, read references/prerequisites.md; if you do not need it, do not read it.
Next step (after the draft is saved)
Once the draft is in the box, that is the endpoint. If you still want to go further:
| What the user wants next | Next step |
|---|---|
| After accumulating a few days of data, look at this account's posting performance / do a checkup | dby-api(use the account diagnosis capability skill.wechat.accountAnalyzer) |
| Track your own or competitors' posting cadence | dby-api(use the official account post list endpoint) |
| Pull the body text of published articles for archiving | dby-api |
| Use review signals to mine the next round of topics | dby-api(mine topics / chase hot topics, and also pull samples from here to start writing) |
| Cannot tell which step to go to | dby(hop-by-hop navigation of the official account flywheel) |
Update this skill
npx skills update dby-publish(for a global install, add -g). For change history, see README.md。