Publish and distribute (CMS + KB + Conv)
When a new piece of content goes live (product update, policy change, public-facing FAQ), three things should happen in lockstep: the canonical version publishes in the CMS, an agent-searchable copy goes into the KB, and a notification message lands in the right conversation channel.
This is a playbook — it composes per-module skills.
TL;DR
- Author + publish the entry per
skill://cms/publish-entry. - Mirror to KB:
kb_create_documentwith the entry's body in the appropriate space. - Announce in a conversation:
conv_send_messageto a designated internal channel (or per-customer channels for big news).
Prerequisites
- The CMS collection and entry exist.
- The KB has a relevant space (
kb_list_spaces); if not, runskill://kb/create-first-space. - The conversation channel for announcements exists (
conv_list_channels).
Step 1 — author + publish in the CMS
Follow skill://cms/publish-entry end-to-end.
After it completes, you have:
- An entry with
status: 'published'and a stampedpublishedAt. - The latest
versionnumber. - A canonical URL the delivery API will serve from.
Read it back to capture the data you'll mirror:
{ "name": "cms_get_entry", "arguments": { "id": "<entryId>" } }
Hold onto the data payload — relevant fields are typically title, a public-facing summary or excerpt, and a slug for cross-linking.
If the entry is multi-locale, decide which locale you mirror to KB. The default locale is the safe default.
Step 2 — mirror to KB
The CMS is the canonical source; the KB copy exists so agents can find it via kb_search. Don't try to keep them perfectly in sync — the KB copy is "good enough" search bait that points back to the CMS.
{
"name": "kb_create_document",
"arguments": {
"spaceId": "<spaceId>",
"title": "<entry.data.title>",
"body": "<entry.data.title>\n\n<entry.data.summary or first ~500 words of body>\n\nFull article: <canonical CMS URL>",
"tags": ["cms-mirror", "<collection-slug>", "<entry-slug>"],
"public": true
}
}
Conventions worth following:
- Tag the document with
cms-mirrorso it's distinguishable from native KB articles in audits. - Include the canonical CMS URL at the bottom so an agent citing this article can link humans to the real version.
- Set
public: trueonly if the underlying CMS entry is public.
If you're updating an already-published entry, the simplest pattern today is delete + recreate the KB mirror — kb_create_document doesn't have an upsert, and there's no built-in "get document by tag" lookup. Track the kb document id alongside the cms entry id in your own state if you want clean updates.
Step 3 — announce in a conversation
Pick the channel for the announcement. For internal: a dedicated conv channel for the team. For customer-facing: a designated broadcast channel (note: there's no "broadcast to all conversations" tool — fan-out is per-conversation).
{
"name": "conv_list_channels",
"arguments": {}
}
Then send the announcement message into a chosen conversation. If it's a fresh announcement thread:
{
"name": "conv_start_conversation",
"arguments": {
"channelId": "<channelId>",
"subject": "Published: <entry.data.title>"
}
}
{
"name": "conv_send_message",
"arguments": {
"conversationId": "<convId>",
"body": "Just published: **<title>**\n\n<one-line summary>\n\nCMS: <canonical URL>\nKB mirror: <kb document id or search hint>"
}
}
For widget or email channels, the message is delivered to the recipient like any other; for an internal-only channel that exists just for announcements, this becomes a thread the team can react to.
Step 4 — verify
{ "name": "kb_search", "arguments": { "query": "<title>", "limit": 5 } }
The mirrored doc should surface within ~5 seconds (embedding pipeline is async).
{ "name": "cms_search", "arguments": { "query": "<title>", "limit": 5 } }
The published entry should be there too. If both surface and the announcement was sent, the publish + distribute step is complete.
What NOT to do
- Don't try to make the KB copy authoritative. The CMS is the source of truth. The KB copy is search bait; it can drift, that's fine.
- Don't mirror long-form articles verbatim into KB. Embeddings and FTS work better with concise, focused chunks. Either summarize, or split by H2 per
skill://kb/import-from-google-docs. - Don't broadcast announcements by sending into every customer's conversation. There's no "broadcast" primitive; fan-out is opt-in by your script. Decide explicitly which conversations receive the message.
- Don't update the KB mirror in place by re-using the same doc id. Today the cleanest path is delete + recreate (or just create a new mirror and let the old one age out via tag).
Related
skill://cms/publish-entry— the publish half.skill://kb/import-articles-in-bulk— bulk mirroring for catch-up imports.skill://conv/setup-email-and-widget-channels— making sure the announcement channel exists.