Vyrade Labs put agentic AI to a hands-on test against a very specific editorial workflow: keep the article text unchanged, extract image suggestions buried in the copy, generate visuals in Napkin, export PNGs/WebP, insert them exactly where the prompts sit, and publish to WordPress—fully automated. “Agent mode” alone couldn’t finish the job (browser restrictions, no Napkin API), so we built a workflow automation that uses headless Playwright + n8n to generate/export Napkin-style images and publish via the WordPress REST API. Vyrade planned the workflow and hardened it with rationale, export, and reliability layers (confidence/coverage, wiring to n8n).
The Exact Task We Gave to GPT Agent Mode
- Use the final article as-is (no text edits).
- Turn the in-line “Image #…” suggestions into Napkin prompts.
- Generate Napkin-style visuals and export PNGs/WebP.
- Place the images exactly at those markers.
- Deliver a WordPress-ready document (images embedded, alt text included).
Why this is tricky for an AI agent alone: no public Napkin API; browser downloads/clipboard and extensions are often blocked; precise placement in the editorial HTML is unforgiving.
What We Tried First: Agentic AI
We began with agentic AI (a GPT agent) to control the browser, log into Napkin, paste prompts, generate visuals, and export PNGs. In a constrained environment, the agent hit three walls:
- Exports blocked (download prompts never saved).
- Clipboard blocked (no reliable paste target).
- No extensions (so no snipping-tool add-on).
An agent can still help with planning and retries, but the last mile—“Export PNG” from Napkin’s UI—requires headless browser automation that captures the download event and persists the file.

The Working Solution: Automating Napkin Visuals with Headless Playwright + n8n
We rebuilt the process as an end-to-end automation:
- Generate images in Napkin with headless Playwright
- Log in with env vars, paste each Napkin prompt, click Generate Visual, choose the first suitable visual, open Export, select PNG, await download, and
saveAs()
the file (Napkin-style look preserved). - Keywords: Playwright automation, headless browser automation, Napkin AI automation.
- Log in with env vars, paste each Napkin prompt, click Generate Visual, choose the first suitable visual, open Export, select PNG, await download, and
- Insert Napkin Visuals into Articles with Content Operations Automation
- Remove the literal “Image #…” lines and inject a
<figure><img/></figure>
block right there—no changes elsewhere. - Keywords: content operations automation, end-to-end automation.
- Remove the literal “Image #…” lines and inject a
- Publish via WordPress REST API
- Upload each PNG to Media, swap local
src
with the media URLs, create the post (Draft/Publish). - Keywords: WordPress REST API automation, WordPress automation, n8n workflows.
- Upload each PNG to Media, swap local
- Orchestrate with n8n
- Three Execute Command nodes: install deps → generate images → assemble+publish.
- Keywords: n8n, n8n workflows, Zapier/Make alternatives.

Where Vyrade Fits and Why It Matters
Vyrade is not the orchestrator. It’s a planner/composer with a reliability layer that turns ambiguous intents into exportable workflows (JSON) and recommends the right orchestration path (Zapier/Make/n8n), along with confidence & coverage and diagnostics. You then run the exported flow in your chosen tool.
- Product pillars: Contextual Discovery, Workflow Composer, Reliability Layer.
- Planner can suggest Zapier/Make/n8n and export with 1-click; secrets and retries included.
- Generic Workflow JSON artifact (nodes, edges, policies, metrics, authRefs) matches this use case.
- Reliability & validation: confidence/coverage on every recommendation; diagnostics toolkits; certification and versions.
In short: Vyrade plans and hardens the workflow, then exports it to n8n where it runs reliably.

