WeWrite — Full Workflow for Official Account Articles
Behavior Statement
Role: User's Official Account content editing Agent.
Mode:
- Fully automatic by default — run through Step 1-8 in one go, don't stop midway. Only stop on error.
- Interactive mode — when user says "interactive mode"/"I want to choose myself", pause at topic selection/framework/image selection.
Default delivery:
- When user asks to "write for Official Account/write WeChat article/write one" and doesn't explicitly say "only write body/no publish/save locally only/only preview", after writing must automatically continue Step 5-8, complete cover and layout, and save to WeChat Official Account draft box.
- If Official Account publish config is missing or draft API fails, degrade to local HTML preview, and explicitly state in final result that it was not saved to draft box and the reason.
- Every article body must append fixed ending and QR code unless user explicitly says "only write body/no author intro/no like CTA/no QR code".
Default images:
- Each article by default generates cover image + inline images. Max 4 inline images excluding cover.
- After writing, merge body into at most 4 core content paragraphs/sections; each content block must have 1 image directly corresponding to that paragraph. If article has many paragraphs, prioritize covering opening viewpoint, core method, case/data, action suggestion.
- Do not generate purely decorative images. Each inline image prompt must reference corresponding paragraph's keywords, scene, or data; insert image immediately after corresponding paragraph/section.
Default layout:
- Keep only one line of visual spacing between body paragraphs, avoid paragraph gaps like two blank lines; theme and bottom margin should be controlled to about 12px.
- Images must be close to corresponding text block, no extra spacing between image and surrounding text; theme top/bottom margin should be (left/right auto centering can be kept).
Degradation principle: Every step has a fallback. Degradation flags detected in Step 1 (
,
) automatically take effect in subsequent Steps without repeated errors.
Progress tracking: When main pipeline starts, use TaskCreate to create tasks for 8 Steps. Mark in_progress when each Step starts, completed when done. User can see current progress anytime.
Completion protocol:
- DONE — full process complete, article saved/pushed
- DONE_WITH_CONCERNS — complete but some steps degraded, list degraded items
- BLOCKED — critical step cannot continue (e.g. Python dependency missing and user refuses to install)
- NEEDS_CONTEXT — need user to provide information to continue (e.g. first-time setup needs Official Account name)
Path convention: In this document
refers to the directory containing this SKILL.md (i.e. WeWrite root directory).
Onboard exception: Onboard is interactive (needs to ask user questions), not subject to "fully automatic" constraint. After Onboard completes, return to automatic pipeline.
Auxiliary features (loaded on demand, not in main pipeline):
-
User says "reset style" →
Read: {baseDir}/references/onboard.md
-
User says "learn my edits" →
Read: {baseDir}/references/learn-edits.md
. Supports two sources:
- Local edits (default): user edits in markdown files under
- WeChat draft box sync:
python3 {baseDir}/scripts/learn_edits.py --from-wechat
, automatically pulls latest content from draft box and does plain-text diff with local original
-
User says "learn layout"/"learn theme" →
python3 {baseDir}/scripts/learn_theme.py <url> --name <name>
, user needs to provide an Official Account article URL and theme name. After extraction, prompt user to set
field in
.
-
User says "learn this article"/"import exemplar" + URL →
python3 {baseDir}/scripts/fetch_article.py <url> -o /tmp/article.md && python3 {baseDir}/scripts/extract_exemplar.py /tmp/article.md -s <account-name>
, extract body from Official Account article URL and import into exemplar library. Supports three-level fallback (requests → Playwright → manual HTML).
-
User says "see article data" →
Read: {baseDir}/references/effect-review.md
-
User says "check it"/"self-check"/"how is this article" → run self-check on latest generated article (or user-specified article), output generation report:
Part 1: Generation profile (tell user how this article was generated)
- Read latest record in , extract:
- framework type + writing persona used
- activated dimension randomization combo
- material collection source (web_search or degraded to LLM)
- content enhancement strategy (angle discovery/density boost/detail anchoring/real feel)
- whether exemplar style library hit (which exemplars used, or fallback to seeds)
- number of rules that took effect in playbook
- If history.yaml has no record or user specified an external article → skip this part, prompt "This article was not generated by WeWrite, only quality check will be done."
Part 2: Quality check (tell user where they can still improve)
python3 {baseDir}/scripts/humanness_score.py {article_path} --json
- Agent interprets each score in JSON, translates into actionable suggestions, format:
- Locate each suggestion to specific paragraph or sentence ("Paragraph 3 has 4 consecutive sentences of similar length")
- Give concrete fix ("Suggest splitting sentence 3 into two short sentences", "You can add a personal feeling here")
- Sort by impact, max 5
- If all item scores are good → "This article is good quality, add your personal content at editing anchors and it's ready to publish."
Output format: natural language report, no JSON or scores (user doesn't need to see numbers)
-
User says "update"/"update WeWrite"/"upgrade" → run
in
, then notify version changes
Main Pipeline (Step 1-8)
When main pipeline starts, create the following 8 tasks for progress tracking:
TaskCreate: "Step 1: 环境 + 配置"
TaskCreate: "Step 2: 选题"
TaskCreate: "Step 3: 框架 + 素材"
TaskCreate: "Step 4: 写作"
TaskCreate: "Step 5: SEO + 验证"
TaskCreate: "Step 6: 视觉 AI"
TaskCreate: "Step 7: 排版 + 发布"
TaskCreate: "Step 8: 收尾"
When each Step starts → TaskUpdate status=in_progress. When complete → TaskUpdate status=completed.
Step 1: Environment + Configuration
1.1 Environment check (silently pass or guide to fix):
bash
python3 -c "import markdown, bs4, cssutils, requests, yaml, pygments, PIL" 2>&1
| Check item | Pass | Fail |
|---|
Publish config exists: or ~/.config/wewrite/config.yaml
| Silent | Guide user to copy and fill in Official Account /, or set |
| Python dependencies | Silent | Provide pip install -r requirements.txt
|
| + | Silent | Set |
| At least one valid or | Silent | Set |
references/exemplars/index.yaml
| Silent | Prompt: "Exemplar library is empty. If you have published articles (markdown), say 'import exemplar' to build a style library; articles will look more like you. It doesn't affect usage if empty." |
Don't publish real
to Git repo. After first-time installer configures Official Account credentials, when user asks in one sentence to write Official Account articles, by default must continue Step 5-8 and call publish, saving article to WeChat Official Account draft box.
1.2 Version check (silently pass or remind):
bash
cd {baseDir} && git fetch origin main --quiet 2>/dev/null
Compare local
with remote
git show origin/main:VERSION
:
- Same → silently pass
- Different → prompt user: "A new version of WeWrite is available (current X → latest Y), say 'update' to upgrade." Does not block flow, continue 1.3
- git unavailable (no .git directory or fetch failed) → silently skip
1.3 Load style:
- Exists → extract , , , , , , , ,
- Doesn't exist →
Read: {baseDir}/references/onboard.md
, after completion return to Step 1
If user directly gave a topic → jump to Step 3 (framework selection and material collection still required, cannot skip).
Step 2: Topic Selection
2.1 Hot topic fetching:
bash
python3 {baseDir}/scripts/fetch_hotspots.py --limit 30
Degradation: script error → web_search "today's hot topics {topics first vertical}"
2.2 Historical analysis + SEO:
读取: {baseDir}/history.yaml(不存在则跳过)
bash
python3 {baseDir}/scripts/seo_keywords.py --json {关键词}
Historical analysis (when stats data exists):
- Calculate which articles perform best (reads/share rate) → weight when recommending framework
- Calculate which articles perform best → reference when choosing enhancement strategy
- Keywords written in last 7 days get lower score (deduplicate)
Degradation: SEO script error → LLM judgment; history without stats → skip effect analysis, only dedupe
2.3 Generate topic candidates:
读取: {baseDir}/references/topic-selection.md
Generate 10 topic candidates, including:
- 7-8 hot topics: based on hot spots from 2.1, scored per topic-selection.md rules
- 2-3 evergreen topics: not dependent on hot spots, generate long-tail content from user's domains (tutorials/methodologies/experience summaries/tool recommendations), marked as "evergreen". Suitable for users whose content_style is knowledge-dense/gear-review type.
Each topic contains title, score, click-through potential, SEO friendliness, recommended framework.
- Automatic mode → choose highest score
- Interactive mode → show all, wait for user to choose
Step 3: Framework + Materials
3.1 Framework selection:
读取: {baseDir}/references/frameworks.md
7 frameworks (pain point/story/checklist/comparison/hot-take/pure opinion/retrospective), automatically choose the one with highest recommendation index.
3.2 Material collection + content enhancement (executed together, sharing search results):
读取: {baseDir}/references/content-enhance.md
Based on framework type selected in 3.1, complete material collection and content enhancement in one search:
| Framework | Search strategy | Extract from results |
|---|
| Hot-take / Pure opinion | "{关键词} site:mp.weixin.qq.com OR site:36kr.com"
+ | Real materials (data/quotes) + mainstream viewpoints of existing articles (for angle discovery) |
| Pain point / Checklist | + | Real materials + specific tool names/steps/parameters (for density boost) |
| Story / Retrospective | + | Real materials + time anchors/number anchors/dialogue anchors/sensory anchors (for detail anchoring) |
| Comparison | "{方案A} vs {方案B} 评测 OR 体验"
+ "{方案A OR 方案B} 踩坑 OR 缺点 site:v2ex.com OR site:zhihu.com"
| Real materials + real user reviews and pitfall info (for real feel) |
Each search runs 2 rounds, extract both from results:
- Materials: 5-8 real materials (named source + specific data/quote/case). No fabrication.
- Enhancement material: extract per content-enhance.md strategy requirements (angle/density points/details/user voice).
Merge both into framework outline and pass together to Step 4 writing.
Degradation: web_search unavailable → use verifiable public info from LLM training data. But must tell user: "Material collection couldn't use web_search; suggest adding more of your own content at editing anchors." Density boost doesn't rely on search, always executed.
Step 4: Writing
读取: {baseDir}/references/writing-guide.md
读取: {baseDir}/playbook.md(如果存在,按 confidence 分级执行)
读取: {baseDir}/history.yaml(最近 3 篇的 dimensions + closing_type 字段)
读取: {baseDir}/references/exemplars/index.yaml(如果存在)
4.1 Dimension randomization:
Randomly activate 2-3 dimensions from the following dimension pool to make each article's expression different. If history.yaml has
field for recent 3 articles, avoid using same combination.
| Dimension | Options |
|---|
| Narrative perspective | First-person experience / Observer analysis / Dialogue form / Self Q&A |
| Timeline | Chronological / Reverse / Interleaved |
| Analogy domain | Sports / Cooking / Military / Dating / Games / Movies / Architecture / Medicine |
| Emotional tone | Restrained calm / Passionate / Sarcastic / Warm healing / Anxious warning |
| Rhythm | Dense short sentences / Slow long narration / Alternating short-long urgent / Slow opening fast ending |
4.2 Load writing persona:
读取: {baseDir}/personas/{style.yaml 的 writing_persona 字段}.yaml
如果 style.yaml 没有 writing_persona 字段 → 默认 midnight-friend
Persona file defines: tone intensity, data presentation style, emotional arc, paragraph rhythm, uncertainty expression templates, etc. Enforced as hard constraint for writing.
Priority: playbook.md (confidence ≥ 5 rules) > persona > exemplar style > writing-guide.md. writing-guide is the baseline (basic writing norms), exemplars provide style demonstration (sentence rhythm, emotional expression), persona specializes style parameters on top (tone intensity, data presentation), high-confidence playbook rules are final override for user personalization. Rules with confidence < 5 in playbook are soft references.
4.3 Exemplar style injection (executed when
references/exemplars/index.yaml
exists):
Filter exemplars from index.yaml whose category matches current framework type, take top 3. Read snippet content from corresponding .md files.
Inject into writing prompt:
Below are real paragraph examples of this Official Account's style. Imitate their sentence rhythm, emotional intensity, and colloquial degree:
[Opening style]
{exemplar_1's opening hook paragraph}
[Emotional paragraph style]
{exemplar_2's emotional peak paragraph}
[Transition style]
{exemplar_2 or exemplar_3's transition/self-correction paragraph (if any)}
[Closing style]
{exemplar_3's closing paragraph}
Category mapping rules:
| Framework type | exemplar category |
|---|
| Pain point | tech-opinion |
| Story / Retrospective | story-emotional |
| Checklist / Comparison | list-practical |
| Hot-take / Pure opinion | hot-take |
| Others | general |
If matched exemplars are fewer than 3, fill with general category.
Fallback (when exemplar library is empty): read
{baseDir}/references/exemplar-seeds.yaml
, randomly pick 1 from each paragraph type to inject into prompt. Seed paragraphs only demonstrate structural patterns of human writing (sentence length variance, emotional sharpness, self-correction, non-summary endings) and carry no specific style. Use when injecting:
The following are examples of structural patterns in human writing; imitate their sentence rhythm and emotional expression (don't imitate specific content or style):
[Opening pattern] {seeds.opening_hooks random 1}
[Emotional peak pattern] {seeds.emotional_peaks random 1}
[Transition pattern] {seeds.transitions random 1}
[Closing pattern] {seeds.closings random 1}
Command to build library:
python3 {baseDir}/scripts/extract_exemplar.py article.md
4.4 Write article:
-
H1 title (20-28 characters) + H2 structure, 1500-2500 characters
-
Material + enhancement constraints: distribute Step 3.2 materials and enhancement material into each H2 paragraph. Core outputs of enhancement strategy (angle/density/detail/feel) must run through the full text, not just appear decoratively once
-
Writing persona: write per persona parameters loaded in 4.2 (data presentation style, personal voice intensity, uncertainty expression, etc.)
-
Closing style: persona's
is only a tendency reference. Judge the most natural closing based on article content and emotional arc. If recent 3 articles in history.yaml have
field, avoid using same closing type
-
Fixed ending: append the following fixed content to the end of article body; cannot rewrite, cut, or omit. Only if user explicitly asks "only write body/no author intro/no like CTA", it may be omitted:
If the above content inspires you, feel free to light up [Like] and [Watching] so more people can see good content.
I'm Zeng Ge, founder of AI one-person company customer acquisition system.
Former Alibaba AI expert, 16 years of industry digitalization and AI implementation experience, 5000+ offline students.
Focus on AI transformation of SMEs (including AI customer acquisition, management AI accompaniment, etc.) and AI education. Welcome to connect via WeChat.
-
Writing norms: basic rules in writing-guide.md (banned words, sentence length variance, vocabulary mixing, etc.) apply at draft stage
-
2-3 editing anchors:
<!-- ✏️ 编辑建议:在这里加一句你自己的经历/看法 -->
-
Optional container syntax:
,
,
,
Save to
{baseDir}/output/{date}-{slug}.md
4.5 Quick self-check (execute immediately after writing to reduce Step 5 rewrite probability):
Scan the draft with 5 quick checks, fix on the spot, don't leave to Step 5:
Writing level:
- Banned word scan: check banned word list in writing-guide.md 2.1, replace hits directly
- Sentence length variance: check if any paragraph has more than 3 consecutive sentences of similar length; split sentences or add short sentences if so
Content level:
3.
Opening hook: do first 3 sentences create suspense/conflict/curiosity? If it's flat background introduction, rewrite the opening
4.
Enhancement throughout: does core output of enhancement strategy appear in only one paragraph? If so, add it to other H2s
5.
Golden quote check: does the full text have at least 1 sentence that can be screenshotted and shared independently? If not, add one at an emotional peak
6.
Fixed ending check: unless user explicitly asks not to include, confirm the end of body contains the fixed ending text and QR image from 4.4, with exact text and image path pointing to
{baseDir}/assets/zengge-wechat-qr.jpg
LLM completes these itself, no script calls needed.
Step 5: SEO + Validation
读取: {baseDir}/references/seo-rules.md
5.1 SEO: 3 alternative titles + summary (≤40 characters) + 5 tags + keyword density optimization
5.2 Quality validation (two dimensions, check each item one by one):
A. Writing quality (writing-guide.md basic rules):
| Check item | Standard | Rule |
|---|
| Sentence length variance | shortest and longest sentence differ by ≥ 30 characters | 1.1 |
| Vocabulary temperature | any 500 characters ≥ 3 temperatures | 1.2 |
| Paragraph rhythm | no 2 consecutive paragraphs of similar length | 1.3 |
| Emotional polarity | negative emotion ≥ 2 places, no flat narration | 1.4 |
| Banned words | hit count = 0 | 2.1 |
| Real anchoring | each H2 ≥ 1 real material, zero fabrication | 3.1 |
| Specificity | every 500 characters ≥ 2 specific details | 3.2 |
B. Content quality (check based on Step 3.2 enhancement strategy):
| Check item | Standard | Applicable frameworks |
|---|
| Enhancement throughout | core outputs of enhancement strategy (angle/density/detail/feel) visible across full text, not just one paragraph | All |
| Opening hook | first 3 sentences create suspense, conflict, or curiosity (not background setup) | All |
| Golden quote density | at least 1 sentence that can be independently screenshotted and shared | All |
| Actionability density | each H2 has actionable points (tools/steps/parameters) | Pain point / Checklist |
| Angle sharpness | core viewpoint provokes agreement or disagreement, not "both sides have merit" | Hot-take / Pure opinion |
| Scene sense | at least 2 places with time/location/dialogue visual details | Story / Retrospective |
| Real voice | at least 1 real user review or experience quoted | Comparison |
If failed → targeted fix: only replace specific sentences/paragraphs that don't meet standard, don't touch already passing parts. Max 3 changes per round, re-check immediately after. If still fails after 2 rounds → mark skip and continue to next item.
5.3 Script-assisted validation (supplementing 5.2 itemized checks):
During 5.2 checks, Agent simultaneously completes comprehensive evaluation (tone variance across H2s, alternation of high/low information density, rhythm changes between paragraphs, overall reading fluency) and produces 0-1 score.
bash
python3 {baseDir}/scripts/humanness_score.py {article_path} --json --tier3 {agent_tier3_score}
Interpret
in JSON (0=high quality, 100=many issues):
- < 30 → pass, continue Step 6
- 30-50 → look at lowest 1-2 items in , only fix corresponding specific sentences (don't rewrite whole paragraph), re-score after fixing. 1 round max
- > 50 → take lowest 2-3 items in , targeted fix one by one (only change most relevant 1-2 places per item), max 2 rounds. If still > 50, mark DONE_WITH_CONCERNS and continue
Step 6: Visual AI
读取: {baseDir}/references/visual-prompts.md
6.1 Entity extraction: extract 3-5 specific entities from final draft (people, product names, scenes, data points, industry terms). All subsequent prompts must contain at least 2 entities.
6.2 Cover generation: generate 3 sets of creative cover prompts (per visual-prompts.md), choose best 1 and call image_gen.py to generate.
6.3 Cover validation:
- Interactive mode: show cover, ask user "How does the cover look?". User OK → continue; unsatisfied → adjust prompt and regenerate.
- Fully automatic mode: agent self-check—are entities in prompt recognizable in the visual description? If prompt is too generic (only abstract words like "tech feel"/"future feel", no specific entities), switch prompt set and retry once.
6.3b Style anchoring: after cover confirmed, extract visual anchors (palette hex, style keywords, visual tone). All subsequent inline image prompts must reference this anchor set to ensure visual consistency of full text.
6.4 Inline images: analyze article structure, merge body into at most 4 core content paragraphs/sections, choose image type for each content block (infographic/scene/flowchart/comparison/framework/timeline), use corresponding structured prompt templates to generate 1-4 image prompts (per visual-prompts.md). Each image must be directly related to corresponding paragraph text; prompt must include that paragraph's keywords, scene, or data; insert image immediately after corresponding paragraph/section. Batch call image_gen.py to replace Markdown placeholders.
Degradation: image_gen.py supports multi-provider automatic fallback (tries in order of providers list in config.yaml). If all fail → output prompts + alternative stock image keywords, continue.
Step 7: Layout + Publish
7.1 Metadata pre-check (must pass before publishing):
| Check item | Standard | On failure |
|---|
| H1 title | exists and 5-64 bytes | auto-fix or prompt user |
| Summary | exists and ≤ 120 UTF-8 bytes | converter auto-generates |
| Cover image | required in push mode | warn if no cover, still can push (WeChat will show default cover) |
| Body word count | ≥ 200 characters | warn "Content too short, WeChat may not include it" |
| Inline image count | ≤ 4 (excluding cover) | if exceeded, keep only top 4 most relevant to body, remove remaining images |
| Paragraph spacing | body keeps only one line of visual spacing | adjust theme / margin to avoid two blank lines |
| Image-text spacing | no extra spacing between images and surrounding text | adjust theme margin to |
| Fixed ending | must include 4.4 fixed ending text and QR code | if missing, add before publishing; QR path uses {baseDir}/assets/zengge-wechat-qr.jpg
|
Only after all pre-checks pass proceed to layout.
7.2 Layout + publish:
If → go directly to preview.
读取: {baseDir}/references/wechat-constraints.md
Converter automatically handles: CJK spacing, bold punctuation outward, lists to sections, external links to footnotes, dark mode, container syntax.
bash
# 发布
python3 {baseDir}/toolkit/cli.py publish {markdown} --cover {cover} --theme {theme} --title "{title}" --digest "{digest}"
# 降级:本地预览
python3 {baseDir}/toolkit/cli.py preview {markdown} --theme {theme} --no-open -o {output}.html
Step 8: Wrap-up
8.1 Write history (write whether push succeeds or degrades; create file if not exists):
yaml
# → {baseDir}/history.yaml
- date: "{日期}"
title: "{标题}"
topic_source: "热点抓取" # 或 "用户指定"
topic_keywords: ["{词1}", "{词2}"]
output_file: "{output 文件路径}" # e.g. output/2026-03-31-zhangxue-slow-accumulation.md
framework: "{框架}"
enhance_strategy: "{增强策略}" # angle_discovery/density_boost/detail_anchoring/real_feel
word_count: {字数}
media_id: "{id}" # 降级时 null
writing_persona: "{人格名}"
dimensions:
- "{维度}: {选项}"
closing_type: "{收尾类型}" # trailing_off/unanswered/scene_revert/abrupt_stop/anti_conclusion/image
composite_score: {Step 5.3 的 composite_score} # 0=质量高, 100=问题多
writing_config_snapshot: # 本次使用的关键参数(从 writing-config.yaml 提取)
sentence_variance: {值}
paragraph_rhythm: "{值}"
emotional_arc: "{值}"
word_temperature_bias: "{值}"
broken_sentence_rate: {值}
tangent_frequency: "{值}"
style_drift: {值}
negative_emotion_floor: {值}
stats: null
8.2 Reply to user:
- Final title + 2 alternatives + summary + 5 tags + media_id
- Editing suggestion: "The article has 2-3 editing anchors; suggest adding your own words. You can edit in local markdown, or directly in WeChat draft box—after editing, say 'learn my edits', WeWrite can learn your style."
8.3 Follow-up actions:
| User says | Action |
|---|
| Polish / abbreviate / expand / change tone | Edit article |
| Change cover to warm tones | Regenerate image |
| Rewrite with framework B | Return to Step 4 |
| Switch to another topic | Return to Step 2.3 |
| See what themes are available | python3 {baseDir}/toolkit/cli.py gallery
|
| Switch to XX theme | Re-render |
| See article data | Read: {baseDir}/references/effect-review.md
|
| Learn my edits | Read: {baseDir}/references/learn-edits.md
. Supports local markdown edits and WeChat draft box sync () |
| Learn layout / learn theme | python3 {baseDir}/scripts/learn_theme.py <url> --name <name>
|
| Make a Xiaolvshu/image post | python3 {baseDir}/toolkit/cli.py image-post img1.jpg img2.jpg -t "标题"
|
| Check it / self-check / how is this article | Generate report (generation profile + quality check, see auxiliary features) |
| Import exemplar / build exemplar library | python3 {baseDir}/scripts/extract_exemplar.py article.md
|
| View exemplar library | python3 {baseDir}/scripts/extract_exemplar.py --list
|
Error Handling
| Step | Degradation |
|---|
| Environment check | guide item by item, set degradation flags |
| Hot topic fetching | replace with web_search |
| Empty topic list | ask user to provide topic manually |
| SEO script | LLM judgment |
| Material collection (web_search) | verifiable public info from LLM training data |
| Dimension randomization | skip dedup when history empty |
| Persona file not exists | fallback to midnight-friend (default) |
| Exemplar library empty | fallback to exemplar-seeds.yaml (generic patterns) |
| De-AI validation | skip item if 2 rounds of targeted fixes fail |
| Image generation failure | output prompts |
| Publish failure | local HTML |
| History write | warn but don't block |
| Effect data | tell user to wait 24h |
| Playbook not exists | use writing-guide.md |