Skip to content
Article

How We Built an Autonomous Content Pipeline With a Human Publication Gate

Autonomy without a publication gate is just faster noise. Here is how we designed discover → summarize → generate as agent-runnable stages in Ansible, while keeping draft, pin, and publish as explicit human decisions.

Most teams that chase “AI content” discover the same trap: speed without judgment. Models can draft faster than editors can think, which is useful until the wrong sentence ships under your brand. The harder product question is not “can we automate writing?” It is “can we automate the work up to the decision to publish?”

That is the line we drew inside Ansible (our Symfony CMS and operations platform). Agents may discover, summarize, generate, attach heroes, and taxonomize. Humans keep the publication gate. Everything else is machinery built to respect that boundary.

TL;DR

We separated an autonomous content pipeline into stages that assistants can run over MCP—discover topics from engineering activity, summarize evidence, generate a draft, optionally create a hero—while publish, pin, and final voice remain human actions. Draft-first tools are the product. Auto-publish is not.

The problem the gate solves

Content systems fail in two opposite ways. Fully manual pipelines starve: good engineering stories sit in merge requests until someone has a free afternoon. Fully automatic pipelines flood: volume rises, voice flattens, and confidential details leak because nobody owned the last look.

A human publication gate is not nostalgia for slow marketing. It is an architectural constraint. If publish is a separate tool and draft is the default end state of automation, then every agent—scheduled or conversational—inherits the same safety property. You can scale discovery without scaling regret.

In our stack that constraint shows up as concrete API shapes. create_blog_post_draft creates drafts. publish_blog_post is a different call. CMS list filters expose Draft versus Published so operators can see the queue. Pinning is its own concern: authentic authority posts may be pinned after human review; volume posts stay unpinned. The gate is not a sticky note on a process doc. It is encoded in the tools assistants are allowed to call.

Architecture: autonomous stages, deliberate handoffs

The authentic, engineering-sourced lane is a three-stage CMS engine that agents invoke the same way a human would click through Blog Posts → Create → AI-Driven.

1. Discover

discover_gitlab_blog_topics starts async discovery against GitLab activity. With a project path it uses a deep prefetch on one repository; without one it runs a shallow pass across a ranked multi-repo set. Status tools poll until suggestions (or blocked suggestions) land. Activity scoring favors commit velocity, recency, and merged MR signal—not vibes from commit messages alone.

Daily automation adds a second discipline: project rotation. A cooldown window deprioritizes repositories that were recently featured so the pipeline does not turn one hot repo into a monologue. That is still autonomous, but it is autonomy with memory.

2. Summarize

summarize_blog_from_gitlab_topic takes a selected suggestion and produces an evidence-aware summary. The summarizer can re-fetch cited file paths so the brief stays grounded in the repository rather than in a single LLM hallucination of “what the team probably built.”

3. Generate

generate_blog_from_summary turns that summary into a CMS draft. Automation modes force draft status. Author resolution prefers the dominant committer on the topic when an employee match exists; taxonomy can be AI-selected from the live category and tag catalog. When hero generation is enabled, the same generation path can attach an editorial image and soft-fail if image generation fails—text draft first, artwork second.

For non-GitLab authority pieces, agents still use create_blog_post_draft with HTML or lossless TipTap JSON. That path is for planned theses and practitioner essays—not a shortcut around the GitLab engine when the story is commit-sourced.

Where humans must stay in the loop

Autonomy ends where accountability begins. We treat four decisions as human by default.

Idea selection. Discovery can propose; it should not decide the editorial calendar alone. Authority posts need a voice pass against positioning, confidentiality, and timing.

Publication. publish_blog_post exists so going live is intentional. Cache revalidation follows publish. The public site only surfaces published records. That split keeps marketing-site consumers honest about what is live.

Pinning. Pin support arrived as first-class CMS fields and MCP tools so authentic posts can be elevated without confusing pin with publish. Operators can toggle pins from the list; agents can set pin state—but authentic pin decisions stay on the human side of the house.

