Skip to content
Dee Wan 1.0 is not yet released (pre-MVP). See the 1.0 product boundary.

Content planner

The planner finds topics, researches them, writes ordinary draft entries and lists the work in a queue. It never publishes. Open Planner in the sidebar. It needs the ai:generate permission on the site.

Everything a plan writes is a normal draft. It goes through the same editor, workflow, versions, history and audit record as a draft you write yourself.

Leaving an edited plan asks whether to discard unsaved changes, including Back and Queue. Stay to keep editing, or leave to discard them. Switching plans ignores late responses for the previous selection.

A plan targets one content model and one or more of the site’s languages. It holds:

  • a goal, an audience and a list of exclusions;
  • the field mapping;
  • the sources;
  • an optional list of topics;
  • the number of items per run (1 to 10) and per day (1 to 50, never less than the per-run number);
  • an optional cadence;
  • the final action: Save drafts (default) or Schedule passed drafts.

The accepted Site Brief is always part of the context. Saving changes to a plan creates a new immutable version of that plan. A run keeps the version it started with, so later edits never change a run in progress. A site can have up to 20 active plans, up to 10 languages per plan, up to 30 topics and up to 10 sources per plan.

A plan names which model field takes the headline, the body and, optionally, the summary, web address, search title, search description, a main image field and up to 5 relation fields (the plan form’s Where it saves section).

  • The starter blog model has a preset: its title is the Headline and its body is the Body. The preset is offered only while the model still has those fields.
  • A custom model has no preset. You map each field once, in the plan. The planner never guesses a field.
  • The headline must be a text field. The body must be a rich text or long text field. A field can be used once.
  • A required model field that the mapping does not cover, and that has no default, makes the mapping invalid.
  • The mapping is checked when you save the plan, before an automatic run starts, before every stage of a run and before every draft is saved. If someone changes the model so the mapping no longer fits, the run stops before more AI work, its running items wait in Needs review (profile_invalid), and a due run waits with the reason until you edit the plan.

With Create an image with AI ticked on the Main image field, the planner generates a picture (see Main image). A relation field offers only published entries of the model it points to, the 50 most recently changed.

Turn on any of these source modes on a plan.

Mode What it reads
Topics The topics you list. Each has a label, an optional angle and optional included and excluded terms.
Entries on this site Entries you select. The current published text is used.
Web pages Manual HTTPS addresses.
News feeds RSS or Atom feeds. The 5 newest entries are used. Their own text is used when present, otherwise the linked page.

There is no built-in search provider and no built-in list of topics, industries or countries.

Page and feed fetches are limited:

  • HTTPS only, without credentials or a fragment in the address;
  • no private, local or reserved addresses, and no names without a dot;
  • at most 3 redirects, and every redirect is checked again;
  • at most 1 MiB per source and 10 seconds per fetch;
  • page types text/html, application/xhtml+xml and text/plain; feed types application/rss+xml, application/atom+xml, application/xml and text/xml;
  • at most 50 entries are read from a feed.

A refused source is marked source_refused. A source that does not answer is marked source_unavailable. Timeouts, 408, 429 and 5xx answers are retried. An address that fails the policy is refused when you save the plan.

The check inspects the address itself. It cannot determine which address a public hostname resolves to.

A plan may name a source model and a rule. Set them under More options at the end of the plan form: Cover entries from and May propose updates to drafts it created. The planner then proposes one new item per language for each published source entry that has no item yet. When the rule allows revisions, it proposes a revision when the source entry changed since the item was made, and only for the entry an earlier item of the same plan saved. It records the source entry and version that caused the proposal. A proposal for a new entry follows the same duplicate rule as a topic idea (see Duplicates): an exact match stops it by name, and a near match is re-angled at most twice before it waits in Needs review with the compared entries of each language. The languages of one proposal stay together. A proposal that cannot run is kept in Needs review, never dropped. The planner never makes an item for every row without the rule, never changes an entry silently, and never infers ownership.

Revisions need permission to update entries of the target model, not only to create them. The same is true of a plan with more than one language or a generated main image, because adding a language and attaching an image are updates.

