Create a new AI-generated email campaign from a text prompt.
Do not call until the user has confirmed both which images to include (L1) and which brand kit to apply (L2) on the layout path. Ask both in one message and wait; picking either on the user's behalf is wrong even when generation succeeds. They are the ONLY questions ever asked. Everything the generator produces itself — the campaign name, subject, headline, body copy, offer, discount, dates, urgency, tone, CTA — is NEVER asked about, however sparse the prompt: "Create a campaign about our summer sale." is already complete. The moment images and brand kit are known the next action is this call — exactly once, never another question, and never `update_campaign afterwards: this tool names the campaign itself.
NEVER retry after this tool has been called — generation is not idempotent and a repeat call can create a duplicate campaign. On any failure, surface it and tell the user to check ActiveCampaign before starting another generation. NOT for copy or edit workflows — use copy_campaign or edit_campaign. This tool rejects the edit arguments content_change, subject_change and preheader_change: those belong to edit_campaign.
ACCOUNT CONTEXT — never browse for it: Do NOT call list_contacts, list_campaigns, or list_lists to gather background context for generation — those tools render full interactive apps. When past campaigns or audience details genuinely affect the request, call get_campaign_generation_context instead. Use the interactive list tools only when the user asked to browse data or must make a visible selection.
ROUTE FIRST — before any other action:
- User wants to copy, duplicate, or clone an existing campaign unchanged
→ copy_campaign (pass source campaign ID as (past campaign id: NUMBER)). A bare copy_campaign is correct only for "copy"/"duplicate"/"clone" with no qualifier beyond a new name.
- User wants a campaign "like"/"similar to"/"based on" an existing one **with any
change of topic, tone, season, product or audience** (e.g. "like my Summer Sale campaign but for autumn") → this is NOT a bare copy. Either call this tool for a fresh campaign, or call copy_campaign and then edit_campaign on the returned campaign_id with content_change=True to rewrite the copy for the new topic. update_campaign only renames — a rename never satisfies a content change, and reporting success after renaming alone is wrong.
- User wants to edit/update an existing campaign →
edit_campaign.
- User picks or names a specific template → TEMPLATE PATH (go to T1).
- All other "create new" requests → LAYOUT PATH (go to L1).
LAYOUT PATH — complete all three steps, confirm each with user, then call:
L1. IMAGES (REQUIRED — never skip for layout creation): Call search_content_manager_images with a keyword from the campaign topic. Present image names and thumbnails; ask user which to include (max 7). Zero results → call again with query="" limit=10; show recent uploads; ask. Duplicate filenames → STOP; show each as [filename](url) (added date); end with "Please select which image you'd like to use."; wait for the selection. Position: "main" = hero slot, "random" = engine places it. Nothing else.
L2. BRAND KIT (REQUIRED — always fetch, always confirm): Call list_brand_kits; present every kit, recommend the is_primary=True one and ask the user to confirm. Pass the confirmed uuid as brand_kit_id.
L3. URL CLASSIFICATION (automatic — only intervene on ambiguity): Pass the user's prompt verbatim — URL detection is automatic from prompt content. If user provides ONLY a URL with no other context → ask: "Should I write the email based on this page's content, or use this link for the button?" Content URL (product page, article, landing page to pull copy from) → call summarize_url; pass returned summarization_uuid to this tool. CTA-only URL (button destination, no content to extract) → pass directly as cta_url; skip summarize_url. No URL in prompt → skip this step.
L4. TONE (never ask): pass tone only when the user named one verbatim (e.g. "professional", "casual", "urgent"); otherwise omit it.
TEMPLATE PATH — complete all steps, confirm each with user, then call:
T1. TEMPLATES (REQUIRED — list before calling): Call list_campaign_templates. Present template names; ask which to use and wait — never call before that answer. Pass the chosen id as template_id. NEVER pass brand_kit_id on this path — template design takes precedence. If user asks to apply a full brand kit on the template path, refuse: brand kit application is not supported on the template path. NEVER pass tone on this path either — the from-template endpoint doesn't support tone validation; it is silently dropped if provided.
T2. IMAGES (optional — only if user asks): Call search_content_manager_images only when user explicitly mentions images. Same zero-results fallback and dedup rules as L1 apply. Position can be any freeform label the user provides (verbatim).
CALL — as soon as the applicable steps above are confirmed; any further question instead of this call is a defect: Call this tool ONCE per request, with all gathered inputs. A later message that merely confirms a choice already acted on is not a second campaign — never generate twice for one request. Pass user's exact words as prompt — NEVER rephrase, rewrite, or expand. summarization_uuid is REQUIRED whenever summarize_url was called earlier in this conversation: pass the summarization_uuid it returned verbatim. Without it the summarization is discarded and the campaign is written from the summary text instead of the scraped page. images must carry the url values from search_content_manager_images. When the user names an image by file name (e.g. "beach-summer.jpg"), look that name up in the earlier search result and pass its url — a bare file name is rejected.
Returns a request_id immediately without waiting for generation to finish. A campaign app UI polls poll_campaign_generation_status with it to drive a live progress bar — do NOT poll yourself then. With no app UI, poll it yourself until status is success` and present the campaign.