Appearance
Marketing content generation
Two flows in one recipe.
Reactive: a marketer drops assets (images, brand-voice doc, product screenshots, transcripts) into chat with a one-line brief. The agent pulls the right skills from skills.sh, drafts a script in the brand voice, generates voiceover with ElevenLabs, renders a Remotion video, and returns a ready-to-post bundle.
Proactive: every morning at 06:00, a scheduled task walks the knowledge graph for fresh signal — new GitHub releases, customer wins from HubSpot, viral support threads in Slack — and pitches 3 concrete content ideas in #marketing-ideas with a "build it" button next to each.
15MarketingMarketing content generation
Context Graph tribal knowledge
brand voice · prior posts · rejected ideas · voice IDs
Sources
Figma
Remotion
ElevenLabs
brief + assets
Agentcy
Agentcy
Content agent + skills
video bundle
Output
Video
+ scripts
At a glance
- Inputs: dropped assets + brief (chat) or the Knowledge Graph + skills.sh registry (cron)
- Trigger: chat message with attachments or cron daily 06:00 UTC
- Output: MP4 video + script.md + social copy + ready-to-post snippet pack — all to Drive/Slack
- Gates: drafts are auto; publishing to public surfaces requires approval
Stack
| Layer | What we use |
|---|---|
| Asset intake | Chat message attachments, Google Workspace Drive folder, Figma for design tokens |
| Reasoning | Agent loop with skills — fetched dynamically from skills.sh registry |
| Voiceover | ElevenLabs — 4 tools (text-to-speech, list voices, voice settings, usage) |
| Video render | Remotion inside a CIAB sandbox — bundled slideshow / intro / graph-recap templates or a Git project |
| B-roll | Runway AI — text→video, image→video, text→image |
| Distribution | Slack, Drive, optional CMS write-back |
| Scheduling | Cron task for the proactive flow |
| Memory | The agent remembers your brand voice decisions, voice IDs, and previously-rejected ideas so it doesn't suggest them again |
Skills powering the recipe
The agent doesn't ship with marketing knowledge baked in — it pulls skills from skills.sh on demand using search_skills_registry + fetch_registry_skill, or installs them up-front via the Skills page. Real skills with real install counts you can use today:
| Skill | Source | Installs | Use for |
|---|---|---|---|
copywriting | coreyhaines31/marketingskills | 79k+ | Headlines, body copy, CTAs |
copy-editing | coreyhaines31/marketingskills | 47k+ | Tightening drafts |
social-content | coreyhaines31/marketingskills | 54k+ | Platform-specific framing |
seo-audit | coreyhaines31/marketingskills | 88k+ | Keyword + structure checks |
marketing-psychology | coreyhaines31/marketingskills | 58k+ | Hooks, persuasion patterns |
script-writer | ailabs-393/ai-labs-claude-skills | — | Video / shorts scripts |
brand-voice / brand-voice-enforcement | anthropics/knowledge-work-plugins | — | Stays-on-tone editor pass |
youtube-thumbnail-design | infsh-skills/skills | 3.9k+ | Thumbnail composition |
programmatic-seo | coreyhaines31/marketingskills | 52k+ | Bulk landing-page templates |
The recipe enables a small core set in the system prompt and lets the agent fetch others on demand within the prompt budget (default 16 000 chars).
What you'll build — Reactive flow
A marketer drops a folder of assets and a brief into the agent. The agent:
- Inventory — lists what was uploaded (logo, 4 product screenshots, a customer-call transcript, a brand-voice PDF). Acknowledges each.
- Brief understanding — confirms the format ("30s vertical Instagram Reel"), audience ("CTOs at fintechs"), and the one thing it should land.
- Skill fetch —
search_skills_registry({ query: "vertical reel script CTO"})→fetch_registry_skill(script-writer)+brand-voice-enforcement. Agent confirms char budget. - Script draft — written in the brand voice, with timecodes for visuals + voiceover.
- Voice —
elevenlabs_list_voices→ user picks (or recipe defaults to a remembered voice).elevenlabs_text_to_speechproduces the VO track. - B-roll — for any timecode without a provided asset, agent calls
runway_text_to_imageorrunway_text_to_videofrom prompts grounded in the script. - Render — Remotion source is the
slideshowtemplate (or a Git project the team maintains), filled with assets + VO + brand tokens from Figma. CIAB renders MP4. - Bundle — drops the MP4, the script.md, a social copy pack (LinkedIn / Twitter / IG caption variants from
social-contentskill), and a thumbnail (youtube-thumbnail-design).
shaked [drops 5 files] make a 30s vertical reel for CTOs about our new
observability feature. Brand voice doc is in there. Audience is
SREs at series-B fintechs.
agentcy ✅ Inventory
- logo.svg
- 3 product screenshots (panel-rendering)
- customer-call.txt (Sumant from Lattix, 14 min, June 8)
- brand-voice-v3.pdf
⚙ Fetching skills
✓ script-writer (1,847 chars)
✓ brand-voice-enforcement (2,103 chars)
✓ social-content (1,420 chars)
Budget: 5,370 / 16,000 chars
📝 Script draft (v1) — 28s, 6 scenes
[00:00] Hook: "your dashboards are lying to you" (logo wipe)
[00:03] Pain: 3 quick clips of frustrated SRE staring at tabs
...
Continue? Y to render, or comment to revise.
shaked good but tighten 00:18-00:24, and use Sarah's voice
agentcy ⚙ Tightening, switching to voice "Sarah" (id: pNInz...)
✓ Revised script
✓ ElevenLabs render: 28.4s VO (eleven_multilingual_v2)
✓ Runway b-roll: 2 clips for SRE-pain scenes
⚙ Remotion render (CIAB sandbox)
→ 1080x1920 H264 30fps
→ 28.4s · 12.4 MB
✅ Done
🎬 reel-observability-2026-04-26.mp4
📄 script.md
📱 social-pack.md (LI, X, IG)
🖼 thumbnail.png
Publish? (sends to #marketing-publish for approval)What you'll build — Proactive flow
A scheduled task runs each morning. It walks the Knowledge Graph for activity that's worth talking about and pitches content ideas:
yaml
name: marketing-ideas-daily
schedule: "0 6 * * *"
realm: marketing
agent: content-strategist
enabled_skills:
- marketing-psychology
- social-content
- copywriting
prompt: |
Walk the knowledge graph for the last 24 hours. Surface candidates worth turning into content:
1. graph.search({ realm: ["product","gtm"], since: "24h" })
— new GitHub releases, merged PRs touching customer-facing features
2. hubspot.search_deals({ stage: "closed-won", since: "7d" })
— fresh customer wins (anonymize unless tagged "case-study-ok")
3. slack.list_messages({ channels: ["#wins","#cs-leads"], since: "24h" })
— viral or notable threads
4. grafana_query — usage spikes worth a "scaling lessons" post
For each candidate, draft:
- hook (≤ 12 words)
- 1-line angle
- format suggestion (reel, blog, thread)
- which skills you'd pull and why
Post 3 picks (NOT all candidates — be opinionated) to #marketing-ideas
with a 🚀 reaction button. Reaction → builds the content end-to-end via
the reactive flow above.
Memory:
- Read `rejected_ideas` and `recent_topics` to avoid repeats and over-coverage.
- On 🚀 react, write the resulting brief back as `published_idea`.What lands in #marketing-ideas at 06:05:
agentcy 🌅 3 ideas for today (Mon Apr 26)
1️⃣ "we shipped panel rendering. it's faster than your dashboard."
angle: real numbers from prod metrics — concrete, no hype
format: 30s vertical reel + LinkedIn thread
skills: copywriting, marketing-psychology, video-script-writer
evidence: PR #2103 (merged Sun), Grafana p99 280ms→190ms
🚀 build it
2️⃣ "Lattix went from 4 tools to 1 in 3 weeks"
angle: customer-side win, anonymized unless permission
format: 90s case-study video + Twitter thread
skills: brand-voice, social-content
evidence: closed-won deal · Sumant call transcript
🚀 build it
3️⃣ "the observability tax: how we cut our Datadog bill 40%"
angle: contrarian engineering POV, evergreen
format: long blog post + LinkedIn carousel
skills: copywriting, programmatic-seo, seo-audit
evidence: Internal cost-watch dashboard, FinOps recipe data
🚀 build itA 🚀 reaction triggers the reactive flow with the chosen idea as the brief — the agent goes from idea to ready-to-publish bundle without anyone touching keys.
Prerequisites
1 · ElevenLabs
bash
curl -X POST $API/api/v1/sources \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{
"name": "elevenlabs-prod",
"connector": "elevenlabs",
"realm": "marketing",
"config": { "api_key": "sk_..." }
}'Test with elevenlabs_list_voices to make sure your voices show up.
2 · Remotion + CIAB
The Remotion connector renders inside a CIAB sandbox. Make sure CIAB is enabled (AGENTCY_FEATURES_CIAB=true) and the EC2 runtime or local Docker runtime is configured.
bash
curl -X POST $API/api/v1/sources \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{
"name": "remotion-marketing",
"connector": "remotion",
"realm": "marketing",
"config": {
"project": { "kind": "git", "repo": "acme/marketing-remotion", "ref": "main" },
"render_defaults": { "fps": 30, "codec": "h264", "resolution": "1080p" }
}
}'The git project type points at your team's Remotion compositions. The bundled slideshow / intro / graph-recap templates work as starters but a custom Git project quickly pays for itself — that's where your brand-tuned compositions live.
3 · Runway (optional, for B-roll)
bash
curl -X POST $API/api/v1/sources \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{
"name": "runway-marketing",
"connector": "runway",
"realm": "marketing",
"config": {
"api_key": "rw_...",
"default_model": "gen3",
"default_duration": 4,
"default_ratio": "9:16"
}
}'4 · Figma (optional, for brand tokens)
If your brand uses Figma variables for colors / typography, the Figma connector exposes them so Remotion compositions stay on-brand without manual color hex juggling.
5 · Skills configured
In Settings → Skills:
skills_dynamic_search_enabled: true— lets the agent fetch from skills.sh on demandskills_max_prompt_chars: 16000(default is fine for marketing)skill_enablement_policy: prompt-user— so dynamic skills require approval the first time
Pre-install the core pack via the Skills → Browse tab:
coreyhaines31/marketingskills— the workhorse packanthropics/knowledge-work-plugins/brand-voice(orbrand-voice-enforcement)ailabs-393/ai-labs-claude-skills/script-writer
Worked example — the policy
rego
# policies/content-generation.rego
package agentcy
# Drafting and rendering: free.
default allow := false
allow if {
input.tool in {
"elevenlabs_list_voices", "elevenlabs_get_voice_settings",
"elevenlabs_text_to_speech", "elevenlabs_get_usage",
"remotion.render", "remotion.list_compositions",
"runway_text_to_video", "runway_image_to_video", "runway_text_to_image",
"figma.get_file", "figma.get_components", "figma.get_styles",
"google_drive.list", "google_drive.read_file", "google_drive.upload",
"graph.search", "graph.related",
"scenario.create",
"search_skills", "enable_skill", "disable_skill", "list_enabled_skills",
"search_skills_registry", "fetch_registry_skill",
}
}
# Publishing to public surfaces requires explicit approval.
allow if {
input.tool in {
"slack.post_message",
"twitter.create_post",
"linkedin.create_post",
"youtube.upload_video",
}
input.approval.granted
}
# Rate-limit ElevenLabs to avoid runaway TTS costs.
deny[msg] if {
input.tool == "elevenlabs_text_to_speech"
count(input.recent_calls_60s) > 10
msg := "rate limit: 10 ElevenLabs renders/min — batch your script first"
}
# Don't publish content referencing a closed-lost deal as a customer win.
deny[msg] if {
input.tool in {"twitter.create_post", "linkedin.create_post"}
some claim
claim := input.args.claims[_]
claim.kind == "customer_reference"
claim.deal_stage == "closed-lost"
msg := "cannot reference a closed-lost deal as a customer win"
}Memory — the agent gets sharper over time
rust
// Agent decides these are durable
remember("brand_voice_pref", "voiceover: Sarah (pNInz...) for product, Dan for technical")
remember("rejected_idea", "the 'we cut Datadog 40%' angle — legal flagged comparative claims")
remember("recent_topic", "panel rendering shipped Apr 24 — covered in 2 reels, 1 blog. cooldown until May.")
remember("published_idea", "Lattix case study — IG reel + LI carousel, posted Apr 26")Recall (stage 2a of the Agent Loop) means tomorrow's proactive run won't pitch the panel-rendering angle again, will offer Sarah's voice for the product reel, and won't re-suggest the Datadog comparison.
Distribution
Three modes, opt in:
- Drive bundle — MP4 + script.md + social-pack.md uploaded to a Drive folder per campaign. Manual posting from there.
- Slack approval channel — bundle dropped in
#marketing-publish; reactions trigger publication: 📱 → IG, 🐦 → X, 💼 → LinkedIn. - CMS / scheduler write-back — push to Buffer, Hootsuite, or your own CMS via the OpenAPI connector.
What good looks like
A reactive run completes in 2-4 minutes for a 30s vertical reel: ~10s for skill fetch, ~30s for script draft, ~20s for ElevenLabs TTS, ~60s for Runway b-roll, ~30s for Remotion render. The marketer's only job: read the script, react to publish.
A proactive day looks like 3 thoughtful suggestions at 06:05 grounded in real activity, with a 1-click 🚀 path to a finished bundle. Over time, memory + audit log shows which suggestions actually shipped — feeds back into the strategist's prompt.
Variations
- Long-form blog mode — swap Remotion render for a Markdown bundle + Hero image (Runway). Same skills, different output. Good for evergreen SEO via
programmatic-seo. - Per-channel sub-agents — dispatch sub-agents (one per platform: IG, X, LinkedIn, YouTube). Each has its own skill set and tone. Parent agent assembles the campaign brief.
- Voice-first review — bind to the voice channel. Marketer drives via voice while reviewing generated drafts on a tablet.
- Internal comms variant — same recipe, different realm. Pitch internal-comms videos (org change announcements, security awareness) to People & Comms instead of GTM.
- Customer-success replay — auto-generate a "you shipped this in 30 days" video for new customers from their actual usage data — sales enablement gold.
Troubleshooting
- Skills budget exhausted. The agent will refuse to enable an additional skill — disable an unneeded one (
disable_skill) or bumpskills_max_prompt_charsin Settings. - ElevenLabs voice not found.
elevenlabs_list_voicesreturned only premade voices. Custom voices live under your account — the API key needs the right scope, and the voice has to be cloned into your library first. - Remotion render fails with "module not found". The Git project at
repo:refis missing a dependency. Check the CIAB sandbox build logs —npm installruns before render, log lines are taggedremotion.install. - B-roll looks generic. Runway's
gen3model needs specific prompts. The agent's default is conservative — add ab-roll-promptingskill to the active set or passprompt_style: "specific"in the args. - Proactive task fires but says "no candidates". The graph queries returned empty — likely no fresh activity in the realms it's looking at, or the cron's
sincewindow is too narrow. Widen tosince: "72h"for a sanity check. - The agent keeps re-pitching the same idea. Memory not writing. Check
agentcy-memorylogs —remember(rejected_idea, ...)should appear after each rejection. If it isn't, the agent isn't being told to write rejections; add it to the prompt.
What's deferred
- ❌ Auto-publishing without human approval — every public post requires explicit approval in v1
- ❌ Native Buffer/Hootsuite connectors — use OpenAPI connector for now
- ❌ Live A/B testing of generated content — analytics flow back is on the roadmap
- ❌ Cursor/Codex sub-agents inside CIAB — Claude Code only today
Next
- Concept: Skills — how the prompt budget works, skills.sh registry
- Connector: Remotion — bundled templates, Git projects
- Connector: ElevenLabs — voice cloning, voice settings
- Connector: Runway — text/image-to-video
- Concept: Tasks & Workers — the proactive cron
- Recipe: Executive Reporting — sibling proactive recipe over the same graph