A topic has a name, an optional angle, optional included and excluded terms, and a switch, Use this topic. Runs use only the topics that are switched on. A topic that is off stays in the plan with its history and is never used. Remove takes a topic out for good: it is deleted, or, when items already name it, it is hidden from the plan and the rotation while those items keep showing its name. The plan screen shows, for each saved topic, when it was last tried and when it last made an item.

An automatic run writes only about the selected topics. For each topic the planner proposes one idea, written in every language of the plan.

  • The topic tried least recently goes first, then the one that made an item least recently, then the order in the list. Every selected topic is tried once before any is tried again, across runs too.
  • A topic with no useful idea records “no candidate” (no_candidate) and the run moves on to the next topic in the same step budget. The planner does not widen a topic or invent another one to reach the requested number.
  • A topic that came up empty in a run, or whose idea was an exact duplicate, is skipped for the rest of that run. It goes to the back of the order for the next run.
  • An idea that uses an excluded term, or none of the included terms when you set some, is not used.
  • When no selected topic can give another idea, the run ends as partial with the reason “The selected topics had no more grounded, new ideas.”

A topic counts as tried after every attempt to find an idea in it. It counts as having made an item when the attempt produced one, and again when that item becomes a draft or is scheduled.

The planner compares a proposal, from a topic or from coverage, with its other items, with drafts and with published entries of the target model in the same language. It checks the 500 most recent items and the 500 most recent entries.

  • An exact match of title or intent stops the idea. No item is made for a topic idea; a coverage proposal is kept in Needs review so the source entry is not lost.
  • A near match (word overlap of 0.6 or more) is re-angled, at most twice. If it is still near, the item is made in Needs review with the compared entries shown.
  • Checks run again before a draft is scheduled. An exact match with a published entry stops there.

The comparison is lexical. It works without any embedding model.

Before writing, the planner reads the sources and extracts claims. It keeps a claim only when its excerpt is an exact quote of the source text, or an exact fact from the accepted Site Brief. Excerpts are at most 1,000 characters, and an item keeps at most 40.

  • If no claim is supported, or claims conflict, the item goes to Needs review with named issues.
  • A draft may leave a source claim out. It may not invent a fact.
  • Required wording from the Site Brief must appear word for word.
  • The item shows its sources, claims and issues next to the draft.

One model call writes the mapped fields. The body uses the rich document format, never executable HTML. Internal links go only to current published pages of the site. External links go only to recorded evidence addresses or to the Site Brief’s valid destinations.

Checks run on the server and do not depend on a model’s opinion. Each issue has a code, a field and a plain sentence.

Code Meaning
schema_invalid A value does not fit its field.
required_missing A required field is empty.
length_bounds A field is too long or too short.
rich_invalid The body is not a valid rich document.
required_wording_missing Required wording is absent.
forbidden_claim The draft makes a claim the Site Brief forbids.
claim_unsupported The draft relies on a claim without evidence.
duplicate_intent The draft repeats existing content (a near match is a warning).
link_not_allowed A link or picture is not allowed.
source_rule The draft uses a term the plan excludes.
relation_invalid A chosen related entry is not allowed.

A body may not contain pictures or embeds; media comes only through the media library. A number in the draft that no supported claim or Site Brief fact states is claim_unsupported.

Errors start a repair. A repair rewrites only the failing fields or passages and runs at most twice. If errors remain, the item goes to Needs review with the best result so far kept. A score never publishes, schedules or hides a failed check.

The draft is saved once through the normal content lifecycle, as the plan owner. The key comes from the plan version, the source and the language, so a replay returns the same entry instead of a second one. A revision pins the version it read. If the entry moved, the item stops as a conflict.

Before the save the planner rechecks the owner’s permission, the field mapping and duplicates.

The languages of one idea are saved as translations of one entry. The first language creates the entry. Each later language is added to it through the lifecycle’s add-language path, pinned to the entry’s current version. Later languages write only translatable fields. Relation fields stay with the first language. If a language already exists on the entry, for example one a person added, the item stops as a conflict (target_conflict) and nothing is overwritten.

