agents · 2026-05-24

How to Prevent AI Agents from Publishing Drafts by Accident

A practical checklist for preventing AI agents, static-site builds, CI jobs, RSS feeds, and sitemaps from publishing unfinished drafts.

AI-assisted: this article was produced with AI assistance and editorial quality gates.

How to Prevent AI Agents from Publishing Drafts by Accident

A draft leak does not need a dramatic failure. A writer agent saves a Markdown file in the wrong folder. The build script treats that folder as public. The sitemap and RSS feed include the page. A deploy job uploads the result. Now an unfinished article has a URL.

No one had to mean harm. The system made the unsafe path easy.

If AI agents help you publish technical content, draft safety should be part of the release process. Do not rely on a prompt that says "do not publish yet." Do not rely on one frontmatter field. Put several boring controls between a draft and production.

This article is not a full content pipeline. It focuses on one failure mode: unfinished files becoming public URLs. It is operational publishing guidance, not legal advice, security policy, or a complete SEO recovery plan.

AI-assisted disclosure: this article was produced from a planner brief and source-backed research packet, then reviewed for factual accuracy, editorial quality, SEO usefulness, and AI-tone issues before publication.

The failure mode: a draft becomes a URL

Most content sites have a public content path: a directory, CMS collection, database flag, or build query that means "turn this into a page." In an Astro site, for example, content collections and build code decide which files become generated output. Other static-site generators have their own conventions, but the risk is similar: the build follows code and file placement, not private editorial intent.

That matters when agents can write files.

A common unsafe sequence looks like this:

Writer agent creates article
  -> saves it under content/agents/
  -> sets status: draft
  -> generator accidentally includes all files in content/agents/
  -> build creates HTML, sitemap, and RSS entries
  -> deploy uploads dist/
  -> unfinished article is live

The mistake is not only the status: draft bug. The bigger mistake is giving the draft only one layer of protection.

Do not trust one control

Single controls fail in ordinary ways.

Control How it fails
Prompt instruction A later agent run gets a shorter prompt, ignores context, or writes to the wrong path.
status: draft The generator does not filter it, or a future refactor breaks the filter.
Human review checklist The reviewer checks prose but misses generated sitemap or RSS output.
Preview deployment A preview is treated as approval and later promoted without checking production.
Git push The repository is correct, but the host serves stale output or a fallback page.

The safer pattern is layered publication control. A draft should have to pass through several gates before it becomes public.

Layer 1: keep working files outside public content paths

Start with directory discipline.

content/briefs/       planner briefs, never public articles
content/research/     research packets and claim maps, never public articles
drafts/agents/        unfinished agent article drafts, never public articles
content/agents/       accepted published articles only
src/generated/        generated public article indexes

This is simple, but it catches many mistakes. If a writer agent creates an unfinished article, the safe default location is drafts/agents/, not content/agents/.

Path isolation is not a substitute for build filtering. It is the first gate. If someone accidentally writes status: published in a draft file, the path should still keep it out of public output.

Layer 2: filter by both path and status

The generator should agree with the directory rule. It should include only files from known public section directories and only when the article is approved for publication.

Treat a file as publishable only when both conditions are true: it lives in an approved public content directory, and its frontmatter status is published.

A simple rule looks like this:

publishable_articles = files
  .from(["content/agents", "content/tools", "content/automation"])
  .where(frontmatter.status == "published")
  .where(frontmatter.slug is present and unique)
  .where(required source and disclosure fields exist)

This rule intentionally excludes content/briefs/, content/research/, and drafts/, even if a file inside one of those paths contains section: agents or status: published by mistake.

The build should use the same definition of "publishable" for every public surface:

  • article pages;
  • section indexes;
  • sitemap files;
  • RSS feeds;
  • generated JSON data;
  • internal-link checks.

If those surfaces use different filters, one of them can leak a draft.

Layer 3: test the leak cases

Write tests for the cases you are afraid of. Do not test only the happy path.

File location Status Expected public? Why
content/agents/example.md published Yes Accepted article path and accepted status.
content/agents/example.md draft No Public path, but not accepted status.
drafts/agents/example.md published No Draft path is never public.
content/briefs/example.md published No Brief path is never public.
content/research/example.md published No Research path is never public.
content/briefs/example.md no frontmatter No Non-article artifacts should not become pages.

The useful check is not just "does the build pass?" Check the outputs that readers and crawlers see:

- generated article data does not contain the draft slug;
- dist/ does not contain a draft article page;
- section index does not link to the draft;
- RSS does not contain the draft title;
- sitemap does not contain the draft URL.

GitHub Actions can run these checks on pull requests and pushes. Protected branches and required checks can make it harder to merge a content change that fails them. You can use other CI systems, but the rule is the same: publication safety should be tested before release.