Confidentiality and naming. Pipelines that read private repositories can surface gated client work. The gate is where anonymization rules are enforced: percentages over logos, craft lessons over named accounts, no accidental NDAs in the hero caption.

Prospecting and newsletter tools follow the same philosophy elsewhere in Ansible: agents queue Gmail drafts or craft newsletter campaigns; humans send. The content pipeline is one instance of a broader pattern—agent mesh with human irreversible actions.

What we learned building it in Ansible

Shipping the pipeline taught us more about product boundaries than about prompt cleverness.

Draft-first is a feature, not a temporary caution. Early CMS work added explicit draft/published status and public APIs that only return published posts. Later MCP work extended create, update, publish, pin, taxonomy, and list tools around that model. When daily GitLab automation landed, it inherited forceDraft: true. The cron never “almost publishes.”

MCP turns the CMS into an agent runtime. Remote Streamable HTTP MCP on the Ansible backend lets Cursor and other harnesses authenticate as employees (OAuth) or as a system principal (API key). Blog tools attribute authorship to the actor. That matters: an autonomous pipeline without attribution becomes a ghostwriter with no audit trail.

Separate publish from create, and pin from both. PR-era work that added pin fields, MCP publish/update/pin/taxonomy tools, and later CMS status filters made the editorial queue operable. Agents and humans share one vocabulary: draft, published, pinned.

Lossless editing beats HTML round-trips for surgery. Read, contentJson, optimistic concurrency, HTML preview, and TipTap patch tools (PR #59) let agents revise without stomping concurrent human edits. Conflict codes beat silent overwrites.

Hero generation should soft-fail. AI heroes on the generation pipeline, regenerate-for-existing-posts, model upgrades, and finally optional generateHeroImage on create_blog_post_draft (PR #72, merged 2026-09-18 PT) all share one rule: missing art must not block a draft. Soft-fail keeps the gate focused on words and risk, not on waiting for an image API.

Rotation and taxonomy are editorial ops encoded as code. Seven-day project cooldown and AI taxonomy from the live catalog stop the pipeline from over-indexing one repo or inventing tags that do not exist. Agents list categories and tags; they do not invent IDs.

Volume and authority need different disciplines. External volume can enter through a webhook path. Authentic posts use the GitLab engine or deliberate draft creation, then human pin/publish. Mixing those lanes without discipline produces a homepage that looks busy and says nothing.

The agent mesh that makes the pipeline runnable

None of this works if the only UI is a browser modal. The MCP server exposes the same blog creation engine assistants need: discovery status tools, summarization and generation polls, draft create/update, taxonomy, media upload, publish, and pin. Adjacent tool families—tickets, prospecting, newsletter—teach the same habit: propose and prepare autonomously; confirm irreversible steps.

That is what we mean by an agent mesh. Specialists do not share one mega-prompt. They share a CMS and a contract. Blog agents mine repositories and draft. Other agents handle ops or outreach. Humans remain the publication authority for brand-bearing surfaces.

A practical pattern you can copy

  1. Encode draft as the default terminal state of automation.

  2. Expose publish as a separate, auditable action.

  3. Give agents discovery and generation tools that match your real CMS engine—not a parallel shadow CMS.

  4. Soft-fail optional enrichment (heroes, taxonomy guesses) so the gate stays about judgment.

  5. Pin and taxonomize deliberately so authority and volume do not compete for the same shelf.

  6. Attribute every mutating call to an employee or system principal.

If your stack cannot say “the agent cannot publish,” you do not have a gate. You have a hope.

Where this goes next

We are still tightening voice passes, evidence packets, and scheduling around the same spine. The interesting work is no longer “can an LLM write a post?” It is whether a marketing operating system can keep humans decisive while agents keep the queue full of grounded drafts.

If you are designing a similar system—or want help standing up an MCP-backed agent mesh around your own CMS—start with the architecture, not the model name.

Explore how we approach this in practice on our AI agent orchestration solution page, or talk with us about an AI workflow for your team.

Drag to pan. Use +/− or Ctrl/Cmd + scroll to zoom. Pinch to zoom on touch devices.