vendor-asset-publisher
Use when a Partner Enablement lead, Partner Marketing Manager, or Channel Ops user wants to produce a partner-facing document (one-pager, battlecard, FAQ, pricing summary, integration guide) from the vendor’s own knowledge sources and publish it into the Introw asset library over MCP, link an existing page or video as a URL asset, refresh an asset that already exists, or organise the library itself (create, rename, move, or archive folders). Trigger phrases include “write a one-pager for our partners”, “create a battlecard on <competitor>”, “publish this PDF to the asset library”, “add this deck to the partner portal”, “add this YouTube video as an asset”, “update the pricing one-pager”, “replace that file with the new version”, “create a folder for X”, “reorganise the asset library”, “archive that folder”.
Built for: Partner Enablement Manager · Partner Marketing Manager · Channel Ops
Workflow: Brief + the vendor’s own knowledge sources → check what exists with list_assets + list_asset_folders → author the document → export as PDF → upload via create_asset_upload → upsert_asset over MCP with folder, categories, and audience → keep the tree tidy with upsert_asset_folder → iterate by replacing the file in place
SKILL.md
---
name: vendor-asset-publisher
description: Use when a Partner Enablement lead, Partner Marketing Manager, or Channel Ops user wants to produce a partner-facing document (one-pager, battlecard, FAQ, pricing summary, integration guide) from the vendor's own knowledge sources and publish it into the Introw asset library over MCP, link an existing page or video as a URL asset, refresh an asset that already exists, or organise the library itself (create, rename, move, or archive folders). Trigger phrases include "write a one-pager for our partners", "create a battlecard on <competitor>", "publish this PDF to the asset library", "add this deck to the partner portal", "add this YouTube video as an asset", "update the pricing one-pager", "replace that file with the new version", "create a folder for X", "reorganise the asset library", "archive that folder".
---
# Agentic Asset Publisher (Vendor)
**Audience**: Vendor, **claude.ai Introw** MCP.
**Use case**: Enablement Support.
## When to use this skill
Use when the user wants partner-facing content to exist in Introw without authoring it inside Introw: write the document here (from their knowledge sources, in their voice), then create or update the asset over MCP so it lives in the asset library, is searchable by the partner-facing AI agent, and can be surfaced in partner experiences.
**Sample prompts that fire this skill:**
- "write a one-pager our resellers can send to prospects"
- "create a battlecard against Competitor X for our partners"
- "turn our pricing page into a partner FAQ and publish it"
- "publish this PDF to the asset library under Sales"
- "add this Loom walkthrough as an asset for Acme only"
- "the pricing changed, update the one-pager"
## Why this matters
Partner content dies in two places: never written, or written and never filed. Partners then ask a CAM for a battlecard that exists in someone's Drive. Authoring here and publishing over MCP closes both gaps in one motion: the document is grounded in the vendor's real docs and data, and it lands in the library the partner portal and the AI partner-support agent both read from, with a category, a folder, and an owner. Iteration is cheap: replace the file in place and the asset keeps its id, link, view history, and version history.
## The five MCP tools
| Tool | Kind | What it does |
| --- | --- | --- |
| `Introw:list_assets` | read-only | Lists assets (assetId, name, description, fileName, mimetype, `type: FILE` or `URL`, folder, categories, isPublic, viewCount, timestamps) and the library's folders. Source of `assetId` for updates and `folderId` for filing. Filter with `query`, `folder`, `partnerId`. |
| `Introw:list_asset_folders` | read-only | The folder tree: folderId, `name`, `path` (readable location such as "Sales/Battlecards"), parentFolderId, partnerId, categories, `assetCount` (assets directly inside), `subfolderCount`, and `archived` + `archiveReason` with `includeArchived`. Filter with `query`, `parentFolder` (that folder's subtree), `partnerId`. |
| `Introw:create_asset_upload` | mutation | Pass the `fileName` **including its extension** (the extension decides the content type). Returns `uploadUrl` (presigned, 30-minute expiry, writes exactly one org-scoped object), the `contentType` that PUT must send, `uploadPageUrl` (drag-and-drop page for the same slot, for environments that cannot PUT a file), and the `uploadKey` to pass to `upsert_asset`. Nothing appears in the library until `upsert_asset` is called with the key. |
| `Introw:upsert_asset` | mutation | Omit `assetId` = create (requires `name` + exactly one source). Provide `assetId` = update; only the fields you pass change. Sources: `uploadKey` (from `create_asset_upload`), `fileUrl` (public https file, copied into Introw's storage), or `url` (a URL asset: page, video, or hosted doc that stays where it is). Settings: `description`, `folder`, `categories`, `partnerId`, `isPublic`. On update, passing any source REPLACES the file. |
| `Introw:upsert_asset_folder` | mutation | Omit `folderId` = create (requires `name`; `parentFolder` nests it, `partnerId` puts it in a partner's library). Provide `folderId` = update: `name` renames, `parentFolder` MOVES the folder with everything inside it, `categories` replaces its tags, `archived: true`/`false` archives or restores the folder **and its entire contents**. |
Two neighbouring tools are worth knowing: `Introw:find_relevant_content` searches what is already in the knowledge base (use it before writing something that exists), and `Introw:search_partners` resolves a `partnerId` when the asset is for one partner only.
## Process
### Step 1: Scope the asset
Confirm before writing:
- **Audience**: which partner type and role (a reseller's seller and an SI's consultant need different documents). One partner only, or the whole network?
- **Format and length**: one-pager, battlecard, FAQ, guide. Default to one page unless the user asks for more.
- **Sources**: which connected knowledge to draw from, such as docs sites, Notion, Confluence, Drive, the product docs, the website. Never fabricate; every claim traces to a source.
- **Filing**: which folder and categories, and whether it should be publicly shareable.
### Step 2: Check what already exists
Run `Introw:list_assets` with a `query` on the topic, and `Introw:find_relevant_content` for the same question. If a close match exists, propose updating it (Step 8) instead of adding a near-duplicate.
Then run `Introw:list_asset_folders` to see how the library is organised and where this belongs. Reuse the folder and category names already in use; a library with "Battlecards", "battle cards", and "Competitive" is a library nobody browses. `assetCount` and `subfolderCount` show you which folders are actually used and which are empty shells.
### Step 3: Write the document
- **Partner-facing voice**: written for someone selling or delivering the vendor's product to their own customer, not for internal staff.
- **Grounded**: real product names, real pricing, real integration steps, from the sources. Cite where each section came from in your summary to the user.
- **Skimmable**: short sections, a clear headline, tables over paragraphs for comparisons, an explicit "what to do next".
- **On-brand**: pull logo, colors, and typography from the vendor's site or brand assets if the format supports it.
- **No internal-only content**: partners download this. No unreleased roadmap, no internal margins, no customer names without permission.
### Step 4: Export as a PDF (or the format the user asked for)
PDF is the default: it previews inline in the portal and its text is indexed for the AI agent. Office files (DOCX, PPTX, XLSX) also work and get a converted PDF preview. Images and video are fine too. Keep it under 2 GB.
### Step 5: Hand Introw the file
Preferred, no hosting needed:
1. `Introw:create_asset_upload` with the `fileName` including its extension, for example `acme-partner-one-pager.pdf`.
2. HTTP PUT the raw bytes to `uploadUrl` with the returned `contentType` as the `Content-Type` header, for example `curl --fail -T one-pager.pdf -H "Content-Type: application/pdf" "<uploadUrl>"`. The header must match exactly or the signature is rejected. The URL expires after 30 minutes; if it lapses, request a new one.
3. Pass the returned `uploadKey` to `upsert_asset` in the next step.
Fallback, if this environment cannot make HTTP requests with a file body (chat assistants): the same response includes `uploadPageUrl`. Give the user that link together with the downloadable file. It is a drag-and-drop page that writes into the same slot and requires them to be signed in to Introw in this organisation (they are redirected to log in if needed). Ask them to say "done", then continue with the `uploadKey`; if `upsert_asset` reports that no file has landed yet, wait and retry.
Two shortcuts skip the upload entirely:
- **`fileUrl`**: a publicly downloadable https file. Introw copies it into its own storage, so the source only needs to live until the call.
- **`url`**: a page, video, or hosted doc that should stay at its own location (YouTube, Loom, Vimeo, Vidyard, Google Docs / Slides / Sheets, Calendly, or any https page). Introw stores the link and embeds it, and nothing is copied, so that URL must stay live and publicly reachable.
Never pass local file paths or base64 to `upsert_asset`.
### Step 6: Publish it
1. Recap every setting (name, description, folder, categories, partner scope, public link) and get explicit approval. This is a write.
2. `Introw:upsert_asset` with no `assetId`, passing the source and settings:
- **`folder`**: a `folderId` from `list_assets`, or a path such as `Sales/Battlecards` (missing folders are created, existing ones reused). `/` means the library root. The response lists any folders it created, so you can report them.
- **`partnerId`**: only when the asset is for one partner's private library. Omit it for the shared library every partner can see.
- **`categories`**: reuse the org's existing category names.
- **`isPublic`**: only when the user explicitly wants a link that works without signing in. Default off.
3. Report the `assetId` and the `assetUrl` from the response so the user can open it in Introw. `status: "created"` means it is live in the library; previews and AI-search indexing finish in the background, so a preview can take a moment.
If the response comes back `status: "already_exists"`, that exact file or link is already an asset. Do not retry with a new upload; use the returned `assetId` to update it instead. For a URL asset this is checked per folder, so filing the same link in a second folder on purpose still works: pass the other `folder`.
### Step 7: Keep the library organised
Folder work is a first-class part of publishing, not an afterthought. `Introw:upsert_asset_folder` covers it:
- **New section**: create a folder, optionally nested (`parentFolder` takes a folderId or a path such as `Sales/Battlecards`, creating missing levels). A folder that already exists in that place is reused, not duplicated.
- **Rename or re-tag**: `folderId` + `name` or `categories`.
- **Reorganise**: `folderId` + `parentFolder` moves the folder **with every subfolder and asset inside it**. Pass `/` to move it to the top level. A folder adopts its new parent's library, so moving between the shared library and a partner's changes who can see the content. Say that out loud before doing it.
- **Retire a section**: `archived: true` archives the folder and everything inside (with an optional `archiveReason`). Partners lose access immediately and the AI agent stops answering from those documents. `archived: false` restores it; if the name was taken again in the meantime, Introw suffixes the restored folder and tells you.
Confirm any move or archive with the user first and report the counts the tool returns (`archivedAssetCount`, `archivedFolderCount`), so they know how much content it touched. Prefer archiving over asking someone to delete: it is reversible.
### Step 8: Iterate, update settings or replace the file
- **Settings-only change** (rename, description, categories, folder, public link): `upsert_asset` with `assetId` and just those fields. The response lists what actually changed, and returns `status: "unchanged"` when nothing differed.
- **Content change**: upload the new file (`create_asset_upload` → PUT → new `uploadKey`), then `upsert_asset` with `assetId` + that `uploadKey`. This replaces the file **in place**: same asset, same link, view history kept, and the previous version stays in the asset's version history so it can be restored in Introw. In-portal previews and AI-search content regenerate in the background. **Always confirm with the user before replacing**, since every partner sees the new file immediately.
- **Swapping types is allowed**: passing `url` to an asset that was a file turns it into a URL asset, and vice versa.
- Omitting `folder` or `partnerId` on an update leaves the asset where it is. Moving an asset out of a partner's library back into the shared one is done in Introw.
## Output format
- **Brief recap** (pre-write, for sign-off): audience, format, sources, filing plan.
- **The document itself** plus a short content summary and where each section came from.
- **Publish receipt**: `assetId`, `assetUrl`, folder (and any folders created), categories, audience (shared library or which partner), public link on or off.
- **Reorganisation receipt** (when folders changed): what moved or was archived, and how many assets and subfolders it affected.
- **Distribution note**: what still has to happen for partners to see it in the portal (see the guardrail below), and the phrasing to use to update it later.
## Guardrails & PRM best practice
- **Knowledge-sourced, never fabricated.** Every claim traces to the vendor's real docs or data; cite the source. Partner-facing collateral is one forward away from being customer-facing.
- **Confirm before every write.** Settings recap before creating; explicit confirmation before replacing a file, because partners see the new version immediately.
- **The library is not the portal.** Publishing puts the asset in the asset library and makes it searchable for the AI partner-support agent, but it does not add it to a specific portal tab or partner experience. Placing it in an asset hub component, or linking a partner-specific asset into a partner experience, is done in Introw. Say so in the receipt rather than implying partners will see it in their portal navigation right away.
- **Check for duplicates first.** `list_assets` plus `find_relevant_content` before writing. Updating the asset partners already bookmarked beats publishing a second one.
- **Reuse the existing taxonomy.** Existing folder names and categories over new ones, checked with `list_asset_folders`. Do not invent a parallel structure, and do not create a folder per asset.
- **Moving and archiving folders is bulk work.** Both act on everything inside the folder: a move relocates every asset in it (and can switch which library, so which partners, they belong to), and archiving hides them all and removes them from the AI agent's knowledge base. Confirm first, then report the counts the tool returns.
- **Archive, never ask for deletion.** Archiving is reversible (`archived: false`) and keeps the audit trail; there is no delete in this skill by design.
- **`isPublic` is a real decision.** It creates a link that works without signing in. Default off; only enable when the user asks, and never for pricing or anything partner-confidential.
- **Partner-specific means partner-specific.** With `partnerId` set, only that partner sees it. Use it for negotiated pricing or one partner's plan, not as a filing shortcut.
- **URL assets depend on the source staying up.** A link that dies is a broken asset. Prefer uploading a file for anything the vendor controls and wants to keep.
- **Permissions.** Anything that touches the shared library requires the connected Introw user's `assets_write` permission: publishing there, and also editing or moving an asset or folder that lives there, even when the call names a partner. If the tool reports it is missing, surface that plainly (an admin grants it) instead of retrying, or scope the work to a partner's own library if that is what the user actually wanted.
- **Cross-skill handoff.** What to write should come from real gaps: `vendor-support-content-gap-detector` (recurring partner questions) or `vendor-content-radar` (market and release signals). Per-partner branded variants of a published asset: `vendor-cobranded-collateral-generator`. If the content is training rather than reference, build a course instead with `vendor-scorm-course-builder`. To nudge partners toward the new asset, use `Introw:create_partner_task` or an announcement.
Drop this file into
.claude/skills/vendor-asset-publisher/SKILL.md in your repo and Claude Code triggers it on the prompts in its description. Or run the same play in plain language from Claude, ChatGPT, Slack, Teams, or your CRM through Introw’s MCP server: every action writes back to your CRM source of truth.