Layer 4: separate agent permissions

Agents should not all have the same permissions. One agent can play multiple roles in a small project, but the workflow should still separate writing, review, acceptance, and deployment.

Role May write May move to public content May deploy Must produce
Planner Briefs No No Brief with scope and acceptance criteria.
Researcher Research packets No No Source list and claim map.
Writer Drafts No No Draft outside public paths.
Fact-checker Review notes No No PASS, REQUEST_CHANGES, or BLOCK.
Editorial reviewer Review notes No No Usefulness, SEO, compliance, and anti-AI-tone verdict.
Acceptance Final article move after approval Yes Maybe CI output and release checklist.
Deploy operator Build output and deploy metadata No content edits Yes Production verification log.

OWASP's LLM guidance is relevant here because tool-using agents can take actions outside the chat window. NIST's AI Risk Management Framework is useful as a framing device, not a certification claim: identify the publishing risk, test the controls, and manage what remains. For publishing, that translates into a practical rule: a writer agent should not be able to approve and deploy its own draft.

Anthropic's guidance on building effective agents also argues for simple, composable patterns before adding more autonomy. Draft safety is a good place for explicit paths, narrow permissions, and repeatable checks.

Layer 5: make release a deliberate move

Publication should require a visible move from draft storage into public content storage.

Before moving a draft into content/<section>/, run this checklist:

[ ] Brief exists and defines the article angle.
[ ] Research packet exists and source URLs are reachable.
[ ] Fact-check verdict is PASS or requested factual edits are resolved.
[ ] Editorial review includes a separate anti-AI-tone pass.
[ ] Frontmatter has title, description, date, slug, section, tags, sources, ai_assisted, affiliate_disclosure, risk_level, and status.
[ ] Original-value requirement from the brief is present.
[ ] Internal links are natural and correct.
[ ] Draft file is moved from drafts/<section>/ to content/<section>/ only after approval.
[ ] CI or the equivalent full build check passes.
[ ] Generated article data, sitemap, RSS, and section index contain only intended published articles.

This release move is the handoff from writing to acceptance. It is the content version of a deployment gate.

If you use the pattern from the planner-executor-reviewer workflow, the planner defines these checks, the executor prepares the draft, and the reviewer blocks weak output. If you use a larger research-writing-review agent pipeline, the same release checklist sits after fact-check and editorial review.

Layer 6: verify the live body, not only HTTP 200

A successful local build does not prove production is showing the new content. A custom domain can route to old output. A fallback page can return HTTP 200. A feed or sitemap can also be generated or cached differently from the article page.

After deployment, check response bodies.

Generic version:

curl -L https://agents.example.com/new-slug/ | grep "Expected H1"
curl -L https://agents.example.com/ | grep "new-slug"
curl -L https://agents.example.com/rss.xml | grep "Expected H1"
curl -L https://agents.example.com/sitemap.xml | grep "new-slug"

For a Cloudflare Pages direct-upload workflow, the deploy command may upload prebuilt output. That makes build-time configuration important. The production check should confirm the exact slug and title in the deployed body, not just that the deploy command exited successfully.

For preview deployments, use the preview URL for review. Do not treat it as final production verification unless that is the URL readers and crawlers will actually use.

What to do if a draft leaks

If a draft is already public, keep the response small and specific.

  1. Remove the draft from the public content path or change the generator filter.
  2. Build and deploy the fix.
  3. Verify the article URL, section index, RSS, sitemap, and generated data no longer include the draft.
  4. If search engines already indexed it, decide whether to return 404, redirect, or use removal/noindex handling based on the URL and risk.
  5. Add the missing regression test.
  6. Record what allowed the leak: path, status filter, CI gap, deploy permissions, or production verification gap.

Do not turn one leaked draft into an exaggerated SEO panic. Google's helpful content and spam policies are still relevant because public pages are evaluated as content. The immediate problem is simpler: readers may see unfinished work, feeds may distribute it, and the team now has cleanup to do.

The safe default

Use this default:

Planner creates brief.
Researcher creates source packet.
Writer creates draft outside public content paths.
Fact-checker verifies claims.
Reviewer checks usefulness, SEO, compliance, and AI tone.
Acceptance moves the approved draft into public content and runs CI.
Deploy operator uploads the build and verifies production bodies.

The system should make accidental publishing harder than deliberate publishing. If a draft can become public because one agent wrote to one folder, the workflow is not ready for unattended publishing.

Sources

Original value in this guide

  • draft leak safety layers
  • safe folder structure
  • draft leak regression test matrix
  • agent permission table
  • draft release checklist
  • production body verification commands

Sources