Technical deep dive
1) Prompts (JSON)
[
{
"name": "image02_agents-vs-copilot-vs-rpa.png",
"prompt": "Mini comparison. Small table: Agents vs. Copilots vs. RPA (columns: Initiative, Context, Autonomy, Typical Use)."
},
{
"name": "image03_funnel-lift-points.png",
"prompt": "Value map. Funnel diagram labeling where each pillar adds lift (top/mid/bottom funnel). Alt: Conversion lift points from prioritization, personalization, insights, and automation."
},
{
"name": "image04_tooling-patterns.png",
"prompt": "Landscape panel. 3-column infographic: CRM-native / Enablement suite / Autonomous SDR, with 2–3 bullets per lane. Alt: Agentic AI tooling patterns and when to choose each.\n\nCRM-native: Agentforce agents & copilots; SDR/AE workflows.\nEnablement suite: AI dialog simulators; content discovery; deal-risk cues.\nAutonomous SDR: Multi-agent outbound (research → personalize → multichannel → handle replies → book); 24/7; hand off qualified meetings."
}
]
2) Headless Napkin generator (Playwright, Node)
import { chromium } from "playwright";
import fs from "fs/promises";
import path from "path";
const EMAIL = process.env.NAPKIN_EMAIL, PASSWORD = process.env.NAPKIN_PASSWORD;
async function createVisual(page, text, outPath) {
// new napkin → paste text → generate → click first visual
await page.getByRole("button", { name: /\+ new napkin/i }).click();
const byPasting = page.getByRole("button", { name: /pasting my text/i });
const draftAI = page.getByRole("button", { name: /draft with ai/i });
if (await byPasting.isVisible()) await byPasting.click(); else if (await draftAI.isVisible()) await draftAI.click();
await page.getByRole("textbox").fill(text);
const gen = page.getByRole("button", { name: /generate visual/i });
if (await gen.isVisible()) await gen.click();
await page.locator("img[alt*='visual']").first().waitFor();
await page.locator("img[alt*='visual']").first().click();
// Export → PNG → wait for download → save
const dlButton = page.locator("button[title*='Download'], [data-test*='download']").first();
if (await dlButton.isVisible()) await dlButton.click();
await page.getByRole("button", { name: /^png$/i }).click().catch(() => {});
const [download] = await Promise.all([
page.waitForEvent("download"),
page.getByRole("button", { name: /download/i }).click()
]);
await download.saveAs(outPath); // Playwright saveAs() persists the file
}
(async () => {
const browser = await chromium.launch({ headless: true });
const ctx = await browser.newContext({ acceptDownloads: true });
const page = await ctx.newPage();
await page.goto("https://app.napkin.ai", { waitUntil: "networkidle" });
// email/password sign-in flow …
// loop over prompts.json and call createVisual(...)
await browser.close();
})();
3) Assembler (replace “Image #..” lines with real images)
import fs from "fs/promises";
const map = {
2: { file: "./out/image02_agents-vs-copilot-vs-rpa.png",
alt: "Agents vs Copilot vs RPA comparison" },
3: { file: "./out/image03_funnel-lift-points.png",
alt: "Funnel lift points across the funnel" },
4: { file: "./out/image04_tooling-patterns.png",
alt: "Tooling patterns: CRM-native, Enablement suite, Autonomous SDR" }
};
const content = await fs.readFile("./article.txt", "utf8");
const html = content.replace(
/^Image\s*#(\d+)\s*—.*(?:\nAlt:\s*(.*))?/gmi,
(_, n, alt = "") => {
const info = map[Number(n)]; if (!info) return "";
const a = (alt || info.alt).trim();
return `\n<figure style="margin:24px 0;">
<img src="${info.file}" alt="${a}" style="max-width:100%;height:auto;" />
<figcaption style="font-size:0.9em;color:#666;">${a}</figcaption>
</figure>\n`;
}
);
await fs.writeFile("./article.html", html, "utf8");
4) WordPress publisher (upload PNGs, create post)
import fs from "fs/promises"; import dotenv from "dotenv"; dotenv.config();
const base = process.env.WP_BASE_URL.replace(/\/+$/,"");
const auth = "Basic " + Buffer.from(`${process.env.WP_USER}:${process.env.WP_APP_PASSWORD}`).toString("base64");
async function uploadMedia(p) {
const b = await fs.readFile(p);
const r = await fetch(`${base}/wp-json/wp/v2/media`, {
method: "POST",
headers: {"Authorization": auth, "Content-Type":"image/png", "Content-Disposition":`attachment; filename="${p.split('/').pop()}"`},
body: b
});
if (!r.ok) throw new Error(await r.text());
return r.json();
}
let html = await fs.readFile("./article.html","utf8");
for (const p of ["./out/image02_agents-vs-copilot-vs-rpa.png","./out/image03_funnel-lift-points.png","./out/image04_tooling-patterns.png"]) {
const m = await uploadMedia(p); html = html.replaceAll(p, m.source_url);
}
const post = await fetch(`${base}/wp-json/wp/v2/posts`, {
method: "POST",
headers: {"Authorization": auth, "Content-Type":"application/json"},
body: JSON.stringify({ title: process.env.WP_POST_TITLE || "Draft from automation", content: html, status: process.env.WP_POST_STATUS || "draft" })
});
if (!post.ok) throw new Error(await post.text());
5) n8n workflow (three Execute Command nodes)
- Node 1:
npm ci && npx playwright install chromium
(first run) - Node 2:
node napkin-bot.js
- Node 3:
node assemble-article.js && node publish-wp.js
n8n’s Execute Command node is the right fit; if your image is Alpine, extend it to include any needed tools.
Visual Representation of AI Agents vs Executable Automation: Shipping Napkin Visuals to WordPress
From agent-mode roadblocks to shipping: watch AI agents hit export limits, then see headless Playwright + n8n generate Napkin-style visuals (PNG/WebP) and auto-publish to WordPress via REST—zero copy edits, exact placement.
Results & Why This Scale
- Napkin look, zero manual export: Headless Playwright automation preserves Napkin’s visual style and reliably captures PNG downloads.
- Editorial integrity: Article text stays unchanged; images land exactly where prompts appear—true content operations automation.
- Repeatable & schedulable: n8n runs on demand or a cron; swap prompts and rerun for future posts.
- Vyrade advantage: Plugs your intent into a composer + reliability layer with clear rationale, exports, and diagnostics; then lets your chosen orchestrator execute.
FAQ
Q: Why not rely on “agent mode” alone?
A: In restricted environments, agents can’t finalize Export PNG (blocked downloads/clipboard, no extensions). Headless Playwright automation is purpose-built for download events and file persistence—exactly what we need.
Q: Is Vyrade an orchestrator?
A: No. Vyrade is the planner/composer and reliability layer that turns your intent into a workflow plan (with confidence/coverage) and exports to n8n/Make/Zapier or agent-only paths.
Q: Can this expand beyond Napkin + WordPress?
A: Yes—Vyrade’s planner can suggest different connectors, and the same Playwright pattern works for other UI-bound tools; the publisher step already uses standard WordPress REST.
Talk with Vyrade about turning ambiguous editorial intents into exportable, reliable workflows that your team can run in n8n (or your tool of choice). Start with the exact “Prompts → images → WordPress” pipeline and scale from there.