When the mapping says Create an image with AI, the planner generates one image per idea after the first draft is saved. It spends site AI credit, stores the picture in the media library through the normal media upload path, and attaches it with a second save of the draft. It never replaces an image already in the field, and it does not attach the image if a person edited the draft meanwhile (the image stays in the library). A retry does not pay for a second image.

If the image fails, the item gets the warning image_failed, the draft is kept and the item still becomes ready.

A required main image field cannot use generation, because the image arrives after the first save. The plan refuses this setup.

Schedule passed drafts is offered only when the Scheduling plugin is installed, active and granted for the target model. You choose the publish transition, a timezone and a delay from 5 minutes to 30 days after the draft is ready.

The planner saves the draft first. Then it asks Scheduling to schedule exactly the version it saved, as the plan owner, with the owner’s live permissions. It uses Scheduling’s schedule-draft operation, which only the planner calls: it is not an operation people or agents run from an entry, Settings, the management API, the CLI or MCP. Core keeps no copy of the schedule; the item keeps Scheduling’s reference and the queue shows when it publishes. The planner never publishes. An existing active publication schedule on the entry is never replaced.

The due time is the moment the draft was ready plus the delay. If Scheduling is missing, refuses or fails, the draft stays as it is and the item goes to Needs review with Retry scheduling. Temporary Scheduling failures, such as a timeout or an unreachable service, are retried automatically first. Retry scheduling asks Scheduling again with a new request; when the planned time has already passed, the delay counts from the retry. If an answer was lost after Scheduling accepted it, the planner asks again with the same request and gets the same schedule back, so a draft is never scheduled twice.

If a person changed the draft after the planner saved it, nothing is scheduled. The planner checks before it asks, and Scheduling refuses (draft_changed) when the entry’s current draft is not the saved version. The draft stays as the person left it and the item waits in Needs review with “The draft changed after it was saved. Schedule it from the entry.” Open the draft and schedule it there. Retry scheduling schedules only while the current draft is still a version the planner saved.

Run now starts a separate run at once. It does not move the automatic schedule. A plan has one live run at a time, and Run now is refused while one is working. An automatic run that falls due while a Run now run works waits; when that run ends, one automatic run starts.

Each run keeps the plan version, the accepted Site Brief version and the AI model it started with. A Site Brief accepted while a run works does not stop that run: it finishes with the version it started with, and the next run uses the new one. Work is stored before each model call, and the state survives restarts.

The plan screen shows the next run before you turn it on: when it would start, how many items it makes, what happens to a draft, and the topics in the order it will try them.

Dee Wan uses the admin Worker’s existing every-minute trigger. There is no separate cron per plan or topic. Each minute it:

  • visits up to 8 sites, starting at a different site every minute so none is always last;
  • on each site, finds up to 5 plans whose next run is due and starts their automatic runs, after the checks in AI credit;
  • advances each active run by one stage under a 5-minute lease, at most 8 stages in total per minute;
  • re-reads the owner’s permission, the content model and the field mapping before each stage;
  • picks up a stage whose worker stopped once its lease runs out, from the last saved checkpoint.

The plans list shows each plan as Not scheduled, Active, Due now, Running or Paused, with the reason a plan waits and the result of its last run.

Enabling a cadence is one explicit action. Later runs need no new confirmation. Choose daily, weekly or monthly, a time and a timezone.

  • Weekly runs on a weekday. Monthly runs on a day from 1 to 28.
  • A time that does not exist on a day the plan fires is refused, so a daylight-saving gap never skips a run silently.
  • A time that happens twice needs your choice: The first time or The second time.
  • A missed run becomes one due run. The planner never makes up every missed occurrence.
  • The next run is always the next occurrence after now.
  • Pause plan stops new automatic runs and stops active runs of that plan from advancing. A stage already working when you pause finishes and is kept; nothing after it starts. Pause keeps the setup, history and drafts. Resume plan continues the paused run where it stopped and works out the next occurrence from now.

The person who enables a cadence becomes the owner of the plan. The plan displays its owner.

A run spends the site’s hourly AI credit, 250 calls an hour unless the installation sets another limit. One model call spends one unit. A retry spends again.

