# Build a campaign from a brief with a Claude Code skill

A Claude Code skill that turns a short brief into a draft campaign with its sequence, an AI field and the Setter, runs the preflight, and stops before launch.

Works with: Claude Code.

MCP tools used (https://docs.versionseven.ai/guides/connect-your-ai):

- `campaigns_list` (read) List the organization's campaigns.
- `list_sequence_recipes` (read) The Playbook's example sequences, by channel and use case.
- `get_sequence_template` (read) A blank skeleton or a worked example sequence.
- `create_campaign` (write) Create a draft campaign.
- `update_sequence` (write) Replace the whole sequence.
- `create_personalization_field` (write) Add an AI field.
- `sender_accounts` (read) The connected LinkedIn and email accounts.
- `check_domain_dns` (read) Check any domain's SPF, DKIM and DMARC.
- `assign_sender_accounts` (write) Set which senders send for the campaign.
- `update_appointment_setter` (write) Configure the Appointment Setter.
- `campaign_preflight` (read) The activation checks, without activating.
- `activate_campaign` (write) Run the preflight and activate.

MCP prompts used: `plan_campaign`, `write_sequence`.

MCP resources used: `victoria://guides/messaging-rules`.

A campaign is a dozen decisions in a fixed order: who it's for, which channels, what the sequence says, which AI field to write per lead, which senders, what the Setter may say. The server's `plan_campaign` and `write_sequence` prompts already encode that order for a connected assistant. This recipe wraps them in a Claude Code skill, so a brief typed as `/victoria-campaign …` becomes a draft campaign that has passed the preflight and is waiting for one word from you. It never activates on its own.

## Before you start

- Claude Code with the Victoria AI MCP server added and signed in:

```bash
claude mcp add --transport http victoria https://api.versionseven.ai/mcp --scope user
```

then `/mcp` inside Claude Code to complete the sign-in, choosing **Read and write**. Or, for a machine that shouldn't hold a sign-in, add `--header "Authorization: Bearer $VICTORIA_API_KEY"` with a key that has `campaigns:write` and `accounts:read`. [Connect your AI](https://docs.versionseven.ai/guides/connect-your-ai#connect-claude-code) covers both.

- At least one connected sender in the workspace. The skill assigns senders; it can't connect one.

## The skill

Save this as `.claude/skills/victoria-campaign/SKILL.md` in a project (or `~/.claude/skills/victoria-campaign/SKILL.md` to have it everywhere):

```markdown
---
name: victoria-campaign
description: Build a Victoria AI outbound campaign from a brief, to the house messaging rules, and stop before launch. Use when asked to create, draft or set up an outbound campaign.
disable-model-invocation: true
allowed-tools: mcp__victoria
---

Build a Victoria AI campaign from this brief, then stop before activating it.

Brief: $ARGUMENTS

Work in this order, and show me each result before the next step:

1. Read the resource `victoria://guides/messaging-rules` first. Every message you write follows it.
2. Call `campaigns_list` and tell me if a campaign with a similar name or audience exists. If so, ask whether to continue.
3. From the brief, write the audience as lead-database filters (titles, seniority, locations, industries, company size) and a one-line offer. Ask me one yes-or-no question if the brief leaves the audience open; otherwise don't ask.
4. Call `sender_accounts`. If the brief names channels, use them; otherwise pick multichannel when there is an active LinkedIn sender and a mailbox, LinkedIn-only or email-only when there is one kind. For a mailbox, call `check_domain_dns` on its domain and tell me if SPF, DKIM or DMARC is missing.
5. Call `list_sequence_recipes` filtered by those channels, pick the closest example, and fetch it with `get_sequence_template`. Keep its shape (steps, delays, branches). Rewrite every message for this audience and offer. Use at most two AI variables, each named in snake_case.
6. Call `create_campaign` with the name, description and audience filters; then `update_sequence` with the sequence; then `create_personalization_field` for each AI variable, with instructions that say what to look for and a fallback that reads well on its own; then `assign_sender_accounts` with the senders from step 4.
7. If the brief mentions booking meetings or a calendar link, call `update_appointment_setter` with mode autonomous, goal book_meeting, the link, the company name, a two-line campaign description and a knowledge base of facts taken only from the brief. Leave it off otherwise.
8. Call `campaign_preflight`. For each failing check, fix what you can with the tools above and run it again. Report any check you can't fix and what I need to do in the app.
9. Stop. Print the campaign's name and id, the sequence as a numbered list with channel and delay per step, the AI fields, the senders, and the preflight result. Then ask: "Activate it?" Only if I answer yes, call `activate_campaign`; if the preflight reported warnings, show them to me and ask again before passing ack_warnings.

Never call `activate_campaign` before I've said yes in this conversation. Never add leads from the lead database unless the brief asks for it, and quote the credit cost before you do.
```

Then, in Claude Code:

```text
/victoria-campaign Heads of Sales and VPs of Sales at US B2B SaaS companies with 50 to 300 employees. We sell an onboarding tool that cuts new-rep ramp time from 90 to 45 days. Multichannel. Book meetings on https://cal.com/jordan/intro.
```

## What happens

1. The skill reads the house messaging rules from the server (the same resource the in-app Copilot reads), so it knows the sequence format, the merge fields and what a connection note may and may not say.
2. It drafts the audience and the offer, shows them, and asks at most one question.
3. It picks a Playbook example sequence that matches the channels, keeps its shape and rewrites every message for your buyers. Each tool that writes (`create_campaign`, `update_sequence`, `create_personalization_field`, `assign_sender_accounts`, `update_appointment_setter`) is one you approve in Claude Code as it's called, because the server marks them as writes.
4. It runs `campaign_preflight`, the same readiness checks as the Activate button, and fixes what the tools can fix: a blank step, a variable without a field, a sender missing. What it can't fix (a sender to connect, a DNS record, a subscription) it reports with the page in the app to do it on.
5. It stops and shows you the whole campaign. `activate_campaign` runs only after you say yes, and warnings get a second look before `ack_warnings`.

`disable-model-invocation: true` means the skill runs only when you type `/victoria-campaign`, never because Claude decided a conversation looked like a campaign brief. `allowed-tools: mcp__victoria` pre-approves every tool of the server added as `victoria` for the skill's turn, so you aren't asked about each read; Claude Code still confirms the writes, which the server marks as such. In a conversation outside the skill, `@victoria:victoria://guides/messaging-rules` attaches the same messaging-rules resource by hand.

## Adapting it

- **A house style**: add a line under step 5 with your rules ("sign off as Jordan", "no exclamation marks", "always offer the teardown first"). The messaging-rules resource stays the floor.
- **A fixed sender set**: replace step 4 with the sender ids to use, from `sender_accounts` once.
- **Leads in the brief**: add a step after 6 that calls `import_leads` with a list you paste, or `find_leads` and `add_leads_from_search` for the lead database; the latter two spend credits and quote the cost first, capped at 5,000 credits in any 24 hours.
- **A team**: commit the skill under `.claude/skills/` in a shared repo and everyone with Claude Code and the connector has the same procedure.

## What to expect

- Campaigns are created as drafts; nothing sends until activation, and activation always runs the preflight.
- `update_sequence` replaces the whole sequence; the server validates it (step types, a conditional after every connection request, LinkedIn messages only on the connected branch, at most 40 steps) and refuses with the failing rule rather than saving a broken one.
- An AI field needs a fallback: it's what a lead gets when the model can't find anything to say. [Personalization instructions](https://docs.versionseven.ai/playbook/personalization-instructions) has patterns that work.
- The skill uses about fifteen tool calls per campaign, well inside 120 a minute.

## Next steps

- [Run a weekly campaign review from Claude or ChatGPT](https://docs.versionseven.ai/cookbook/weekly-review-with-claude), for the week after launch.
- [Check senders and runway on a schedule with Claude Code](https://docs.versionseven.ai/cookbook/scheduled-claude-code-check), the same connection, unattended.
- [Choosing a sequence shape](https://docs.versionseven.ai/playbook/choosing-a-sequence-shape) for which example the skill should start from.
