← SurferCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Surfer
Snapshot Oct 7, 2026 · 18:03 UTC · version 0.1.0
Collection source: downloaded plugin package.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"description": "Use when the user wants Surfer to produce a brand-new article or blog post from a keyword or topic. Triggers include \"write an SEO article about X\", \"draft optimized content for this keyword\", \"generate a Surfer AI article\", and \"write for SEO and AI Search\". To improve content that already exists, use surfer-optimize-content. For a writer brief without a draft, use surfer-create-content-brief.",
"included_files": [
{
"relative_path": "LICENSE",
"size_in_bytes": 1079
},
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 440
}
],
"name": "surfer-write-article",
"skill_md_contents": "---\nname: surfer-write-article\ndescription: >-\n Use when the user wants Surfer to produce a brand-new article or blog post from a keyword or topic.\n Triggers include \"write an SEO article about X\", \"draft optimized content for this keyword\",\n \"generate a Surfer AI article\", and \"write for SEO and AI Search\". To improve content that already\n exists, use surfer-optimize-content. For a writer brief without a draft, use\n surfer-create-content-brief.\nlicense: MIT\n---\n\n# Surfer: Write an Optimized Article\n\n## Overview\n\nTurn a keyword into a new, AI-authored draft grounded in Surfer's SEO and AI Search analysis. When\nthe user wants only an outline or a brief, create a manual Content Editor and stop before\n`ai_article__generate`.\n\n## Prerequisites\n\n- Require connected Surfer MCP tools. For setup or connection failures, use `surfer-connect`;\n ask to install it if missing. If a required tool is unavailable, name it and stop.\n- Use the `workspace_id` supplied by the user or the handoff, and verify it is active with\n `workspace__list`. If none was supplied, use the sole active workspace or ask the caller to\n choose when several are active.\n- Accept an existing `content_editor_id` as a first-class input, especially from a recommendation,\n outline, or brief handoff. Require `main_keyword` for a new editor; for an existing editor, read\n its keyword and accept up to 19 secondary keywords. Default the location to United States and the\n device to mobile only when creating. Location and device are inputs to `content_editor__create`.\n- Before creation, collect the optional `target_word_count`, any SEO or AI Search score targets,\n and `manual_outline`, which is an `ai_article__generate` input. Collect the full editor setup as\n well: the `use_brand_knowledge` toggle (it applies the workspace's brand profile, which cannot be\n inspected or edited from here), one `custom_template_id` or `surfer_template` as the content type\n (mutually exclusive), and `custom_instructions`. When both template fields are omitted, Surfer\n picks a template itself during analysis, so a request for no template cannot be guaranteed.\n Omitting `custom_voice_id` applies the workspace default voice. To honor a request for no voice,\n send `custom_voice_id: null`. Competitors are read from the `competitors` block of\n `seo_guidelines__get` and changed with `seo_guidelines__update_competitors` after initialization.\n- Treat \"AI writing mode\" as the `ai_article__generate` call rather than a `content_editor__create`\n field. Leave it out for manual work.\n\n## Playbook\n\n1. **Reuse or create the Content Editor.** When `content_editor_id` is supplied, read it with\n `content_editor__get` in the selected workspace. Verify the keyword and any location, device, or\n setup constraints the user supplied; report a mismatch before generating. Keep its existing\n settings unless the user requested a change. Reuse it for a continuation or a first draft from\n an outline or brief. An explicit request for another, separate article takes priority: create a\n fresh editor with the requested setup. Otherwise, if no id was supplied, look for a matching\n editor the user asked to continue and call `content_editor__create` only if none applies.\n Include the keyword, location, device, selected brand toggle, template or voice, and custom\n instructions. A create consumes a credit, so use one `idempotency_key` for that logical create\n and reuse it after an ambiguous response. If no template is selected, keep the one Surfer chooses\n during analysis.\n\n2. **Wait for initialization.** Await the completion signal or poll `content_editor__get` until\n `state` is `completed`. Report a failure or a bounded timeout with the editor id.\n\n3. **Review the content plan before drafting.** Read `seo_guidelines__get`, one brief with the terms,\n structure targets, topics, questions, and competitors. Read `ai_search_guidelines__list_facts`\n when AI Search is a goal. Read `content_editor__get` to verify the brand toggle, template or\n voice, and instructions. If the user asks to change competitors, inspect the `competitors` block\n of `seo_guidelines__get`, apply an approved `seo_guidelines__update_competitors`, then re-read the\n affected guidelines before generating.\n\n4. **Choose outline behavior.** `outline__get` returns the read-only SERP outline.\n `outline__regenerate` rebuilds it from the SERP competitors with the editor's template,\n instructions, and brand knowledge. Use it after a setup change or a failed outline. For a\n reviewable AI outline, set `manual_outline: true` when calling `ai_article__generate`. That\n outline is separate from the SERP outline and pauses before prose is written.\n\n5. **Generate or continue the requested article.** Call `ai_article__generate` for a new draft.\n For a continuation, use `ai_article__get` with the known article id, or `ai_article__list` to find\n it. If generation reports an existing-article conflict, use the returned article id to continue\n that work. Surfer rejects another generation in an editor with an in-progress or completed\n article; an explicit request for a separate article uses a fresh editor as in step 1. After a\n lost response, use `ai_article__list` to recover the article; if the outcome remains unclear,\n report it and stop without an automatic retry. On `waiting_for_user_input`, fetch\n `ai_article__get_outline`, present it, and submit only the user-approved version with\n `ai_article__submit_outline`. While it is `new`, `generating_outline`, or `writing`, wait. On\n `failed`, report and stop.\n\n6. **Read the canonical draft and score snapshot.** Await the completion signal or poll\n `ai_article__get` until `completed`. Fetch `content__get`, then read `content_score__get` for the\n unified `total` plus the `seo` and `ai_search` subscores. Trust an individual score only when its\n `status` is `ready`. A `loading` or `calculating` status is still settling. An `error` or\n `unavailable` AI Search score is terminal. Call it out rather than treating it as a pass or\n polling for `ready`.\n\n7. **Iterate only toward user-selected targets.** If a target is set and unmet, improve the draft\n with the relevant SEO guidance and the sourced AI Search facts, write it with `content__update`,\n re-fetch the sanitized stored version with `content__get`, and wait for the selected score\n timestamps to advance. Stop after 3 to 5 rounds or after a plateau. Do not chase a unified Content\n Score target.\n\n8. **Deliver and hand off.** Return the canonical content, the SEO, AI Search, and unified scores\n separately, the Content Editor id, and an edit or share link from `permalink__list`. For a\n recommendation-led workflow, hand control back to `surfer-content-recommendations`.\n"
}SHA-256 of public snapshot: 634900852c956ef285a3229f6ae20d01869d0a26b4d17ff8e44767f14ad0273c