One item uses up to 8 calls: one to find the idea (up to 2 more when re-angling), then research, outline and draft, and up to 2 repairs. The planner reads the remaining credit without spending it.

Before an automatic run starts, the planner checks, in this order: no other run of the plan is working, the content model and field mapping still fit, the owner’s permission, the daily item limit, the site’s active-run limit (2), a provider wait, and at least 8 units of credit left. If any check fails, no run or item is created, and the plan shows a plain reason. When the owner lacks permission, the plan waits for its next occurrence. For the other checks, the planner tries again the next minute. Run now applies the same checks and answers with the reason.

You see the per-run and per-day limits and the credit before you turn a cadence on.

  • A temporary provider or fetch failure is retried at the same stage up to 3 times, with increasing delays. A rate-limit answer also holds back the site’s runs.
  • A stage that crashed is picked up again after 5 minutes.
  • Invalid output, failed checks, exhausted repair attempts, a conflict, lost permission or a refused source stop that item with a specific reason. The run goes on with the others and ends as partial.
  • Retry continues from the last saved stage in the same run and topic. If the run had finished, it is reopened, never replaced. It is refused while another run of the plan is live.
  • A retried save returns the entry saved before, and a retried hand-off returns the schedule made before, so retries never make a second draft or schedule.
  • Cancel stops an item. Work in flight is thrown away. A draft already saved is kept and stays linked. A scheduled item cannot be cancelled here, because only Scheduling can withdraw its schedule.

The plan owner is checked again at every stage, before every write and every outside call: the account exists, belongs to the site and is allowed ai:generate, and can create entries of the target model (and update them when the plan revises, has more than one language or creates images).

If the owner loses any of this during a run, running items become Blocked with the reason and the run stops. If it is lost before a due run, no run starts, the plan shows the reason and moves to its next occurrence. The cadence stays on in both cases. Once the owner’s permission is back, the next due run starts by itself; nobody has to turn the cadence on again. Drafts and evidence stay. Pause plan is the way to stop automatic runs. There is no hidden automation account.

When you act on an item yourself, you act as yourself, and the owner does not change.

The Queue groups items by what you need to do.

Group States
Needs you Proposed, Needs review, Blocked
In progress Approved, Running
Ready Draft ready, Scheduled
Done Done, Cancelled

An item becomes Done when its own language is live. The queue and the background step both notice this.

Each row shows the title, state, stage (for example Writing, Checking, Saving draft, Scheduling), the content type it saves to, the language, the plan, the topic, whether the run was Automatic or Manual, when Scheduling publishes it, the reason it stopped, the next step, and a link to the draft once one is saved.

An item shows its stage, target, language, sources, compared duplicates, issues, attempts, and its draft or schedule. Actions:

  • Approve a proposed item.
  • Edit the title, angle, intent or keyword of a proposed or review item.
  • Run a proposed or approved item. It joins the plan’s active run, or gets a run of its own with no discovery.
  • Retry a review or blocked item. After a failed hand-off it reads Retry scheduling.
  • Cancel item an item that is not scheduled or finished.
  • Open draft for the saved entry.
  • Pause plan and Resume plan on the plan, and Turn on automatic runs to enable the cadence.

Generate ideas asks for 5 to 7 ideas at once, one per language, as proposed items. It writes no draft. Repeating the same request returns the same items.

The planner keeps plans and their versions, topics, sources, runs, items, the claims, evidence excerpts, issues, comparisons and attempts of each item (the last 20 attempts), and a stage checkpoint of at most 64 KiB. Planner records belong to one site.

It does not keep the full text of fetched pages or the prompts it sent.

Planner records are editorial records of the site, not telemetry. Settings → History lists each planner save as “Draft saved by the Planner”. Site copy and site history transfer do not carry them.


Unreleased / pre-MVP; no stable version
Source revision: fe23db481c422b40e317b92fc98116b4c0c26a87 (modified checkout)
Build date (UTC): 2026-10-18T09:22:34.630Z
Upgrade target: unavailable: modified checkout. Release notes